Class JsonValueBoundaryScanner
- Namespace
- ShapeShift.Json
- Assembly
- ShapeShift.Json.dll
Recognizes the boundary of one complete, top-level JSON value using Utf8JsonReader's own incremental parsing support, without buffering more than that one value requires.
public sealed class JsonValueBoundaryScanner : IValueBoundaryScanner
- Inheritance
-
JsonValueBoundaryScanner
- Implements
- Inherited Members
Remarks
Utf8JsonReader already supports incremental parsing of a growing buffer via JsonReaderState resumption, so this scanner does not reimplement any JSON grammar. It only drives the reader through exactly the calls required to recognize "one value has been fully read", which takes a small amount of care:
- TrySkip() requires the reader to already be positioned on a token; called on a reader that has never read a token (None) it returns true immediately without consuming anything, which would look like "boundary found at offset zero" if called blindly. So this type calls Read() first to position on the value's first token, and only afterward considers calling TrySkip().
- Once positioned, only StartObject and StartArray require a further TrySkip() call to consume the rest of the container; every other token type is itself already a complete, self-contained value after the single Read().
- Resuming a saved JsonReaderState correctly restores TokenType, so the same two checks above can simply be repeated on every call without tracking extra state of our own.
Constructors
JsonValueBoundaryScanner(JsonReaderOptions)
Initializes a new instance of the JsonValueBoundaryScanner class.
public JsonValueBoundaryScanner(JsonReaderOptions options = default)
Parameters
optionsJsonReaderOptionsThe options that govern how the JSON is tokenized (e.g. comment handling, trailing commas).
Methods
TryScan(in ReadOnlySequence<byte>, bool, out SequencePosition, out SequencePosition)
Attempts to locate the end of the next complete top-level value at the start of buffer.
public bool TryScan(in ReadOnlySequence<byte> buffer, bool isFinalBlock, out SequencePosition end, out SequencePosition examined)
Parameters
bufferReadOnlySequence<byte>All input buffered so far and not yet consumed. Callers are expected to advance their underlying reader past
examinedafter every call (whether it returns true or false), so on the next call for the same value,bufferbegins exactly where the previous call'sexaminedleft off.isFinalBlockbooltrue if no further input will ever be appended to
buffer(the source has reached its end).endSequencePositionReceives the position, within
buffer, immediately after the complete value, if this method returns true; otherwise default.examinedSequencePositionReceives the position, within
buffer, up through which this instance guarantees it will never need to look again -- regardless of whether this call returns true or false. When this method returns true, this always equalsend. When it returns false, this isbuffer's start unless the implementation can prove the skipped-over bytes are not part of any value (for example, whitespace preceding the next JSON token) and therefore safe to discard even though the value itself has not yet been found. A caller that has reachedisFinalBlockand finds this method returns false withexaminedequal tobuffer's end may conclude that no further value begins here (a graceful end of a sequence of values), rather than that the input ended in the middle of one.
Returns
- bool
true if
buffercontains (starting at its start) one complete top-level value; false if more input is required before that can be determined.
Exceptions
- DecoderException
Thrown when the buffered input is definitely malformed.