offsetDecoder<T> function

Decoder<T> offsetDecoder<T>(
  1. Decoder<T> decoder,
  2. OffsetConfig config
)

Moves the offset of a given decoder before and/or after decoding.

The pre-offset function determines where decoding should start, while the post-offset function adjusts where the next decoder should continue.

Implementation

Decoder<T> offsetDecoder<T>(Decoder<T> decoder, OffsetConfig config) {
  (T, int) readImpl(Uint8List bytes, int preOffset) {
    int wrapBytesImpl(int offset) => _modulo(offset, bytes.length);

    final newPreOffset = config.preOffset != null
        ? config.preOffset!(
            PreOffsetScope(
              bytes: bytes,
              preOffset: preOffset,
              wrapBytes: wrapBytesImpl,
            ),
          )
        : preOffset;
    assertByteArrayOffsetIsNotOutOfRange(
      'offsetDecoder',
      newPreOffset,
      bytes.length,
    );

    final (value, postOffset) = decoder.read(bytes, newPreOffset);

    final newPostOffset = config.postOffset != null
        ? config.postOffset!(
            PostOffsetScope(
              bytes: bytes,
              preOffset: preOffset,
              wrapBytes: wrapBytesImpl,
              newPreOffset: newPreOffset,
              postOffset: postOffset,
            ),
          )
        : postOffset;
    assertByteArrayOffsetIsNotOutOfRange(
      'offsetDecoder',
      newPostOffset,
      bytes.length,
    );

    return (value, newPostOffset);
  }

  return switch (decoder) {
    FixedSizeDecoder<T>() => FixedSizeDecoder<T>(
      fixedSize: decoder.fixedSize,
      read: readImpl,
    ),
    VariableSizeDecoder<T>() => VariableSizeDecoder<T>(
      read: readImpl,
      maxSize: decoder.maxSize,
    ),
  };
}