GeezerVison is showing github.com — Read Cargo.toml package name and version through one shared toml_edit reader · Issue #693 · SocketDev/socket-patch
Read Cargo.toml package name and version through one shared toml_edit reader #693Description[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: E15.
Kind: refactor. Source: review §1 recommendation 1 and Part 5.4 ("Cargo"); register E15.
Problem
Five places read a Cargo.toml [package] table, with three different parsers. Two of them are hand-rolled line scanners, although toml_edit is already a dependency of socket-patch-core.
| Reader |
Parser |
Used for |
crawlers/cargo_crawler.rs#L12-L113:`` parse_cargo_toml_name_version + `parse_table_header` + `extract_string_value` |
line scanner ("no TOML crate dependency") |
crate identity in crawl_all (#L399-L407) and find_by_purls (#L285-L302) |
vex/product.rs#L167-L170 parse_cargo_toml → scan_toml_section |
a second line scanner (also used for pyproject.toml) |
the VEX product purl |
vendor/cargo_tag.rs#L132-L155 version_literal |
toml_edit, [package] or legacy [project] |
tagging the vendored copy's version |
vendor/cargo.rs#L1665-L1680 path_crate_version |
toml_edit, [package] only |
the version a [patch] path points at |
vendor/cargo.rs#L82-L101 declared_cargo_minor |
toml_edit, ad hoc .get("package").get("rust-version") |
the declared cargo floor |
They have drifted. I ran one set of manifests through the crawler, VEX product detection and cargo_tag on 045d7ec, in a throwaway integration test that I ran twice and did not commit. toml_edit parses all of these inputs:
Cargo.toml |
crawler |
VEX product |
cargo_tag |
[package] name/version |
("old", "0.1.0") |
pkg:cargo/[email protected] |
tags it |
| same, with a UTF-8 BOM |
None |
pkg:cargo/[email protected] (strips the BOM) |
tags it |
legacy [project] table |
None |
None |
tags it |
dotted keys (package.name = …) |
None |
None |
tags it |
[package] junk (invalid TOML) |
("old", "0.1.0") |
None |
refuses (Unparseable) |
So a crate whose manifest cargo_tag reads can be invisible to the crawler, and the crawler accepts a manifest that cargo rejects. In a cargo vendor directory the crawler's fallback (the directory name) carries no version, so such a crate cannot be discovered at all. The VEX scanner and the crawler also disagree with each other on BOMs.
Normalized crates.io manifests always use a plain [package] table, so real registry crates hit none of these rows today. The point of this issue is the duplicate parsers and the rules that have already drifted, not a live wrong answer.
Symptoms
Impact: low risk, small size. Deleting the hand-rolled scanner removes a class of "valid TOML the scanner misreads" bugs (the crawler has already needed fixes for header comments and single quotes, according to its own comments).
Proposed change
Add one pure reader in formats/cargo/manifest.rs (or formats/cargo/mod.rs), built on toml_edit:
pub(crate) struct PackageFields { name: Option<String>, version: Inherit<String>, rust_version: Inherit<String>, workspace: Option<String> }
pub(crate) enum Inherit<T> { Literal(T), Workspace, Absent }
pub(crate) fn package_fields(doc: &DocumentMut) -> Option<PackageFields> // [package], else legacy [project]
Then:
- Delete
parse_cargo_toml_name_version, parse_table_header and extract_string_value from cargo_crawler.rs (about 100 lines plus their unit tests). The crawler parses with toml_edit (BOM handled by the parser) and keeps its directory-name fallback for Inherit::Workspace. tests/crawler_cargo_e2e.rs and cargo_crawler/oracle.rs switch to the shared reader.
vex/product.rs parse_cargo_toml uses package_fields (scan_toml_section stays for pyproject.toml, which is E38's).
cargo_tag::version_literal takes its item from the shared lookup and keeps only the span and quote logic.
path_crate_version uses the shared reader. Its [project] blind spot goes away.
plan_cargo_toml's regex dependency scanner in patch/redirect/mod.rs is the other half of E15. It is out of scope here and will be filed separately.
Size and scope
formats/cargo/ (new reader, about 60 lines), crawlers/cargo_crawler.rs (−100), vex/product.rs, vendor/cargo_tag.rs, vendor/cargo.rs.
- Estimated diff: about 150 production lines added, 130 removed, plus tests.
- Out of scope: the hosted
plan_cargo_toml scanner, pyproject parsing, Cargo.lock (already shared through formats::cargo), and the Vendored cargo warns cargo_multi_version_old_cargo ("declares no rust-version") when the root package inherits rust-version from [workspace.package] #651 warning text. Vendored cargo warns cargo_multi_version_old_cargo ("declares no rust-version") when the root package inherits rust-version from [workspace.package] #651 can land here if the reader models rust-version inheritance; otherwise it stays separate.
Acceptance criteria
- One
[package] reader in formats/cargo. No hand-rolled TOML scanner reads Cargo.toml in crawlers/ or vex/product.rs.
- A table test over the rows above (plain, BOM,
[project], dotted keys, inline package = { … }, version.workspace = true, invalid TOML): crawler, VEX product and cargo_tag agree on every row.
-
version.workspace = true still falls back to the directory name in the registry layout (existing crawler tests).
- Green:
cargo test -p socket-patch-core (crawler_cargo_e2e, the cargo_crawler oracle, vex::product, vendor::cargo_tag, vendor::cargo) and cargo clippy --workspace --all-targets.
Dependencies
Activitymikolalysenko commented on Oct 3, 2026 CollaboratorAuthor More actions [agent] Shares root cause with #651: Cargo.toml [package] fields are read through several ad hoc lookups, none of which models { workspace = true } inheritance (declared_cargo_minor, vendor/cargo.rs:82-101, is the one #651 hits). Will be fixed together.
Triaged as priority:p2 (Cargo). Not a duplicate; no open PR covers it (#602 touches the same crawler read sites, not the parser).
Generated by Claude Code mikolalysenko commented on Oct 8, 2026 CollaboratorAuthor More actions [agent] Claiming this issue for the architecture refactor routine (highest leverage: the only scoring candidate whose files no open PR touches; it collapses three Cargo.toml [package] parsers into one). Branch: arch-refactor/693-cargo-manifest-reader. Claim-ID: 2026-10-08T05:55:51Z-7c41a9
Slice taken: the shared formats::cargo::manifest reader, used by the crawler, VEX product detection and cargo_tag. What's left: vendor/cargo.rs (path_crate_version, declared_cargo_minor, and #651's rust-version inheritance), because five open PRs change that file.
Generated by Claude Code mikolalysenko commented on Oct 8, 2026 CollaboratorAuthor More actions
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|