Skip to content

v2.1.0

Latest

Choose a tag to compare

@noahbaculi noahbaculi released this 10 Jun 19:29
· 28 commits to main since this release

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-version in Cargo.toml). This follows pathfinding 4.15.0, which moved to Rust edition 2024 and so requires 1.87. The bump carries no functional change for this crate. The only yen-related fix in 4.15.0 is a panic when k == 0, which is unreachable here because num_arrangements is a validated NonZeroU8, so the k passed to yen is always at least 1. Consumers on a toolchain below 1.87 need to run rustup update.

Internal

  • Moved the TypeScript-surface derive from tsify-next back to tsify. RUSTSEC-2025-0048 flags tsify-next as unmaintained, and its own final 0.5.6 release carries a deprecation notice pointing to tsify. Both crates sit at 0.5.6 with the same js feature and #[derive(Tsify)] attributes, so the change is the crate name in Cargo.toml plus three use statements. The generated .d.ts public surface is unchanged except for one doc comment that named the old crate, pinned by the tests/snapshots/wasm.d.ts snapshot. See ADR-0010.

  • Index yen() successors by node group instead of re-scanning the full node list. calc_next_nodes now looks up the one contiguous beat group through path_node_groups rather than filtering a flattened Vec<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 the fur_elise_3_arrangements and fur_elise_5_arrangements benches fell about 22% (roughly 21.6 ms to 16.7 ms) while the untouched parse_lines control 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 average dependency and compute the non-zero-fret mean inline. This removes eight crates from the non-dev dependency graph (average, rayon, rayon-core, the three crossbeam-* 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 existing calc_avg_non_zero_fret tests.

  • Compile the pitch regex once into a process-lifetime LazyLock<Regex> static instead of rebuilding it on every cache-missing parse_lines call. Behavior is unchanged. The parse_lines bench, 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 push instead 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. The render_tab bench fell roughly 4 to 6% against the prior commit in CI, while the untouched parse_lines and fur_elise_1_arrangement benches 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_max with a digit-count check instead of allocating a String per fingering to read its length. The width is identical for any fret and reuses the same digit rule render_fret already applies. The render_tab bench 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 String instead of cloning each row into a Vec<String> and joining it. render_string_output now pushes each borrowed row and writes the / playback lines in place, dropping the per-row clone, the intermediate vector, the second copy from join, and the " ".repeat(..) playback-indent temp string. Render output is unchanged (PRD finding F6), pinned by the render snapshot tests. The render_tab bench fell roughly 11% against the prior commit in CI (about 56.4 µs to 50.2 µs across the parameter sweep), while the untouched parse_lines and fur_elise_1_arrangement benches held flat. (Indicative cross-run CI figure, not a persisted baseline.)

Full Changelog: v2.0.0...v2.1.0