Update Rust crate noyalib to 0.0.27 - #154
Open
renovate[bot] wants to merge 1 commit into
Open
Conversation
renovate
Bot
force-pushed
the
renovate/noyalib-0.x
branch
from
August 20, 2026 09:57
9d962f8 to
c0612c6
Compare
renovate
Bot
force-pushed
the
renovate/noyalib-0.x
branch
from
August 20, 2026 22:33
c0612c6 to
b61e166
Compare
renovate
Bot
force-pushed
the
renovate/noyalib-0.x
branch
from
August 21, 2026 17:34
b61e166 to
fe06b52
Compare
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.
This PR contains the following updates:
0.0.23→0.0.27Release Notes
sebastienrousseau/noyalib (noyalib)
v0.0.27Compare Source
Two correctness fixes in alias and merge-key handling, both found by
consumers pointing a real workload at a published release.
Fixed
An alias used as a value beside a merge key came back unresolved
(#301, reported and diagnosed by
@mathstuf, fixed in #304).
peek_eventandnext_eventeach read from either the replay stack orthe parser, and resolved aliases on the parser branch only — then
labelled both results processed. An alias arriving through replay was
therefore stored as though it were fully processed while still being an
Event::Alias. The replay stack only exists once a merge has injectedsomething, which is why the same document works with the alias written
above the
<<:line and fails below it.Alias resolution now runs whichever branch the event came from, in one
process_event;anchor_and_recordis the single place doing anchorbookkeeping; and the lookahead slot is typed (
Lookahead::{Raw, Processed}) so its two consumers stop inferring which kind they hold,in opposite directions. Inline alias resolutions 3 -> 1, anchor/record
pairs 3 -> 1.
Only a plain
<<scalar is a merge key. The YAML merge type givestag:yaml.org,2002:mergeto a plain<<; a quoted"<<", and analias resolving to the string
<<, both resolve totag:yaml.org,2002:str. Both were being read as merge instructions.By the time a key reaches the mapping arms it is a
Value::String("<<")however it was written, so eligibility is nowdecided at each scalar-resolution site and carried in the frame.
loader.rsholds two complete loaders, each with its own frame enumand its own pair of merge checks — four sites in all. The first attempt
patched one and changed nothing observable.
Value::apply_mergeremains style-blind by nature and is documented assuch: it operates on an already-built
Value, where presentation doesnot exist.
Added
merge_keys_with_aliasesexample — merge keys and aliases in onemapping, and which spellings of
<<are merges.<<:expansion (merge_key_single_anchor,merge_key_sequence_of_anchors,merge_key_quoted_is_ordinary, and amerge_key_absent_baseline). The existingmerge_small/merge_nested/merge_concattimeValue::merge(), an API method onan already-parsed value; nothing measured merge-key expansion during
parsing.
matrix asserts every case on both the streaming and AST paths), and
8 regression, plus a differential oracle comparing
from_str::<Value>against
load_all, which shares no lookahead code.Changed
doc/ECOSYSTEM.mdanddoc/scorecard.jsonregenerated against thisrelease. The previous scorecard's
audit_vulnerabilitiesrows werenever actually measured —
cargo auditwas exiting 101 under ashadowing shell alias and the probe's fallback read that as zero
advisories. That probe was fixed in v0.0.26; this is the first
scorecard where those rows are earned.
v0.0.26Compare Source
Fixed
removeleft a whitespace-only line in a wrapped flow collection(#294, reported and fixed by @zoosky,
PR #296). A flow collection written one member per line —
— lost the member but kept its indentation, so
remove("ports[0]")wrote
onto a line that had held content. The value round-trippedunchanged, so this was never corruption; it was trailing whitespace in
a patch, which
git diff --check,yamllint'strailing-spacesandeditorconfig-checkerall reject. A library whose promise is that anedit touches only what the path names should not hand its caller a diff
their own lint refuses.
flow_member_rangetook the member and exactly one separator — rightfor
{x: 1, y: 2}, and all a single-line collection ever needs — butnothing then asked whether the line had anything left on it. The block
path had always answered that same question the other way:
owned_entry_rangetakes the entry's whole line, indentation included.Same operation, same shape, opposite answers.
The member now takes its whole line when — and only when — it is alone
on it. The condition is "alone on its line", not "the collection is
wrapped", so an opening indicator, a sibling member, a trailing comment
or the closing indicator all keep the line standing and leave those
outputs byte-identical.
Unreachable before #285: a wrapped flow collection did not parse, so
nothing downstream of the scanner had ever seen one. That is the second
time in two releases that fixing a parse refusal exposed a defect it
had been hiding.
The fix is
absorb_emptied_line, named for the existingabsorb_head_commentsit sits beside. Its doc comment draws oneboundary worth repeating: a comment left on the line keeps the line,
because what a comment stranded by a removal means is the caller's
question, not something a whitespace rule should decide.
42 tests added — 13 from @zoosky's PR, plus 18 integration and 11 unit
tests here — and the
cst_wrapped_flow_editexample. The unit testswere written against an independent implementation of the same fix and
pass unmodified against this one, which is the closest thing to a
second opinion a single codebase gets.
The ecosystem scorecard scored a security probe it had not run.
cargo audit --jsonexits 101 where a user-definedaudit = "audit"alias in
~/.cargo/config.tomlshadows the subcommand and recurses.The probe's fallback counted
RUSTSECoccurrences in whatever landed onstdout, so an error message yielded "0 advisories" and a clean pass —
the harness's own "no credit for unmeasured work" rule violated in the
place it matters most. It now invokes
cargo-auditdirectly and treatsunparsable output as N/A. Exit status alone cannot decide this, because
cargo-auditalso exits non-zero when it genuinely finds advisories;the discriminator is whether
.vulnerabilities.countparses. The realcount for this release is 0 across 272 crates, confirmed by running the
binary directly.
v0.0.25Compare Source
Four fixes from @zoosky, all found while
adopting v0.0.24 in yqr, and all cases
where the previous behaviour produced or refused something this codebase
already disagreed with elsewhere.
Each arrived as a reproduction against a published version, a diagnosis
naming the responsible function, a fix, and tests — including the cases
that had to keep failing. Three of the four were found by pointing a real
consumer at a release and reporting what broke, which is the kind of
testing a library cannot do for itself.
Fixed
removewrote an empty collection at its key's own column (#283,PR #284). A block sequence may sit at its key's column —
on:/- pushis what nearly every GitHub Actions and Ansible file lookslike. What replaces it may not:
{}/[]is a block mapping value,and one sharing its key's column does not re-parse as that key's value.
The inconsistency was visible from inside: delete the
jobs:line andthe identical removal was refused by the oracle, because the guard
re-parses with this parser, which accepts
on:\n[]\njobs: {}andrejects
on:\n[]. Same shape, same output spelling —Okwith asibling, refused without one.
sole_entry_rangetook the indent from the removed entry's own line,which for this layout is the key's column. The constraint is
"strictly deeper than the key", and the two coincide for every layout
except this one. The parent key's offset is now threaded down and the
indent clamped to the key's column + 2 when the entry's own indent does
not already clear it. A root collection, or one reached through a
sequence item, has no parent key and is unchanged.
The head-comment run from #280 is still absorbed at the entry's own
column, where those comment lines actually sit — only the replacement
moves.
A wrapped flow collection was refused when its closing indicator sat
at the parent's column (#285, PR #286):
A read refusal, so nothing downstream ran. The indentation check
exists so that flow content continuing across a line break cannot be
ambiguous with sibling block content (yaml-test-suite 9C9N) — but that
rationale is about content. A line whose first character is
]or}cannot begin block content, so there is nothing to be ambiguouswith; the rule was reaching the terminator too.
The asymmetry was already in the tree: the same closer at column 0 is
accepted at the root, where
self.indentis-1. Only a flow inside ablock mapping refused it.
Under-indented flow content stays refused, deliberately — that is
9C9N's rule and this does not touch it.
ports: [/80,/]isstill an error, as is 9C9N itself, whose third line opens with a scalar
rather than the indicator.
A new key could not be inserted into a mapping whose keys contain a
.,[or*, and the refusal blamed a<<merge that was notthere (#288, PR #289).
insert_entry("labels", "tier", "frontend")refused. That is thestandard Kubernetes label convention, so the shape is everywhere.
Two sites took the last key from the typed view, composed it back
into a path string, and re-parsed it —
mapping_insert_anchor, andinsert_entry, which duplicated the logic inline.parse_query_pathsplits on
.,[and*unconditionally, so no such key survives theround trip and every entry looked span-less. With no anchor left, the
only error the function knew about fired: the merge one.
Two defects nested — a path round trip that no such key survives, and a
diagnostic asserting a cause rather than reporting an observation.
The anchor never needed a path.
mapping_insert_anchornow walks thespan tree's entries directly, through a new
resolve_tree, andinsert_entryshares it instead of keeping its own copy. Three thingsfall out, each tested: keys holding
[,*or quoted dots insertcorrectly; a mapping whose last entry is an implicit null anchors on
that entry's key line, so a sibling lands after it rather than
above it; and a mapping with both a
<<merge and an entry of its ownanchors on the entry. A merge-only mapping still refuses, leading
with what was observed.
Insert only —
set,remove,rename_keyandswap_itemsstilladdress through
parse_query_path, so a dotted key stays out of reachfor them. Whether the path grammar should grow an escape form is a
separate question.
An inserted scalar was quoted because some unrelated line was
quoted (#290). The dominance vote counted only quoted scalars against
each other — plain ones did not vote — so a single quoted scalar
anywhere decided the spelling of every later insertion:
On a Kubernetes manifest the vote was settled by
value: "30"in acontainer's env block, arbitrarily far from the labels being edited.
Nothing was wrong with the value — it round-trips and the document
stays valid — but the diff a reviewer saw was a quoted value among
plain ones. It also disagreed with
set, which writes plain at thesame site.
EmitCtx's doc already stated the intent — an implementation should"match the file it is landing in" — so the radius was wrong rather than
the idea. Insertion now learns from the collection it lands in and only
falls back to the document-wide vote when that collection has no scalar
values to learn from.
Two details decided by implementing it:
site's byte range cannot tell one from the other, and mapping keys
are almost always plain —
a: "one"/b: "two"would tie two plainkeys against two quoted values and pick plain, the opposite of what
the site says. The entry values are read from the span tree instead.
mixed (
a: 1besideb: 'two'), and there the quoting alreadypresent is the better guide. Every case #290 reports has plain
winning outright.
Document::dominant_quote_styleis public, documented, and pinned bythree doctests, so its behaviour is unchanged — this narrows what
insertion asks, not what that function answers. Of the two options in
the report this is the second, which leaves the public API alone.
removerefuses an alias-valued entry instead of silently doingnothing (PR #292). Behaviour change: a call that previously
returned
Ok(())now returns an error.An alias resolves through to its anchor, so the value span for
bis the anchor's bytes on another line — before
b's own key. Therange arithmetic degenerated to an empty splice, so the call removed
nothing and reported success.
Refusing is what
SpanTree::Alias's own documentation alreadyprescribes: a write there would splice the anchor's bytes, which
belong to a different key. The message names the entry and the reason.
Removing the anchor's own entry still works, as does
replace_spanfor callers who want the bytes gone deliberately.
Present since at least v0.0.24 — reproduced identically on that tag —
and surfaced by the corrected fuzz invariant below, which asserts that
an accepted removal changed the source.
Testing
The differential fuzz target's remove invariant was unsound (PR
#291).
fuzz_editorsasserted that an acceptedremoveshrinks theparsed value. It does not, under duplicate mapping keys:
Valuededuplicates and the last duplicate wins, so removing one of two
5:entries deletes a line from the source while both parses still show
three keys. A correct edit failed the assertion and
fuzz-diffwentred on
main.Asserting the source gets shorter is also wrong — removing the only
entry rewrites
"::\n"to"{}\n", which is correct and exactly aslong. What holds is that the source changed, and that is what the
target now asserts; the node count is kept only in the non-strict
direction, which still catches a removal that takes a parent with it.
removeitself was correct throughout. Both behaviours are pinned intests/cst_remove_fuzz_regressions.rsso they run under the normalsuite rather than only under a nightly fuzz job.
Changed
Per-release notes moved from the repository root to
doc/release-notes/, renamed to matchtheir tags exactly (
doc/release-notes/v0.0.17.mddocumentsv0.0.17). Moved withgit mv, so history follows. Links thatpointed at the old root paths were updated; deep links to
RELEASE-NOTES-v0.0.N.mdonmainwill need adjusting.Version → 0.0.25.
v0.0.24Compare Source
Fixed
removestranded a sole entry's head comment (#280, reported by@zoosky). The same comment on the same entry was taken when the
entry had a sibling and left behind when it did not:
The two arms derived their range from different things.
Removal::Linegoes throughowned_entry_range, which callsabsorb_head_commentsand so owns the contiguous same-indent commentrun above the entry.
Removal::SoleEntryreplaced the collection'sspan, and a collection starts at its first entry's content —
below the comment — so the run was never absorbed. Returned
Ok, andinvisible to the typed oracle, because a comment is not in the typed
value.
Both paths now share
sole_entry_range. Two consequences worthnaming:
whitespace falls inside the replaced range and is written back —
otherwise
a:loses its value entirely rather than gaining{}.a: {x: 1}starts at the{part way along a line whose earlier bytes belong to the key. There
is no head-comment run to own there, and those bytes are not
indentation: treating them as such rewrote
a: {x: 1}as{}and lost the key. Caught by an existing test.
Unchanged, and now pinned: a comment detached by a blank line, or at a
different column, is not the entry's and stays put; an inline trailing
comment sits inside the collection span and was always removed
correctly.
Changed
#275, #276, #277 and #278:
jsonschema0.49.6 → 0.49.9hashbrown0.15.5 → 0.17.1github/codeql-action/{analyze,init,upload-sarif}4.37.6 → 4.37.7taiki-e/install-action2.85.10 → 2.86.1Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.