Skip to content

v1.0.0 - Stable

Latest

Choose a tag to compare

@jamesgober jamesgober released this 18 May 14:24

Release Notes for v1.0.0 - Stable

Version 1.0.0 - 2026-05-18

The first stable release. API surface is locked under SemVer. Breaking changes from here require a major-version bump; additive features ship as minor bumps; bug fixes as patch bumps. CI enforces this via cargo-semver-checks and a new cargo public-api diff workflow that fails any PR which changes the public surface without an explicit snapshot update.

API-compatible with 0.9.11. Callers on 0.9.11 upgrade by bumping the version string in Cargo.toml and nothing else. Callers still on 0.9.6 or earlier should read docs/MIGRATION_0.9_TO_1.0.md for the recovery path.

What ships in 1.0.0

  • Anonymous mappings. AnonymousMmap::new(size) returns a process-local, RW memory region with no backing file. Pages are zero-initialized on first touch; memory is released when the value drops. Useful for shared scratch memory between threads, large temporary allocations that bypass the heap, or as the kernel-side substrate for fd-passing IPC patterns. Closes audit F1, the longest-standing gap in the inventory.
  • Hugepage runtime introspection. mmap.is_hugepage_backed() -> Option<bool> answers the question "did the kernel actually back my mapping with huge pages?" On Linux, parses /proc/self/smaps and inspects the AnonHugePages / Private_Hugetlb / Shared_Hugetlb fields. On other platforms returns None. Pairs with the existing hugepages feature to close the loop on a previously best-effort capability. Closes audit F4.
  • Multi-process IPC integration test. tests/ipc_cross_process.rs verifies bidirectional cross-process byte visibility through a single mmap'd file: parent writes a magic value, spawns child via std::process::Command::new(std::env::current_exe()), child reads parent's writes and writes its own bytes, parent verifies the child's writes. The crate has always supported this pattern; now it has a dedicated regression test. Closes audit T6.
  • Sparse-file behavior documented. create_rw and open_or_create now explicitly document that set_len(size) produces a sparse file on every supported platform: a 1 TB default_size does not consume 1 TB of free disk until pages are written. Closes audit F6.
  • # Errors / # Panics rustdoc completeness pass. Every Result-returning public method now documents its error conditions; every method that calls .expect() documents its panic conditions. The crate already enforced #![deny(missing_docs)]; now clippy::missing_errors_doc and clippy::missing_panics_doc also pass clean.
  • public-api.txt snapshot committed. A cargo public-api --simplified --all-features dump of the locked surface lives in the repo root. A new CI workflow regenerates it on every PR and fails the build if the diff is non-empty without an accompanying snapshot update. This catches accidental API changes at PR review time, not at release time. The 0.9.7 incident (a patch release that silently broke as_slice) cannot happen again.

Stability commitment

From this release forward:

  • Major version bumps (2.0.0+) are reserved for genuine breaking changes. They will be telegraphed in advance through deprecation warnings and migration notes.
  • Minor bumps (1.1.0+) ship additive features. New methods, new types, new feature flags. Existing code keeps compiling.
  • Patch bumps (1.0.1+) ship bug fixes, perf improvements, internal refactors, and documentation polish. No public-surface changes.

cargo-semver-checks runs on every PR against the latest published version. The public-api workflow runs on every PR against the committed snapshot. Either check failing is a blocking gate, not advisory.

The path from 0.9.x

mmap-io was first published at 0.1.0 on 2025-08-05. The 0.9.x series ran from 0.9.0 through 0.9.11 over the course of the prior year, with the bulk of the load-bearing work in the final months:

  • 0.9.5: Three critical correctness bugs closed. flush_range accumulator math, EveryMillis flush-policy lifetime, atomic-view UAF across resize.
  • 0.9.6: Unsafe audit. Every unsafe block re-justified with platform-spec citations; property-test suite added.
  • 0.9.7: Performance milestone. Zero-copy iterators (13.2x at 4 KiB, 475x at 64 KiB), zero-copy as_slice on RW mappings, touch_pages tight-loop rewrite (~50-100x). This release also accidentally shipped breaking signature changes as a patch bump, a SemVer violation that carried for four releases.
  • 0.9.8: Ergonomic surface (audit E1-E7, F2, F5, F9). open_or_create, from_file, unmap, raw pointer access, prefetch, builder polish.
  • 0.9.9: Native file-change watchers via inotify / FSEvents / ReadDirectoryChangesW.
  • 0.9.10: Pre-1.0 stabilization. Fuzz scaffold, ten focused examples, docs/PERFORMANCE.md with measured numbers, cargo-audit and cargo-semver-checks CI workflows, bench-regression hard gate.
  • 0.9.11: Field-issue response. Compat shims for the 0.9.7 violation (as_slice_bytes, for_each_mut_legacy), runtime-agnostic async (smol works), bytes::Bytes integration, io::Read + io::Seek cursor, AsFd / AsRawFd / AsHandle / AsRawHandle trait impls.

1.0.0 is the result of that work. The code base is the same one that has been running through 0.9.11; this release adds the four 1.0-bracket items (F1, F4, T6, F6), the doc-completeness pass, and the SemVer enforcement infrastructure.

What 1.0.0 does NOT include

A handful of items from the audit are explicitly deferred to post-1.0:

  • sync_file_range (Linux). A niche fast path for some DB workloads. No external request to date.
  • Custom allocator hook. Speculative; will land when a real consumer asks.
  • Additional platform targets (FreeBSD, illumos). Mostly CI plumbing; the POSIX path already covers them in source.
  • MmapInventory::all_open() diagnostic. Probably belongs in a separate diagnostics crate.
  • Memory-pressure callbacks. Speculative; pattern unclear without a concrete consumer.

These are tracked in .dev/ROADMAP.md under "post-1.0 long-term work" and will ship as additive 1.x minor bumps when there is a real consumer.

Tests

  • 158 tests pass under --all-features (up from 140 in 0.9.11), 1 ignored (the unrelated hugepages-fallback test), 0 failed.
  • 17 new tests in tests/v1_0_0_additions.rs cover the AnonymousMmap surface and is_hugepage_backed.
  • 1 new test in tests/ipc_cross_process.rs covers cross-process byte visibility.
  • cargo build (default / no-default / all-features), cargo +1.75 build --all-features (MSRV), cargo fmt --check, cargo clippy --all-targets --all-features -D warnings, cargo doc --no-deps --all-features, cargo audit --deny warnings, cargo semver-checks check-release, and cargo public-api snapshot diff all clean.

Internals

  • New module src/anonymous.rs exporting AnonymousMmap.
  • is_hugepage_backed and the smaps parser live in src/mmap.rs behind #[cfg(target_os = "linux")] (returns None on other platforms).
  • MappedSliceMut gains a pub(crate) fn guarded constructor so the anonymous module can build write-guarded slices without duplicating the field-access boilerplate.
  • Bench-only fix: Arc import in benches/mmap_bench.rs gated behind #[cfg(feature = "atomic")] to match its sole call site.
  • New CI workflow .github/workflows/public-api.yml runs the diff check.

Notes

  • MSRV unchanged at Rust 1.75.
  • No new dependencies in the production tree. tempfile remains dev-only.
  • The 0.9.7-introduced API surface (MappedSlice, the zero-copy iterators, the flattened for_each_mut) is the recommended path for new code; the compat shims from 0.9.11 (as_slice_bytes, for_each_mut_legacy, chunks_owned) are preserved in 1.0.0 and will not be deprecated.

Full Changelog: v0.9.11...v1.0.0