Skip to content

Replace discontinued serde_yaml with yaml_serde - #46

Merged
dduugg merged 2 commits into
mainfrom
replace-serde-yaml
Aug 17, 2026
Merged

Replace discontinued serde_yaml with yaml_serde#46
dduugg merged 2 commits into
mainfrom
replace-serde-yaml

Conversation

@dduugg

@dduugg dduugg commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Closes #15.

Replaces serde_yaml (discontinued March 2024) with yaml_serde, the YAML organization's maintained fork. This also swaps the unsafe-libyaml backend for libyaml-rs from the same org, which yaml_serde pulls in transitively.

Why yaml_serde

The issue asked whether there's something else to consider, so here's what the field looks like now:

crate status drop-in?
yaml_serde 0.10.6 YAML org fork, last release Aug 2026 yes — same API, same output
serde_yaml_ng 0.10.0 no release since May 2024 yes
serde_norway 0.9.42 no release since Dec 2024 yes
serde-saphyr 1.1.0 active, 1.0 in Jul 2026 no — different API, no Value type
serde_yaml2 0.1.3 thin yaml-rust2 binding, undocumented no

yaml-rust2 (suggested in the issue) has no maintained serde layer of its own; the path to it is serde_yaml2, which is 0.1.x and 0% documented. serde_yaml_ng and serde_norway are both drop-ins, but both are now going stale themselves, so picking either would trade one unmaintained fork for another.

yaml_serde is the only option that is both actively maintained and byte-compatible. I diffed its source against serde_yaml 0.9.34: the only substantive changes are no_std support (std/core/alloc import shuffling), clippy modernization, and the libyaml-rs swap. src/ser.rs is functionally untouched, so the emitter behaves identically.

Verification

Beyond the existing test suite (253 tests, all passing), I built the binary before and after and compared them directly:

  • Ran update, validate, check, and lint-package-yml-files over all 31 fixtures in tests/fixtures/, then diffed the resulting trees. Every package.yml and package_todo.yml is byte-identical. (lint-package-yml-files is the interesting one — it rewrites every pack through serialize_pack.)
  • Same for add-dependency, create, and update-dependencies-for-constant across five fixtures.
  • Built a stress fixture with anchors, aliases, !!str tags, multiline literals, unicode, empty collections, and scalars that need each quoting style (#hash, &amp, *star, a: b, 'true', '123', .inf). Output identical.
  • YAML parse errors are character-for-character the same, e.g. did not find expected key at line 11 column 5, while parsing a block mapping at line 9 column 1, so corrupt_todo_test and users' diagnostics are unaffected.

The only output differences I found between the two binaries were two pre-existing sources of nondeterminism that reproduce on main alone: Pack::client_keys is a HashMap, so arbitrary keys in package.yml can shuffle between runs, and strict-mode violation messages come out in parallel-execution order.

What this does not do

The issue also mentions the workarounds. Those stay, unchanged, because yaml_serde inherits serde_yaml's emitter, which offers no control over scalar quoting style:

  • the #…# sentinel in package_todo.rs that produces double-quoted constant keys
  • add_back_necessary_quotes in pack.rs that re-adds quotes around ::-prefixed constants

Worth recording for a follow-up: serde-saphyr does solve this. It exposes DoubleQuoted/SingleQuoted wrapper types, and with no wrappers at all it already emits "::Bar": as a map key and - "::Necessary" in a sequence, which is exactly what the two workarounds hand-roll today. Two things make it a separate change rather than part of this one:

  1. It has no dynamic Value type, which Pack::client_keys: HashMap<String, Value> needs in order to round-trip user-defined package.yml keys.
  2. It prefers double quotes where libyaml prefers single, so ignores: - '**/*' becomes - "**/*". That reformats every affected package.yml in every consumer repo once, which deserves its own decision rather than riding along here.

Happy to open a follow-up issue for that if it's worth pursuing.

serde_yaml was discontinued in March 2024, and its unsafe-libyaml backend
has been unreleased since. Swap both for yaml_serde and libyaml-rs, the
YAML organization's maintained forks.

yaml_serde is an API-compatible fork of serde_yaml 0.9.34 whose only
substantive changes are no_std support and lint cleanups, so this is
behavior-preserving. Verified by diffing the old and new binaries across
all 31 test fixtures: every package.yml and package_todo.yml they write is
byte-identical, as are their YAML parse error messages.

The two emitter workarounds are still required and unchanged: yaml_serde
inherits serde_yaml's emitter, which offers no control over scalar quoting
style.
@dduugg
dduugg requested a review from a team as a code owner August 17, 2026 18:33
@github-project-automation github-project-automation Bot moved this to Triage in Modularity Aug 17, 2026
@dduugg
dduugg enabled auto-merge (squash) August 17, 2026 19:02
Comment thread Cargo.toml Outdated
@dduugg
dduugg merged commit 832309c into main Aug 17, 2026
11 checks passed
@dduugg
dduugg deleted the replace-serde-yaml branch August 17, 2026 19:05
@github-project-automation github-project-automation Bot moved this from Triage to Done in Modularity Aug 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Replace serde_yaml

2 participants