silk/json_scanner
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc.
Strict, allocation-free JSON tokens from complete slices or successive byte chunks.
When to use
Use JsonScanner to inspect one complete JSON document without building a value tree.
Use JsonScanState when bytes arrive in chunks and retain token fragments yourself.
Details
JsonScanState.step consumes at most one token per call. Spans and errors use absolute byte
offsets; a step also reports the part of the current lexeme in its supplied chunk. Strings
retain their source spelling and report whether they contain escapes. No operation allocates.
Gotchas
A number at a nonfinal chunk boundary needs another step to establish its delimiter. The
delimiter remains unconsumed. After any error the state is terminal; create a new state.
Nesting is limited to MAX_DEPTH. The scanner validates syntax, not duplicate key equality.
Examples
Scan a complete number
import silk.json_scanner {JsonScanner, JsonToken, JsonError}
import silk.result {Result}
pub fn main() -> i32 {
let mut scanner = JsonScanner.make(b"42")
let token = JsonScanner.next(&mut scanner)
return match move token {
Result<JsonToken, JsonError>.Failure {error} => 1
Result<JsonToken, JsonError>.Success {value} => match move value {
JsonToken.Number {span: _} => 0
_ => 1
}
}
}Import as JsonScanner with import silk.json_scanner { JsonScanner }.
Public declarations: 9.
MAX_DEPTH
pub const MAX_DEPTH: usizeThe maximum number of simultaneously open JSON arrays and objects.
JsonSpan
pub struct JsonSpanA half-open byte range in the complete JSON source.
Field offset
pub offset: usizeThe absolute offset of the first byte.
Field length
pub length: usizeThe number of bytes in the range.
Implementation Copy for JsonSpan
impl Copy for JsonSpanJsonReason
pub enum JsonReasonA stable category for a JSON scanner failure.
UnexpectedByte
UnexpectedByte = 0A byte cannot begin or continue the expected JSON construct.
UnterminatedString
UnterminatedString = 1A quoted string ended without a closing quote.
InvalidEscape
InvalidEscape = 2A backslash escape or surrogate pair is invalid.
InvalidUtf8
InvalidUtf8 = 3A string contains malformed UTF-8.
InvalidNumber
InvalidNumber = 4A number does not satisfy the JSON number grammar.
DuplicateKey
DuplicateKey = 5An object repeats a decoded member name.
InvalidValue
InvalidValue = 6A constructed value contains a child of the wrong container kind.
TypeMismatch
TypeMismatch = 7A valid JSON value does not have the requested type.
NumberOutOfRange
NumberOutOfRange = 8A JSON number cannot fit the requested numeric type.
MissingField
MissingField = 9A required object member is absent.
UnknownField
UnknownField = 10An object member is not part of the requested type.
UnexpectedEnd
UnexpectedEnd = 11The final input ended before the single root value was complete.
DepthExceeded
DepthExceeded = 12The fixed nesting stack is full.
TrailingContent
TrailingContent = 13A second root value follows the first.
OffsetOverflow
OffsetOverflow = 14An absolute byte offset cannot be represented as usize.
TokenTooLarge
TokenTooLarge = 15A streaming consumer's caller-owned token buffer is too small.
JsonError
pub struct JsonErrorA deterministic JSON failure with absolute input position and optional capacity details.
Field reason
pub reason: JsonReasonThe stable failure category.
Field offset
pub offset: silk/option.Option<usize>The offending byte or end position, when available.
Field required
pub required: silk/option.Option<usize>Capacity required by a future consumer, if applicable.
Field available
pub available: silk/option.Option<usize>Capacity available to a future consumer, if applicable.
Associated function JsonError.at
pub fn at(reason: JsonReason, offset: usize) -> JsonErrorCreates an input failure at an absolute byte offset.
JsonToken
pub union JsonTokenOne validated JSON token. String and number spans retain the raw source spelling.
ObjectBegin
JsonToken.ObjectBegin: JsonTokenAn opening object brace.
ObjectEnd
JsonToken.ObjectEnd: JsonTokenA closing object brace.
ArrayBegin
JsonToken.ArrayBegin: JsonTokenAn opening array bracket.
ArrayEnd
JsonToken.ArrayEnd: JsonTokenA closing array bracket.
KeySeparator
JsonToken.KeySeparator: JsonTokenA colon between an object key and value.
ValueSeparator
JsonToken.ValueSeparator: JsonTokenA comma between array elements or object members.
String
JsonToken.String { span: JsonSpan, escaped: bool }: JsonTokenA quoted, UTF-8-valid string, including its source quotes in span.
Field span
pub span: JsonSpanThe raw quoted source range.
Field escaped
pub escaped: boolWhether a backslash escape occurred.
Number
JsonToken.Number { span: JsonSpan }: JsonTokenA valid number lexeme, without numeric conversion.
Field span
pub span: JsonSpanThe raw source range.
True
JsonToken.True: JsonTokenThe literal true.
False
JsonToken.False: JsonTokenThe literal false.
Null
JsonToken.Null: JsonTokenThe literal null.
EndOfInput
JsonToken.EndOfInput: JsonTokenThe complete root value and trailing whitespace have ended.
Implementation Copy for JsonToken
impl Copy for JsonTokenJsonScanEvent
pub union JsonScanEventThe outcome of one resumable scan step.
Token
JsonScanEvent.Token { token: JsonToken }: JsonScanEventA complete token was emitted.
Field token
pub token: JsonTokenThe token, whose source offsets are absolute.
NeedMore
JsonScanEvent.NeedMore: JsonScanEventAll supplied bytes were consumed; another chunk is needed.
EndOfInput
JsonScanEvent.EndOfInput: JsonScanEventThe complete document has ended.
JsonScanStep
pub struct JsonScanStepOne step's byte accounting and event.
Field consumed
pub consumed: usizeNumber of bytes consumed from this call's chunk.
Field fragment
pub fragment: JsonSpanRange of this lexeme's bytes within this call's chunk, possibly empty.
Field event
pub event: JsonScanEventThe token, need-more request, or final end event.
JsonScanState
pub struct JsonScanStateOwned lexical and container state shared by slice and streaming scanners.
Details
It retains no chunk view. Feed each unconsumed suffix back into step until it reports
NeedMore or EndOfInput; after NeedMore, supply the next chunk.
Associated function JsonScanState.make
pub fn make() -> JsonScanStateCreates an empty, allocation-free state for exactly one root JSON value.
Method JsonScanState.step
pub fn step<'life0, 'life1>(self: &'life0 mut silk/json_scanner.JsonScanState, chunk: &'life1 [u8], final: bool) -> silk/result.Result<silk/json_scanner.JsonScanStep, silk/json_scanner.JsonError>Consumes a chunk up to one token, need-more boundary, or document end.
Details
Reuse the unconsumed suffix after Token. final remains true for every suffix of the
final chunk, including an empty one. No input slice survives this call.
Gotchas
NeedMore consumes the entire chunk. A number at a nonfinal boundary remains pending;
its lookahead delimiter is left for the following call. Errors make this state terminal.
JsonScanner
pub struct JsonScanner<'input>A slice-backed convenience adapter over the resumable scanner.
Associated function JsonScanner.make
pub fn make<'input>(input: &'input [u8]) -> silk/json_scanner.JsonScanner<'input>Borrows a complete input slice and starts a single-document scan.
Method JsonScanner.next
pub fn next<'input, 'life1>(self: &'life1 mut silk/json_scanner.JsonScanner<'input>) -> silk/result.Result<silk/json_scanner.JsonToken, silk/json_scanner.JsonError>Returns the next token or sticky EndOfInput after trailing whitespace.
Method JsonScanner.peek
pub fn peek<'input, 'life1>(self: &'life1 mut silk/json_scanner.JsonScanner<'input>) -> silk/result.Result<silk/json_scanner.JsonToken, silk/json_scanner.JsonError>Returns the next token without consuming it.
Method JsonScanner.offset
pub fn offset<'input, 'life1>(self: &'life1 silk/json_scanner.JsonScanner<'input>) -> usizeReturns the absolute byte offset of the last token returned by next or peek.
Method JsonScanner.length
pub fn length<'input, 'life1>(self: &'life1 silk/json_scanner.JsonScanner<'input>) -> usizeReturns the length of the complete input slice.
Method JsonScanner.slice
pub fn slice<'input, 'life1>(self: &'life1 silk/json_scanner.JsonScanner<'input>, span: JsonSpan) -> &'input [u8]Borrows the raw bytes denoted by a token span from this scanner's complete input.