Class PipeReaderExtensions
- Namespace
- ShapeShift
- Assembly
- ShapeShift.dll
Extension methods for PipeReader that drive incremental, boundary-scanned value decoding.
public static class PipeReaderExtensions
- Inheritance
-
PipeReaderExtensions
- Inherited Members
Remarks
These members are format-neutral: they know nothing about JSON or MessagePack syntax. Each format package supplies an IValueBoundaryScanner implementation and a synchronous decode delegate; this class supplies the shared loop that buffers input from a PipeReader a chunk at a time, invoking the decode delegate exactly once, only after a complete top-level value has been confirmed present.
Methods
ReadValueAsync<T>(PipeReader, IValueBoundaryScanner, Func<ReadOnlySequence<byte>, T?>, long, CancellationToken)
Reads and decodes the next complete top-level value from a pipe, buffering only as much input as that one value requires.
public static ValueTask<(bool HasValue, T? Value)> ReadValueAsync<T>(this PipeReader reader, IValueBoundaryScanner scanner, Func<ReadOnlySequence<byte>, T?> decode, long maxBufferedSize = 9223372036854775807, CancellationToken cancellationToken = default)
Parameters
readerPipeReaderThe pipe to read from.
scannerIValueBoundaryScannerA scanner that recognizes the boundary of one top-level value in the format being read. The same instance may be reused across repeated calls (e.g. to read a sequence of values from one pipe).
decodeFunc<ReadOnlySequence<byte>, T>Invoked synchronously with the exact bytes of one complete, buffered top-level value in order to produce
T. This runs before the underlying buffer segments are released back to the pipe, so it must not retain ReadOnlySequence<T> or any span/memory derived from it beyond its own return.maxBufferedSizelongThe maximum number of bytes this method will retain, at any one time, while still waiting to resolve one top-level value. Bytes proven to precede the value entirely (such as insignificant whitespace separating NDJSON-style entries) are released as soon as the scanner accounts for them (see TryScan(in ReadOnlySequence<byte>, bool, out SequencePosition, out SequencePosition)) and so do not count against this limit; once a value has begun, though, every byte of it must remain available for the eventual decode step, so this limit bounds the size of the value itself -- including one very large scalar token, or a value that never completes at all (e.g. one with a corrupt or hostile, effectively unbounded length header).
cancellationTokenCancellationTokenA cancellation token.
Returns
- ValueTask<(bool HasValue, T Value)>
A tuple whose
HasValueis true and whoseValueis the decoded value, if a complete top-level value was read; otherwiseHasValueis false because the pipe reached its end before any further value began (a graceful end of a sequence of values).
Type Parameters
TThe type of value to produce.
Exceptions
- DecoderException
Thrown when the pipe ends in the middle of a value, or when
scannerdetects malformed input.- ShapeShiftSerializationException
Thrown when a single value would require buffering more than
maxBufferedSizebytes.