Maintenance release: no new features and no public API change, so the Rust and .d.ts surfaces stay byte-identical to 2.0.0. It swaps tsify-next -> tsify to clear RUSTSEC-2025-0048, raises the MSRV to Rust 1.87, and lands a batch of allocation and pathfinding cleanups that speed up arrangement generation and rendering.
Changed
- Raised the minimum supported Rust version to 1.87, up from 1.86 (
rust-versioninCargo.toml). This followspathfinding4.15.0, which moved to Rust edition 2024 and so requires 1.87. The bump carries no functional change for this crate. The onlyyen-related fix in 4.15.0 is a panic whenk == 0, which is unreachable here becausenum_arrangementsis a validatedNonZeroU8, so thekpassed toyenis always at least 1. Consumers on a toolchain below 1.87 need to runrustup update.
Internal
-
Moved the TypeScript-surface derive from
tsify-nextback totsify. RUSTSEC-2025-0048 flagstsify-nextas unmaintained, and its own final 0.5.6 release carries a deprecation notice pointing totsify. Both crates sit at 0.5.6 with the samejsfeature and#[derive(Tsify)]attributes, so the change is the crate name inCargo.tomlplus threeusestatements. The generated.d.tspublic surface is unchanged except for one doc comment that named the old crate, pinned by thetests/snapshots/wasm.d.tssnapshot. See ADR-0010. -
Index
yen()successors by node group instead of re-scanning the full node list.calc_next_nodesnow looks up the one contiguous beat group throughpath_node_groupsrather than filtering a flattenedVec<Node>, which drops the adjacency term from roughly O(k * N^2) toward O(group size) on multi-arrangement and long inputs. Arrangement output is byte-for-byte unchanged. In CI thefur_elise_3_arrangementsandfur_elise_5_arrangementsbenches fell about 22% (roughly 21.6 ms to 16.7 ms) while the untouchedparse_linescontrol held flat. The single-arrangement long-input bench moved only 1 to 3%, matching the O(k * N^2) shape where the win scales with the arrangement count k. (Indicative cross-run CI figures.) -
Dropped the
averagedependency and compute the non-zero-fret mean inline. This removes eight crates from the non-dev dependency graph (average,rayon,rayon-core, the threecrossbeam-*crates,easy-cast,float-ord), so Rayon no longer compiles into the production or WASM build. That restores ADR-0009's no-Rayon state and slightly shrinks the size-optimized WASM artifact. The mean is arithmetically identical, pinned by the existingcalc_avg_non_zero_frettests. -
Compile the pitch regex once into a process-lifetime
LazyLock<Regex>static instead of rebuilding it on every cache-missingparse_linescall. Behavior is unchanged. Theparse_linesbench, which reparses each iteration, fell from roughly 285 µs to 77 µs in CI (about a 3.7x speedup), since regex compilation dominated the per-parse cost and now runs once for the process. (Indicative cross-run CI figure.) -
Pad a rendered row's trailing dashes in place with
pushinstead of building and copying a throwaway"-".repeat(..)String. The row buffer already reserves the full width, so the bytes have a home. Render output is unchanged, pinned by the render snapshot tests. Therender_tabbench fell roughly 4 to 6% against the prior commit in CI, while the untouchedparse_linesandfur_elise_1_arrangementbenches held flat, so the gain tracks this change rather than runner variance. (Indicative cross-run CI figure, not a persisted baseline.) -
Measure each fret's display width in
calc_fret_width_maxwith a digit-count check instead of allocating aStringper fingering to read its length. The width is identical for any fret and reuses the same digit rulerender_fretalready applies. Therender_tabbench fell a further 3.5 to 4.5% in CI, roughly 8 to 9% cumulative across the two render cleanups. -
Build the rendered tab body directly into a single
Stringinstead of cloning each row into aVec<String>and joining it.render_string_outputnow pushes each borrowed row and writes the▼/▲playback lines in place, dropping the per-row clone, the intermediate vector, the second copy fromjoin, and the" ".repeat(..)playback-indent temp string. Render output is unchanged (PRD finding F6), pinned by the render snapshot tests. Therender_tabbench fell roughly 11% against the prior commit in CI (about 56.4 µs to 50.2 µs across the parameter sweep), while the untouchedparse_linesandfur_elise_1_arrangementbenches held flat. (Indicative cross-run CI figure, not a persisted baseline.)
Full Changelog: v2.0.0...v2.1.0