Skip to content

feat: Add Reader.RawValue for capturing a value's raw bytes - #45

Merged
keelerm84 merged 1 commit into
v3from
mk/SDK-2760/jreader-raw-value
Jul 29, 2026
Merged

feat: Add Reader.RawValue for capturing a value's raw bytes#45
keelerm84 merged 1 commit into
v3from
mk/SDK-2760/jreader-raw-value

Conversation

@keelerm84

@keelerm84 keelerm84 commented Jul 27, 2026

Copy link
Copy Markdown
Member

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() and Reader.Offset() on the default build (!launchdarkly_easyjson) so callers can keep verbatim JSON alongside typed parsing without re-scanning or copying the input buffer.

RawValue consumes 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 by encoding/json.Valid on the captured span. Invalid containers surface a new errMsgInvalidValue syntax error. The method handles unread-token state (e.g. after a Null() probe).

Offset reports the next byte to consume (or the start of a pushed-back token), documented for the alternative pattern: slice input[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.

@keelerm84
keelerm84 force-pushed the mk/SDK-2760/jreader-raw-value branch from 00cfd3b to 975e0be Compare July 28, 2026 16:53
@keelerm84
keelerm84 changed the base branch from v3 to mk/SDK-2771/rfc-8259-compliance July 28, 2026 16:53
Base automatically changed from mk/SDK-2771/rfc-8259-compliance to v3 July 29, 2026 17:23
@keelerm84
keelerm84 force-pushed the mk/SDK-2760/jreader-raw-value branch from 975e0be to 3c65837 Compare July 29, 2026 17:32
@keelerm84
keelerm84 marked this pull request as ready for review July 29, 2026 17:38
@keelerm84
keelerm84 requested a review from a team as a code owner 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
keelerm84 force-pushed the mk/SDK-2760/jreader-raw-value branch from 3c65837 to db5e127 Compare July 29, 2026 17:45
@keelerm84
keelerm84 merged commit 28aa1e3 into v3 Jul 29, 2026
13 checks passed
@keelerm84
keelerm84 deleted the mk/SDK-2760/jreader-raw-value branch July 29, 2026 18:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants