feat: Add Reader.RawValue for capturing a value's raw bytes - #45
Merged
Conversation
keelerm84
force-pushed
the
mk/SDK-2760/jreader-raw-value
branch
from
July 28, 2026 16:53
00cfd3b to
975e0be
Compare
keelerm84
force-pushed
the
mk/SDK-2760/jreader-raw-value
branch
from
July 29, 2026 17:32
975e0be to
3c65837
Compare
keelerm84
marked this pull request as ready for review
July 29, 2026 17:38
RawValue consumes the next JSON value of any type and returns its raw bytes verbatim as a zero-copy slice of the input, with cap == len so a caller cannot reslice or append into adjacent bytes of the buffer. The value is fully validated: scalars by the tokenizer, whose grammar is RFC 8259 compliant, and arrays/objects by locating the byte boundary with a fast string-aware scan and then checking the captured span with encoding/json's json.Valid, since the boundary scan does not interpret the content in between. Malformed input produces a parsing error rather than being returned. Offset reports the Reader's current byte position within its input (or the start of a pushed-back token). A caller that parses a value in place can record the offset before and after the parse and slice the original input to obtain the value's raw bytes with no separate scan or validation pass, since the tokenizer fully validates everything it parses; captured spans may include surrounding JSON whitespace, which callers trim. Both methods exist only in the default build. easyjson support is planned for removal from this library, so no new functionality is provided for it; the launchdarkly_easyjson build does not have these methods, following the same pattern as NewReaderFromEasyJSONLexer, which exists only under that tag. These APIs support go-server-sdk's single-pass FDv2 payload parsing, which needs both the parsed form and the verbatim bytes of every item: recognized items are model-decoded in place with offsets captured around the decode, and RawValue covers values that are never model-parsed (objects of unrecognized kinds), where its validation is the only line of defense before the bytes are relayed downstream.
keelerm84
force-pushed
the
mk/SDK-2760/jreader-raw-value
branch
from
July 29, 2026 17:45
3c65837 to
db5e127
Compare
kinyoklion
approved these changes
Jul 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Returns the raw bytes of the next JSON value as a zero-copy slice of the
reader's input, consuming the value. Scalars are fully validated; array and
object values are scanned with a fast string-aware delimiter-matching pass.
Implemented for both the default tokenizer (position-based span capture) and
the launchdarkly_easyjson build variant (jlexer.Raw).
This enables consumers that need both a parsed representation and the
verbatim JSON of the same value (for example, the FDv2 data sources in
go-server-sdk, which store parsed items and relay raw bytes downstream) to
avoid re-scanning or copying the input.
Note
Medium Risk
Touches core tokenizer behavior and JSON acceptance boundaries for containers; mistakes could change what bytes are relayed downstream, though the change is additive and heavily tested against encoding/json.
Overview
Adds
Reader.RawValue()andReader.Offset()on the default build (!launchdarkly_easyjson) so callers can keep verbatim JSON alongside typed parsing without re-scanning or copying the input buffer.RawValueconsumes the next value and returns a zero-copy slice (cap == len) into the reader’s input. Scalars use the existing RFC 8259 tokenizer; arrays/objects use a string-aware delimiter scan followed byencoding/json.Validon the captured span. Invalid containers surface a newerrMsgInvalidValuesyntax error. The method handles unread-token state (e.g. after aNull()probe).Offsetreports the next byte to consume (or the start of a pushed-back token), documented for the alternative pattern: sliceinput[start:Offset]around an in-place parse, trimming JSON whitespace at the ends.The easyjson build intentionally omits both APIs (comment only). Coverage includes unit tests, differential/oracle tests against
encoding/json, generative fuzz, and offset-span tests.Reviewed by Cursor Bugbot for commit db5e127. Bugbot is set up for automated code reviews on this repo. Configure here.