Skip to content

v0.13.0 — Core Engine Rebuild

Choose a tag to compare

@759401524 759401524 released this 11 Aug 02:05
· 48 commits to main since this release

[v0.13.0] — 2026-08-10

Changed

  • Rust MSRV raised to 1.96 and edition bumped to 2024 - both crates now
    declare rust-version = "1.96" and edition = "2024"; CI pins the
    build/test-freethreaded jobs to Rust 1.96 for deterministic wheel builds
    and adds an msrv-check job running cargo check/cargo test at the MSRV
    to prevent silent MSRV drift (the rust-lint job stays on stable).
    The floor is set above PyO3 0.29's own baseline (rustc 1.83) for std API
    headroom (e.g. assert_matches!, stabilized 1.96) with no code migration
    needed. TAG_REGISTRY (tag handler storage) refactored to
    std::sync::LazyLock, dropping the Mutex<Option<...>> indirection.

Performance

  • safe_dump / from_dict / dump_file / dump_iterable: direct writer
    — Python→YAML serialization without intermediate CustomNode AST.
    Single-pass direct_dump replaces the old two-pass pyobject_to_node +
    to_yaml. 7x faster on safe_dump (28ns→4ns), 6x faster on from_dict
    (35ns→6ns). (#60)
  • safe_load / safe_loads / to_dict: fast-path skip anchor tracking
    — when input has no & characters, skip collect_anchors + anchor
    resolution and use the simpler node_to_pyobject_simple path. (#59)
  • resolve_core_type: first-byte dispatch whitelist — non-numeric/
    non-boolean first bytes return Str immediately, avoiding schema
    resolution overhead for the common case. (#59)
  • granit-parser migration — saphyr-parser replaced with granit-parser
    1.0.1 for native Event::Comment emission, eliminating the full-text
    scan_yaml() pre-scan. parse_small -18%, parse_large -21%,
    roundtrip_large -18%.

Fixed

  • float_to_yaml_string round-trip fix — appends .0 when Rust
    Display drops the decimal (4242.0) so floats round-trip as
    floats instead of becoming ints.
  • Reverted count_nodes pre-allocation — the full AST traversal cost
    more than the reallocations it avoided (serialize_10mb was ~14% slower);
    buffer growth is left to the Vec.

Added

  • max_depth on stream & frontmatter APIsparse_stream(yaml, on_event, max_depth),
    read_markdown(path, schema, max_depth), read_markdown_str(content, schema, max_depth)
    accept max_depth (default 1000). Stream parsing now enforces the nesting-depth limit
    via core parse_stream_with_options (previously stream events had no depth limit).
  • Pydantic integrationdump_pydantic() serializes a Pydantic model
    to YAML string via model_dump(mode='json') + safe_dump; parse_as()
    parses YAML string into a Pydantic model instance. Both use lazy imports,
    no hard dependency on pydantic. (#61)

Internal

  • Split py/mod.rs — monolithic 1786-line module broken into
    document.rs (YamlDocument), yaml_instance.rs (YAML class),
    functions.rs (module-level functions), stream_iterator.rs,
    walk_helpers.rs. mod.rs reduced to 128 lines. (#61)
  • needs_quotes() guard + double_quoted_scalar() constructor
    strings like 'true' / '42' / 'null' now emit as double-quoted
    scalars under the core schema instead of being misread on re-parse
    (pyobject_to_node + json_value_to_node).
  • CodSpeed benchmarks unified on codspeed-divan-compat
    exclude-allocations removes allocator noise; cross-library benchmarks
    consolidated into tests/test_benchmark_crosslib.py with shared
    tests/data/yaml_samples.py fixtures and streaming coverage.