rc_hashmap/
lib.rs

1//! rc-hashmap: A single-threaded, handle-based map with Rc-like
2//! references to entries that allow fast access and cleanup on drop.
3//!
4//! Internal Design:
5//!
6//! Summary
7//! - Goal: build RcHashMap in safe, verifiable layers so each piece can
8//!   be reasoned about independently.
9//! - Layers:
10//!   - HandleHashMap<K, V, S>: structural map that returns stable
11//!     handles for O(1) average access without re-hashing; includes a
12//!     debug-only reentrancy guard to keep internals consistent while
13//!     mutating.
14//!   - CountedHashMap<K, V, S>: wraps HandleHashMap and adds per-entry
15//!     reference counting (increments on get/clone, decrements on put).
16//!   - RcHashMap<K, V, S>: public API that exposes `Ref` handles; drops
17//!     free entries when the last `Ref` is dropped.
18//!
19//! Constraints
20//! - Single-threaded: `!Send`/`!Sync` by design (no atomics).
21//! - No per-entry heap allocations beyond the map’s own storage.
22//! - Stable, generational keys behind small `Handle` wrappers.
23//! - O(1) average lookups with unique keys; duplicate inserts fail.
24//! - Reentrancy: disallowed during critical sections of HandleHashMap
25//!   (only `K: Eq/Hash` may run); allowed elsewhere.
26//!
27//! Why this split?
28//! - Localize invariants: each layer has a small, precise contract.
29//! - Minimize unsafe: raw-pointer handling is isolated in `tokens::RcCount`;
30//!   structural indexing uses safe Rust.
31//! - Clear failure boundaries: HandleHashMap never calls into user code
32//!   once the structure is consistent.
33//!
34//! Reentrancy policy and interior mutability
35//! - HandleHashMap employs an internal exclusive-access discipline and a
36//!   debug-only reentrancy guard at the start of each method to prevent
37//!   nested entry while its internal state can be transiently
38//!   inconsistent. These methods only invoke user code via `K: Eq/Hash`
39//!   during probing.
40//! - Upper layers (CountedHashMap, RcHashMap) rely on HandleHashMap’s
41//!   guarantees and do not need their own guard. After
42//!   `HandleHashMap::remove` returns `(K, V)`, the structure is again
43//!   consistent; `Drop` for `K`/`V` may reenter safely.
44//!
45//! Overflow semantics
46//! - Reference-count overflow is considered undefined behavior, matching
47//!   `Rc`. The crate assumes there are fewer than `usize::MAX` references
48//!   to any entry; no runtime checks are performed.
49//!
50//! Hasher and rehashing invariants
51//! - Each entry stores a precomputed `u64` hash and indexing always uses
52//!   the stored hash; `K: Hash` is never invoked after insertion. This
53//!   avoids rehash-time calls into user code.
54//!
55//! Notes and non-goals
56//! - Still single-threaded; enforced with marker types on `Ref`/`Inner`.
57//! - No weak handles (could be added later).
58//! - No explicit `clear()`/`remove()`/`drain()` on RcHashMap; removal
59//!   occurs when the last `Ref` is dropped to preserve refcount
60//!   semantics.
61//! - RcHashMap does not implement `Clone`.
62//! - Keys are immutable post-insert; there is no `key_mut`.
63//! - Public API surface is `RcHashMap` and its `Ref`; lower layers are
64//!   implementation details.
65//!
66//! Implementation note
67//! - The internal `RcCount<T>` helper (in `tokens`) encapsulates the
68//!   raw-pointer based use of `std::rc::Rc` increment/decrement APIs.
69
70pub mod counted_hash_map;
71pub mod handle_hash_map;
72mod handle_hash_map_proptest;
73pub mod hash;
74mod rc_hash_map;
75mod reentrancy;
76pub mod tokens;
77
78// Public surface
79pub use handle_hash_map::InsertError;
80pub use hash::DefaultHashBuilder;
81pub use rc_hash_map::{RcHashMap, Ref};