feat(rust): make readable indented Links Notation the default encoding - #38
Conversation
Adding .gitkeep for PR creation (default mode). This file will be removed when the task is complete. Issue: #37
encode() now writes an indented, plain-text document that uses one ( ) construct for both objects and arrays at every level, including the root. Keys and values are written verbatim, strings are double-quoted, and numbers, true/false and null stay bare so types survive a round trip. A value is base64-encoded only when it genuinely cannot be written as text (it contains control characters), and each such value is marked individually as (base64 "...") while everything around it stays readable. The previous single-line base64 output is kept under the explicit names encode_compact()/encode_obfuscated(), and decode() accepts both forms, so existing files keep working and migrate on the next write. Reading the readable form back needs links-notation 0.14 semantics, where a parenthesis opens a nested indentation context, so the dependency is raised to 0.14. Closes #37
Working session summaryDone — PR #38 is ready for review with all CI checks green: #38 What landed (commit
Verification: 41 unit + 17 readable-format + 5 documentation + 7 doc tests, plus fmt/clippy/file-size clean locally; CI passed on ubuntu, macOS and Windows. The read-back path is a dedicated line-aware tokenizer rather than the This summary was automatically extracted from the AI working session output. |
🤖 Solution Draft LogThis log file contains the complete execution trace of the AI solution draft process. 💰 Cost: $5.344790📊 Context and tokens usage:Claude Opus 5: (2 sub-sessions)
Total: (5.9K new + 142.2K cache writes + 4.7M cache reads) input tokens, 61.6K output tokens, $5.344790 cost 🤖 Models used:
📎 Log file uploaded as Gist (2366KB)Now working session is ended, feel free to review and add any feedback on the solution draft. |
🎉 Auto-mergedThis pull request has been automatically merged by hive-mind.
Auto-merged by hive-mind with --auto-merge flag |
PR #38 changed only the Rust codec and no other language's CI ran, because each workflow filters itself by paths:. This adds .github/workflows/parity.yml (no paths: filter) and scripts/check-language-parity.mjs, which fails a pull request when one language's src/ changed without the others. An intentional single-language change opts out with [skip-parity] in the PR title or body. Covered by scripts/check-language-parity.test.mjs (7 cases).
Closes #37.
Problem
Stored documents were unreadable: every string went through base64, so a router
state file looked like
grep,git diffand human review were all useless on it, even though nothingin the data actually needed encoding.
Solution
encode()now writes an indented, plain-text document. One( )constructcarries both objects and arrays at every level including the root;
key valuelines make an object, bare-value lines make an array:
true,falseandnullstay bare, so"18878"and18878still decode to a string and an intrespectively.
(it contains control characters), and each such value is marked individually
as
(base64 "...")— the rest of the document stays readable.()and an empty object is(+ newline +), so emptycontainers keep their type across a round trip.
encode_compact()/encode_obfuscated();encode_with_indent()lets theindentation string be configured. Nothing but the readable form is the default.
decode()detects which form it is given, so previously written files keepdecoding and are rewritten in the readable form the next time they are saved.
links-notationis raised to 0.14, where a parenthesis opens a nestedindentation context — required for the nested form above to read back.
Because the
links-notationAST does not preserve quoting ("42"and42bothparse to
Ref("42")) and cannot tell a one-pair object from a two-elementarray, the readable form is read back by a small line-aware tokenizer in
rust/src/readable.rsthat keeps both distinctions.Reproduction
experiments/issue-37/parenthesis-indentationcontains the probe used to verifythat 0.14 is genuinely required: on 0.13 the nested
serverlink flattens tofour loose references, on 0.14 it yields two pair-links.
Before/after output of the codec itself is visible in
cargo run --example basic_usage(the example now prints both the readable andthe compact form).
Tests
rust/tests/readable_format.rs(17 tests) covers every case listed in the issue:serverparses as one link of twopairs (the 0.14-only behaviour)
record boundary
strings stay strings; NaN/Infinity/-Infinity round-trip
literal
base64key is not mistaken for the markerissue) still decode, and
encode_compactoutput still decodesrust/tests/documented_examples.rspins the snippets used in the READMEs, andrust/src/readable.rscarries 9 unit tests for the encoder/decoder internals.Full local run: 41 unit + 17 readable + 5 documentation + 7 doc tests passing,
with
cargo fmt --check,cargo clippy --all-targets -D warningsandscripts/check-file-size.mjsclean.Docs
Crate docs,
rust/README.mdand the rootREADME.mdno longer claim that UTF-8support works "using base64 encoding"; they describe the readable format, the
output-format table (
encode/encode_with_indent/encode_compact/encode_obfuscated) and the(base64 "...")marker. Arust/changelog.d/fragment requests a minor bump.