arena-lib 0.9.0

Typed memory arena and slab allocator library. Generational indices, typed arenas (one allocation per type), interned strings, and bump allocation. Zero unsafe leakage into user code.
Documentation

Why arena-lib

Allocator-aware Rust normally means juggling three or four crates: one for slab storage, one for handle stability, one for string interning, plus a bump arena for short-lived scratch. arena-lib collects those primitives behind a single, safe, REPS-disciplined surface so you can move fast without paying for it later.

Designed around four guarantees:

  • Typed arenas — one backing allocation per element type, predictable layout, cache-friendly traversal.
  • Generational indices — stable handles that catch use-after-free without reference counting.
  • String interning — O(1) equality and compact storage for repeated identifiers.
  • Bump allocation — short-lived scratch regions that reset in constant time.

Every public path is safe Rust. unsafe lives only in measured, documented internals — never in your call sites.

Status: v0.9.0 (Hardening + Audit). The 0.5 surface is feature-frozen; every public item carries a documented example, property tests cover the arena, interner, bump, and drop-arena invariants, and a runnable examples/quick_start.rs exercises all four primitives end-to-end. Audit findings are logged in docs/release/v0.9.0.md. Next release is the 1.0 freeze.


Quick start

Add the crate to your Cargo.toml:

[dependencies]
arena-lib = "0.9"

End-to-end use of every primitive:

use arena_lib::prelude::*;

fn main() {
    // Generational arena — stable handles, use-after-free detection.
    let mut arena: Arena<&'static str> = Arena::with_capacity(8);
    let alice = arena.insert("alice");
    let bob = arena.insert("bob");
    assert_eq!(arena.get(alice), Some(&"alice"));

    // String interner — O(1) equality on repeated identifiers.
    let mut interner = Interner::with_capacity(8);
    let id_a = interner.intern("user:alice");
    let id_b = interner.intern("user:alice");
    assert_eq!(id_a, id_b);

    // Bump arena — fast scratch, grows on demand, O(1) reset.
    let bump = Bump::with_capacity(64);
    let scratch = bump.alloc([0_u8; 16]);
    assert_eq!(scratch.len(), 16);

    // Drop arena — same ergonomics but runs destructors on drop.
    let owned = DropArena::<String>::new();
    let s = owned.alloc(String::from("freed when `owned` is dropped"));
    assert!(s.contains("dropped"));

    // Removing a slot invalidates its handle without touching the rest.
    assert_eq!(arena.remove(alice), Some("alice"));
    assert!(arena.get(alice).is_none());
    assert!(arena.get(bob).is_some());
}

See docs/API.md for the full reference, including the planned 1.0 surface.


Standards

  • REPS governs every decision. See REPS.md.
  • MSRV: Rust 1.85.
  • Edition: 2024.
  • Cross-platform: Linux, macOS, Windows.

License

Dual-licensed under either of:

at your option.