Hand-rolled JSON byte scanner. Resolves a PathStep list against an Array[Byte] JSON document and returns the byte span [start, end) of the resolved value, or -1 for the start if the path doesn't match.
Why hand-rolled rather than reusing jsoniter-scala-core's JsonReader: the scanner only needs to skip-with-backtracking, not decode. Embedding JsonReader would force us to thread its mark / rollback state through every call site, and its API doesn't expose byte offsets directly. 100-ish LoC of dispatch is cheaper than the impedance mismatch.
The scanner is permissive about whitespace (skips it everywhere) and strict about structure (unbalanced quotes / brackets short-circuit to "miss"). It does NOT validate the document; an invalid JSON whose path step happens to resolve will return a span — decoding is the layer that surfaces validity failures.
Resolve path against bytes. Returns the byte span of the focused value (start, end), or Miss if any step fails to match. Rejects PathStep.Wildcard — wildcards produce 0-or-many results and don't fit a single-Span return; route them through findAll.
Resolve path against bytes. Returns the byte span of the focused value (start, end), or Miss if any step fails to match. Rejects PathStep.Wildcard — wildcards produce 0-or-many results and don't fit a single-Span return; route them through findAll.
Resolve path against bytes, returning every span that matches. Wildcard steps fan out across array elements; a path with no wildcards returns 0 or 1 spans. Spans are returned in document order. On any structural mismatch (wrong context for a step, malformed JSON), the sub-tree is silently skipped — the caller sees fewer spans, not an error.
Resolve path against bytes, returning every span that matches. Wildcard steps fan out across array elements; a path with no wildcards returns 0 or 1 spans. Spans are returned in document order. On any structural mismatch (wrong context for a step, malformed JSON), the sub-tree is silently skipped — the caller sees fewer spans, not an error.