getPatternMatchDecoder<TTo> function

Decoder<TTo> getPatternMatchDecoder<TTo>(
  1. List<PatternMatchDecoderEntry<TTo>> patterns
)

Returns a decoder that selects which variant decoder to use based on pattern matching.

This decoder evaluates the byte array against a series of predicate functions in order, and uses the first matching decoder to decode the value.

final decoder = getPatternMatchDecoder<int>([
  ((bytes) => bytes.length == 1, getU8Decoder()),
  ((bytes) => bytes.length == 2, getU16Decoder()),
  ((bytes) => bytes.length <= 4, getU32Decoder()),
]);

decoder.decode(Uint8List.fromList([0x2a]));            // 42 as u8
decoder.decode(Uint8List.fromList([0xe8, 0x03]));      // 1000 as u16
decoder.decode(Uint8List.fromList([0xa0, 0x86, 0x01, 0x00])); // 100000 as u32

Throws a SolanaError with code SolanaErrorCode.codecsInvalidPatternMatchBytes if the byte array does not match any of the specified patterns.

See also: getPatternMatchEncoder, getPatternMatchCodec.

Implementation

Decoder<TTo> getPatternMatchDecoder<TTo>(
  List<PatternMatchDecoderEntry<TTo>> patterns,
) {
  int getIndexFromBytes(Uint8List bytes, int offset) {
    final index = patterns.indexWhere((p) => p.$1(bytes));
    if (index == -1) {
      throw SolanaError(SolanaErrorCode.codecsInvalidPatternMatchBytes, {
        'bytes': bytes,
      });
    }
    return index;
  }

  final variants = patterns.map((p) => p.$2 as Decoder<Object?>).toList();
  final fixedSize = _getFixedSize(variants);

  (TTo, int) readImpl(Uint8List bytes, int offset) {
    final index = getIndexFromBytes(bytes, offset);
    final (value, newOffset) = variants[index].read(bytes, offset);
    return (value as TTo, newOffset);
  }

  if (fixedSize != null) {
    return FixedSizeDecoder<TTo>(fixedSize: fixedSize, read: readImpl);
  }

  final maxSize = _getMaxSize(variants);
  return VariableSizeDecoder<TTo>(read: readImpl, maxSize: maxSize);
}