1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//! # sefer-region — typed handle-addressed store
//!
//! A thin typed membrane over [`slotmap`](https://docs.rs/slotmap): values live
//! in `slotmap::SlotMap` — a contiguous slot array resolved by a single
//! indirection (the lookup/churn axis it was benchmarked to win; see
//! <https://github.com/PHPCraftdream/sefer-alloc/blob/main/docs/BENCHMARKS.md>). `SlotMap` keeps tombstone holes after removals, so it
//! is NOT always-compact; `DenseSlotMap` is the dense-iteration alternative.
//! Every operation exposes only typed [`Handle<T>`] values — raw `DefaultKey`s
//! never escape as usable values through the API (Debug output renders the
//! underlying key for diagnostics only — it cannot be turned back into a
//! functioning handle through this crate's public surface).
//!
//! **Runtime relationship to `sefer-alloc`:** This crate exists as a public
//! surface for the `sefer-alloc` workspace root crate (which re-exports
//! `Region`, `Handle`, and `SyncRegion`), but it is **not used by the
//! `sefer-alloc` allocator runtime itself**. Empirically verified by searching
//! the allocator source code (`src/`) in the main workspace: no direct calls
//! into `Region`/`Handle`/`SyncRegion` on any hot path. Further API evolution
//! is intentionally deferred until a confirmed external consumer requests it.
//!
//! ## What makes this different from using slotmap directly?
//!
//! Slotmap's `DefaultKey` is untyped: a `DefaultKey` from one map can be passed
//! to another of a different value type without a compile error. `sefer-region`
//! wraps it in `Handle<T>` — a `PhantomData<fn() -> T>`-branded key plus a
//! `region_id` — so the compiler rejects cross-**type** handle confusion at the
//! type level (a `Handle<Foo>` cannot be used where a `Handle<Bar>` is
//! expected), and the runtime `region_id` check rejects cross-**instance**
//! handle confusion at the value level: a `Handle<T>` minted by one
//! `Region<T>` is rejected (treated exactly like a stale handle — `None`/
//! `false`, no panic) by every *other* `Region<T>` of the same type, even one
//! whose slotmap key happens to collide with the handle's own key.
//!
//! ## Invariants upheld (I1–I7)
//!
//!
//! ## Pure Rust / zero own unsafe
//!
//! `#![forbid(unsafe_code)]` at the top of this crate. The internal `unsafe`
//! lives upstream, in the mature, widely-used `slotmap` dependency, not in
//! this crate. This crate adds no C / C++ libraries and contributes zero
//! `unsafe` blocks of its own.
//!
//! ## `no_std` support
//!
//! With `default-features = false` (disabling `std`) the crate compiles under
//! `no_std + alloc`, providing [`Region<T>`] and [`Handle<T>`]. The `std`
//! feature (on by default) additionally enables [`SyncRegion<T>`], which wraps
//! `Region<T>` in `std::sync::RwLock`.
compile_error!;
pub use Handle;
pub use ;
// Test-only forwarder (see its own doc comment in `region.rs`): exposes the
// `region_id`-minting helper to integration tests in `tests/`, which can
// only reach items re-exported from the crate root. `#[doc(hidden)]` keeps
// it off docs.rs; this is not part of the public API.
pub use dbg_try_mint_region_id;
pub use SyncRegion;