Rindle docs and package mapSkip to main content

Module wire_json

Module wire_json 

Source
Expand description

The normalized protocol’s JSON wire rendering — byte-for-byte the shape the @rindle/remote client validates (bare cells, camelCase keys, lowercase op tags, hex fingerprints, f64-safe counters). Moved here from rindle-replica so every party on the wire shares ONE codec: the napi addon and the Rust daemon’s ws front emit with it (via rindle-replica’s re-export), and the room — the first Rust consumer of these frames (RINDLE-REALTIME-DESIGN.md §3) — parses with it. The ..._from_json decoders are new with the room’s upstream leg; until they landed, decode existed only in TS (@rindle/remote/src/normalized.ts).

Two conventions are deliberate and load-bearing:

  • Counters are JS numbers (epoch/seq/cv/comparatorVersion as f64 — the emitters write as f64, so a Rust producer renders 3 as 3.0 while a JS producer writes 3; the decoders accept both), and fingerprints are 16-hex-char strings (a u64 would lose precision as a JS number).
  • Cells are bare (number | string | boolean | null): Int collapses to a JS number and Json to its string form on encode, so decode yields Float/Str — the same inference the wasm Db’s js_to_owned_value applies. The wire is value-faithful, not variant-faithful, by design (the engine’s single numeric model).

The serde derives on the protocol types are not this wire — they are the in-Rust round-trip form (oracles, journals). Sockets carry this rendering.

Shape-only by design: normalized_hello_from_json checks structure, not semantics — PK bounds, duplicate tables, and fingerprint verification belong to RoomStore::open (in rindle-room-core) / the NormalizedSubscriber, which return the protocol’s own errors.

Functions§

fnv1a64
FNV-1a-64 over raw bytes — the flush batch identity (batch_hash, §5.3 step 4: computed once by the emitter over its canonical batch bytes; the authority stores and compares it, never recomputes). Render with {:016x}.
json_to_owned
A bare JS cell → OwnedValue, inferring from the runtime JSON type (matches the wasm js_to_owned_value: number→Float always, string→Str, bool→Bool, null→Null). A json column already crossed as its stringified form, so it lands here as a String.
nbatch_frame
Assemble one full nbatch frame for client_qid, splicing the already-encoded ops_fragment into the scalar envelope. Byte-identical to the json! frame in RouterSink::batch: {"batch":{"cv":…,"epoch":…,"normalizedFp":"…","ops":…,"seq":…}, "queryId":…,"t":"nbatch"} (all keys alphabetical).
nbatch_ops_fragment
Encode batch.ops as its […] JSON array — the fragment nbatch_frame splices into each subscriber’s envelope. RouterSink::batch encodes it ONCE per batch, outside the router lock, then assembles a frame per subscriber (only the envelope’s queryId/seq/epoch differ across a fan-out).
normalized_batch_from_json
Parse an nbatch frame’s batch object into a NormalizedBatch.
normalized_batch_to_json
A NormalizedBatch{ epoch, seq, cv, normalizedFp, ops }. The fingerprint is a hex string (a u64 would lose precision as a JS number); cv is the commit version the optimistic client buffers by (OPTIMISTIC-WRITES-DESIGN.md §8.6).
normalized_hello_from_json
Parse an nhello frame’s hello object into a NormalizedHello (shape only — see the module docs for where semantic validation lives).
normalized_hello_to_json
A NormalizedHello{ epoch, comparatorVersion, tables: [{ name, columns, primaryKey }], normalizedFp } — the slim per-table-schema handshake (§3).
normalized_op_from_json
Parse one { table, op, … } wire object into a NormalizedOp. Note the shape is the OUTBOUND batch wire — remove carries row and edit carries old/new — distinct from the change-source ingest shape (rindle-replica’s mutation_from_json), where remove carries old and edit’s new row rides as row.
normalized_op_to_json
A NormalizedOp → its camelCase JS object: { table, op, row | old/new } (bare cells), the path-free twin of a flat change (NORMALIZED-CHANGES-DESIGN.md §3).
owned_to_json
OwnedValue → a bare JS value. Int/Float collapse to a JS number (the engine’s single numeric model); Str/Json to a string (a json column is parsed at read time by the view’s typed schema, exactly as on the local path).
packed_row_to_json
A packed engine row → its JSON array of bare cells (the wire_row_to_json twin for [OwnedRow]).
row_change_to_json
One row change in the change-source ingest shape — the changes[] element rindled’s /apply-row-change-txn consumes (rindle-replica’s mutation_from_json is the decode dual): add → {row}, remove → {old}, edit → {old, row} where row is the NEW image. Deliberately distinct from normalized_op_to_json — that is the OUTBOUND batch wire, where remove carries row and edit carries new. The room’s write-behind flush emits this shape (RINDLE-REALTIME-DESIGN.md §5.3), with old carrying the base image the CAS precondition asserts. NOTE: this emitter renders cells via owned_to_json, which is FLOAT-FORM for Int — it is NOT the integer-exact ingest codec (rindle-replica::wire_json::mutation_to_json, design 226 Stage D). Room cells are Number-plane today so nothing is lost; unify onto the exact codec before any exact-int producer feeds this path.
wire_row_from_json
One JSON array of bare cells → a positional wire row.
wire_row_to_json
One positional wire row → its JSON array of bare cells.