grid: splice the row object into the JSON frame view #208

Merged
natsukium merged 1 commit from fix/row-json-splice-193 into main 2026-09-07 23:56:03 +09:00
Owner

Fixes #193.

RowPayload is #[serde(transparent)] over its bytes, so a GridMsg::RowDelta whose payloads carry
encode_row_json output was serialized as an array of the byte values of the row's JSON text — roughly
3.5x the size for a 48-column row, and unreadable without a second decode, in every consumer
felis-grid::transcode exists to serve.

body_to_json now splices the decoded row object into the frame view, and the inverse direction accepts
only that spliced object: a byte-array row is refused rather than admitted as a second valid row shape.
The splice lives in felis-grid rather than in felis-protocol, whose serde impl stays transparent — a
serializer-dependent impl there would resurrect the human-readable branch that was dropped for reaching
no live path.

Doc cascade: CHANGELOG.md (Fixed) records the user-visible shape change for out-of-repo readers of the
JSON frame view; no reference or explanation page states the row's JSON encoding, so nothing else moved.

Verified: just check green (fmt, clippy, nextest, deny, proto-compat); reviewed by pi sol + pi luna;
docs proofread by Gemini gemini-3.8-flash-high

Deferred

  • No test for a non-RowDelta Grid message (e.g. RehydrateBegin) through the new splice branches —
    both branches are gated on the RowDelta shape, and the existing dispatch test plus the felis-cli
    bridge suite exercise the untouched path; an added case would be redundant coverage.
  • The byte-array rejection test doesn't distinguish a shape-check failure from a content-decode failure —
    the finding itself verifies the test already pins the correct (structural, any-array) rejection path; a
    more faithful fixture would strengthen the story but changes no pass/fail outcome.
  • a_byte_array_row_payload_is_rejected exercises the pure shape check rather than a decode-based
    rejection — the same test and the same cosmetic gap as the note above; merged into that class.
Fixes #193. `RowPayload` is `#[serde(transparent)]` over its bytes, so a `GridMsg::RowDelta` whose payloads carry `encode_row_json` output was serialized as an array of the byte values of the row's JSON text — roughly 3.5x the size for a 48-column row, and unreadable without a second decode, in every consumer `felis-grid::transcode` exists to serve. `body_to_json` now splices the decoded row object into the frame view, and the inverse direction accepts only that spliced object: a byte-array row is refused rather than admitted as a second valid row shape. The splice lives in `felis-grid` rather than in `felis-protocol`, whose serde impl stays transparent — a serializer-dependent impl there would resurrect the human-readable branch that was dropped for reaching no live path. Doc cascade: `CHANGELOG.md` (Fixed) records the user-visible shape change for out-of-repo readers of the JSON frame view; no reference or explanation page states the row's JSON encoding, so nothing else moved. Verified: just check green (fmt, clippy, nextest, deny, proto-compat); reviewed by pi sol + pi luna; docs proofread by Gemini gemini-3.8-flash-high ## Deferred - No test for a non-`RowDelta` `Grid` message (e.g. `RehydrateBegin`) through the new splice branches — both branches are gated on the `RowDelta` shape, and the existing dispatch test plus the felis-cli bridge suite exercise the untouched path; an added case would be redundant coverage. - The byte-array rejection test doesn't distinguish a shape-check failure from a content-decode failure — the finding itself verifies the test already pins the correct (structural, any-array) rejection path; a more faithful fixture would strengthen the story but changes no pass/fail outcome. - `a_byte_array_row_payload_is_rejected` exercises the pure shape check rather than a decode-based rejection — the same test and the same cosmetic gap as the note above; merged into that class.
grid: splice the row object into the JSON frame view
All checks were successful
bench / Criterion full-suite snapshot (pull_request) Has been skipped
bench / Criterion regression gate (pull_request) Successful in 2m10s
darwin / detect relevant changes (pull_request) Successful in 4s
darwin / darwin docs-only no-op (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
pr / nix flake check (pull_request) Successful in 31s
pr / wire schema is compatible with the base (pull_request) Successful in 12s
darwin / build felis (aarch64-darwin) (pull_request) Successful in 50s
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m4s
pr / cargo build / clippy / test / deny (pull_request) Successful in 1m39s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 52s
pr / publish felis (x86_64-linux) (pull_request) Has been skipped
windows / detect relevant changes (pull_request) Successful in 3s
windows / windows docs-only no-op (pull_request) Has been skipped
windows / cargo clippy (Windows cross) (pull_request) Successful in 14s
windows / cargo nextest (Windows) (pull_request) Successful in 4m41s
windows / frontend smoke (Windows) (pull_request) Successful in 1m58s
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
81fb8973bd
`RowPayload` is `#[serde(transparent)]` over its bytes, so serializing a
`GridMsg::RowDelta` whose payloads hold `encode_row_json` output re-encoded
the row's JSON text as an array of byte values: 3.5x the size for a 48-column
row, and unreadable without a second decode, in every consumer the module
exists to serve.

The splice lives here rather than in `felis-protocol`, whose serde impl
stays transparent: a serializer-dependent impl there would resurrect the
human-readable branch that was dropped for reaching no live path. The inverse
refuses a byte-array row instead of accepting it, so the JSON view has one row
shape rather than two.

Refs #193
natsukium deleted branch fix/row-json-splice-193 2026-09-07 23:56:03 +09:00
Sign in to join this conversation.
No description provided.