Table of Contents

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

reader PipeReader

The pipe to read from.

scanner IValueBoundaryScanner

A 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).

decode Func<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.

maxBufferedSize long

The 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).

cancellationToken CancellationToken

A cancellation token.

Returns

ValueTask<(bool HasValue, T Value)>

A tuple whose HasValue is true and whose Value is the decoded value, if a complete top-level value was read; otherwise HasValue is false because the pipe reached its end before any further value began (a graceful end of a sequence of values).

Type Parameters

T

The type of value to produce.

Exceptions

DecoderException

Thrown when the pipe ends in the middle of a value, or when scanner detects malformed input.

ShapeShiftSerializationException

Thrown when a single value would require buffering more than maxBufferedSize bytes.