Add Spanned<T> for source locations, plus a serde-saphyr comparison benchmark#63
Open
jskoiz wants to merge 3 commits into
Open
Add Spanned<T> for source locations, plus a serde-saphyr comparison benchmark#63jskoiz wants to merge 3 commits into
jskoiz wants to merge 3 commits into
Conversation
Benchmark saneyaml against serde-saphyr across dynamic-value and typed-struct deserialization in a new example, and document the results in BENCHMARKS.md. Add serde-saphyr as a dev-dependency.
Spanned<T> pairs a deserialized value with the source span (byte offsets plus line and column) it was read from, built on the existing node span tree via a private deserializer protocol. It is available on the from_str, from_slice, and from_node read paths and nested struct fields, serializes transparently, and adds no dependencies. The from_value path remains spanless.
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.
Summary
Adds
Spanned<T>for capturing the source location of deserialized values, plus a reproducible head-to-head benchmark againstserde-saphyr(the motivation for the feature work). Three commits:serde-saphyrcomparison benchmark — a new example and a documentedBENCHMARKS.mdsection.Spanned<T>— capture the source span of a successfully deserialized value.Spanned<T>— source locations for parsed valuesError spans only appear on failure;
Spanned<T>exposes the location of a successful read (byte offsets plus line/column), which is what config linters, language servers, and "this setting came from line N" tooling need.Design: built on the existing spanful
Nodetree — each span-bearing deserializer recognizes a private marker struct indeserialize_structand answers with the current node's span (which already carries line/column), so there is no second parse and no retained source buffer. The fivedeserialize_structhooks are inert guards for every other type.from_str,from_slice,from_node, and nested struct fields.from_value(line 0), by design.ryu+serde.serde-saphyrcomparison benchmarkexamples/serde_saphyr_headtohead.rscompares both crates on identical bytes into identical target types (idiomaticfrom_str), across three axes; results documented indocs/BENCHMARKS.md.On an Apple M4 Pro, both libraries on shipping defaults, saneyaml is ~1.8–2.2× faster (dynamic-value corpus, nested typed struct, and flat typed records — the widest margin on serde-saphyr's own target shape). As elsewhere in
BENCHMARKS.md, the trustworthy signal is the same-run ratio, not absolute ns/byte.serde-saphyris a dev-dependency only.Verification
Run locally and green:
cargo fmt --check,cargo test(full suite, 38 binaries) + doctests,cargo clippy --all-targets -D warnings,scripts/check-feature-clippy.sh,cargo doc -D missing_docs,cargo deny check, theruntime_dependency_closuretrust guard, and thePUBLIC_API.txtsnapshot check (regenerated to includeSpanned).Not included: the
miettefeatureA
miette::Diagnosticintegration was also prototyped, but it adds an (optional) dependency, which theruntime_dependency_closuretrust guard intentionally rejects —[dependencies]is asserted to be exactly{ryu, serde}. That's a dependency-policy decision, so it is deliberately left out of this PR. Options to land it later: a separatesaneyaml-miettecompanion crate (preserves the two-dependency guarantee) or an explicit relaxation of the trust guard for optional deps.