noyalib v0.0.19
noyalib v0.0.19
Changes since v0.0.18 (2026-07-31).
5 merged pull requests, 195 files, +2,439 / −1,965.
Note on versioning. 0.0.19 and 0.0.20 were both prepared on
main
at different points but neither was ever tagged, so neither reached
crates.io — the last published release is 0.0.18. This release
renumbers back to 0.0.19 so the published sequence stays
contiguous. No previously published version is affected.
Fixed
from_str_strict rejected every populated Option field (#239)
Reported as Option<String> failing on "", which reads like an
empty-string edge case. It was not — every Option<T> field with a
value failed, for every T:
f: "" -> Err(invalid type: string "", expected option)
f: "hello" -> Err(invalid type: string "hello", expected option)
f: 7 -> Err(invalid type: integer 7, expected option)
f: ~ -> Ok(None)
option sat in the forward_to_deserialize_any! list on
impl Deserializer for &Value, so deserialize_option fell through to
deserialize_any, which hands the visitor a concrete scalar. Serde's
Option visitor rejects anything that is not visit_some /
visit_none. Only null worked, because deserialize_any maps
Value::Null to visit_unit and serde accepts that as None — likely
why the bug survived, since the null path is the one most likely to be
tested.
from_str was never affected: it does not deserialise from a &Value.
Only from_str_strict, which goes through serde_ignored, took that
path.
Thanks to @kshpytsya for the report and the minimal repro.
Bare nan / inf spellings destroyed a scalar's text
A mapping key nAn came back as nan, so nAn: null did not
round-trip. Found by the roundtrip_value property test.
resolve_plain_scalar fell back to s.parse::<f64>(), and Rust's
f64::from_str accepts nan, inf and infinity in any case with an
optional sign. YAML 1.2 spells the float specials .nan, .inf and
-.inf — with a leading dot — and those are matched explicitly. Once a
bare form resolved to a float, the original text was unrecoverable.
Bare spellings now stay strings, which is what the spec asks for. An
explicit !!float nan is unaffected — tagged scalars resolve on a
separate path where the tag makes the intent unambiguous.
TRUE still resolves to true; that is the bool arm's YAML 1.1 legacy
behaviour, gated behind a flag and deliberate.
CST remove() took trivia it did not own (#226)
remove() now takes the trivia the removed entry owns, and only that.
Thanks to @zoosky.
Changed
Configured clippy lints were never applied (#228)
[package.metadata.clippy] warn-lints = [...] is not a table cargo
reads, so none of the configured lints were in effect. It is now a real
[lints.clippy] table with cargo, pedantic and nursery at warn.
Test files no longer carry allow(clippy::all), so the suite is linted
too. cargo clippy --all-targets --all-features -- -D warnings runs
clean.
serde_core is now a direct dependency (#227)
Replaces serde with derive.
Clippy-driven refactors
i64::try_fromin place ofv <= i64::MAX as u64plusas i64,
which also removed a redundant runtimecfg!()test that duplicated
the#[cfg]blocks beneath it (#240)clippy::pedanticandclippy::nurseryautofixes (#241)use Trait as _for traits imported only for their methods (#242)format!("literal")→"literal".to_string()(#243)impl core::error::Error for ParseNumberError, unconditional rather
than#[cfg(feature = "std")](#256)
All of the above from @EdJoPaTo, with authorship preserved.
Coverage gate rebaselined 96% → 95% (functions)
The function threshold left under three functions of slack. The crate
measures 96.19% on one revision and 95.99% on another whose only
difference in the affected file is MappingAny::with_capacity →
Self::with_capacity — semantically identical. The metric is also not
stable run to run: the same commit reported 78 uncovered (95.99%) then
77 (96.04%) on consecutive runs of the identical command.
A threshold a no-op rename can breach, and that moves without the code
moving, is measuring LLVM's instantiation accounting rather than the
test suite. Line (94%) and region (93%) floors are unchanged — those
were stable across every run.
Dependencies
Two consolidation waves, 19 Dependabot pull requests in total.
This release (#257) — serde-saphyr 0.0.29 → 1.0.1, bytes 1.12.0 →
1.12.1, jsonschema 0.49.2 → 0.49.6, actions/attest-build-provenance
v4.1.1 → v4.2.2, the rust-toolchain group across 48 call sites in 17
workflows, and codeql-action analyze / upload-sarif / init
v4.37.4 → v4.37.6.
Earlier (#238) — validator 0.19.0 → 0.21.0, sval 2.20.0 → 2.21.0,
schemars 1.2.1 → 1.2.2, the tokio-stack group, taiki-e/install-action
2.85.2 → 2.85.5, ossf/scorecard-action 2.4.3 → 2.4.4, and
codeql-action 4.37.3 → 4.37.4.
serde-saphyr's major bump is bench-only: it is optional, gated behind
compare-saphyr, and used only by the comparison benchmarks. The
benches were verified to compile against 1.0.1 rather than the API
being assumed stable.
Supply chain
Nine crates came up unvetted after the bumps. Refreshing imported
audits covered four of them outright with genuine third-party audits —
fancy-regex, jsonschema, referencing and regex-automata — rather than
exempting them. The remaining five already had exemptions, which were
moved in place. The exemption count is unchanged at 21; nine
unvetted crates produced zero new exemptions.
validator 0.21 pulls in proc-macro-error3 and
proc-macro-error-attr3 (maintained forks of the unmaintained
proc-macro-error); both are recorded in supply-chain/config.toml.
Verification
Run against the merged result, not the individual pull requests:
| gate | result |
|---|---|
cargo check --locked --workspace --all-targets |
exit 0 |
cargo clippy --all-targets --all-features -- -D warnings |
exit 0, zero diagnostics |
cargo test --all-features |
5,941 passed, 0 failed |
| coverage (95% fn / 94% line / 93% region) | exit 0 |
cargo vet --locked |
249 fully audited, 1 partially, 20 exempted |
reuse lint |
850/850 files compliant, REUSE 3.3 |
| Miri (focused) | pass |
Both bug fixes ship with regression tests that were confirmed to fail
without their fix.