This file provides guidance to AI coding assistants when working with code in this repository.
@GOTCHAS.md
mmap-guard is a Rust library that wraps memmap2::Mmap::map() behind a safe API, so downstream crates can use #![forbid(unsafe_code)] while still benefiting from zero-copy file access. See KICKOFF.md for the full design spec and API sketch.
The core motivation is isolation: by centralizing the unsafe boundary in a single, focused crate, we can concentrate testing, fuzzing, and hardening efforts on that one point. This library should provide all reasonable protections against common mmap threats (SIGBUS from truncation, empty files, permission errors) so consumers don't have to reason about them.
Key design constraints:
- This crate contains the single
unsafeblock (thememmap2call) — it is NOT#![forbid(unsafe_code)] - Must enforce
#![deny(clippy::undocumented_unsafe_blocks)] - Read-only mappings only; no mutable/writable mappings
- The unsafe boundary should be exhaustively tested and hardened — prioritize safety coverage
- Rust edition 2024, stable toolchain
- See GOTCHAS.md for unsafe code rules and downstream expectations.
# Build
cargo build
# Test (prefer nextest)
cargo nextest run
cargo nextest run <test_name> # single test
cargo test # fallback if nextest unavailable
# Lint
cargo fmt --check
cargo clippy -- -D warnings
# Coverage
cargo llvm-cov # requires cargo-llvm-cov via mise
# Security audits
cargo audit
cargo deny check
# Format
cargo fmt
# All tools managed via mise — run `mise install` to bootstrapPre-commit is configured (.pre-commit-config.yaml) and runs on commit:
cargo fmt,cargo clippy -- -D warnings,cargo check- cargo-machete (unused dependencies), cargo-audit, cargo-sort
- mdformat on markdown (excludes
.claude/) - See GOTCHAS.md for pre-commit re-staging pitfalls.
.github/CODEOWNERSassigns@unclesp1d3ras reviewer for*.rsfiles only (notCargo.toml/Cargo.lock, to avoid blocking dependabot).- Mergify merge queue is enabled for bot PRs (dependabot, dosubot, release-plz). Human PRs are not auto-queued.
FileDatahas a compile-timeSend + Syncassertion (const block infile_data.rs) -- do not remove it; it guards against regressions if variant types change.- All public functions (
map_file,load,load_stdin) carry#[must_use]-- maintain this for any new public API.
The crate is a thin library with four source files:
src/lib.rs— crate-level docs, re-exports public APIsrc/file_data.rs—FileDataenum (Mapped(Mmap, File)|Loaded(Vec<u8>)),Deref<Target=[u8]>,AsRef<[u8]>src/map.rs—map_file()with pre-flight stat check; contains the singleunsafeblocksrc/load.rs—load()routes"-"toload_stdin(Some(1 GiB)); other paths tomap_file().load_stdin(max_bytes)reads stdin into a heap buffer with optional byte cap
Runtime dependencies: memmap2, fs4 (advisory file locking). Dev-dependencies: tempfile, proptest.
Coverage-guided fuzzing via cargo-fuzz (nightly) and property tests via proptest (stable).
The fuzz/ directory is a separate Cargo workspace (not published). It depends on mmap-guard with the __fuzz feature to access internal functions.
# Install cargo-fuzz (one-time)
cargo install cargo-fuzz --locked
# Run a fuzz target (nightly required)
cargo +nightly fuzz run fuzz_read_bounded -- -max_total_time=60
cargo +nightly fuzz run fuzz_map_file -- -max_total_time=60
# List available targets
cargo +nightly fuzz listTargets:
fuzz_read_bounded— structured input (Arbitrary) exercising the bounded-read logic with fuzzer-controlled data and capfuzz_map_file— writes fuzzer bytes to a temp file, maps it, asserts round-trip integrity
tests/prop_map_file.rs— proptest integration test formap_fileround-tripsrc/load.rsmod tests::prop— proptest forread_bounded(unit test, has access to private API)
The __fuzz feature exposes read_bounded (normally private) as #[doc(hidden)] pub. It is not part of the public API — the leading underscores signal internal-only use. Only the fuzz crate enables it.
.github/workflows/fuzz.yml— weekly nightly fuzzing + merge queue gate, matrix over targets, uploads crash artifacts on failure.github/workflows/compat.yml— weekly Rust version compatibility matrix (stable, stable minus 2, stable minus 5, MSRV 1.85) + merge queue gate, runs build + tests with default features- Both fuzz and compat workflows use the two-step CI pattern: they trigger on
pull_requestbut skip on regular PRs viaif: startsWith(github.head_ref, 'mergify/merge-queue/'). Mergify'smerge_conditionsusecheck-success-or-neutralso skipped jobs pass on regular PRs but block merge if they fail in the queue.
- Clippy denies
unwrap_usedandpanic; warns onexpect_used— test modules need#[allow(clippy::unwrap_used, clippy::expect_used)] undocumented_unsafe_blocks = "deny"— everyunsafeblock must have a// SAFETY:comment- Full pedantic/nursery/cargo lint groups enabled (see
[workspace.lints.clippy]in Cargo.toml) - See GOTCHAS.md for clippy and rustdoc edge cases.
All dev workflows use just (see justfile):
just ci-check— full local CI parity (fmt, clippy, test, audit, coverage)just test/just test-ci— run nextestjust coverage/just coverage-check— llvm-cov (85% threshold)just lint— fmt + clippy + actionlint + markdownlintjust audit/just deny— security checks- See GOTCHAS.md for CI and tooling edge cases.