tether_map/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(feature = "std"), no_std)]
3#![deny(missing_docs)]
4
5mod arena;
6pub mod linked_hash_map;
7
8extern crate alloc;
9
10#[cfg(feature = "std")]
11type RandomState = std::hash::RandomState;
12#[cfg(not(feature = "std"))]
13type RandomState = hashbrown::DefaultHashBuilder;
14
15/// A hash map that maintains the relative order of entries, implemented as a
16/// doubly-linked list backed by a hash table for O(1) lookups.
17///
18/// This is the main type alias using the default hasher. For custom hashers,
19/// use [`linked_hash_map::LinkedHashMap`] directly.
20///
21/// # Examples
22///
23/// ```
24/// use tether_map::LinkedHashMap;
25///
26/// let mut map = LinkedHashMap::new();
27/// map.insert("a", 1);
28/// map.insert("b", 2);
29///
30/// // Maintains relative order
31/// let entries: Vec<_> = map.iter().collect();
32/// assert_eq!(entries, [(&"a", &1), (&"b", &2)]);
33/// ```
34pub type LinkedHashMap<K, V> = crate::linked_hash_map::LinkedHashMap<K, V, RandomState>;
35use core::num::NonZeroU32;
36
37pub use linked_hash_map::CursorMut;
38pub use linked_hash_map::Entry;
39pub use linked_hash_map::IntoIter;
40pub use linked_hash_map::Iter;
41pub use linked_hash_map::OccupiedEntry;
42pub use linked_hash_map::VacantEntry;
43
44#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
45#[repr(transparent)]
46/// A pointer type used to identify entries in the linked hash map.
47///
48/// This is an opaque handle that can be used to directly access entries
49/// without key lookup. It provides O(1) access to entries. It is
50/// **non-generational**, meaning that once an entry is removed, the pointer may
51/// be re-used for a new entry.
52///
53/// # Examples
54///
55/// ```
56/// use tether_map::Entry;
57/// use tether_map::LinkedHashMap;
58/// use tether_map::Ptr;
59///
60/// let mut map = LinkedHashMap::new();
61/// let ptr = match map.entry("key") {
62///     Entry::Vacant(entry) => entry.insert_tail(42).0,
63///     Entry::Occupied(entry) => entry.ptr(),
64/// };
65///
66/// // Use the pointer for direct access
67/// assert_eq!(map.ptr_get(ptr), Some(&42));
68/// ```
69pub struct Ptr(NonZeroU32);
70
71impl core::fmt::Debug for Ptr {
72    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
73        write!(f, "Ptr({})", self.0.get() - 1)
74    }
75}
76
77impl Ptr {
78    pub(crate) fn unchecked_from(index: usize) -> Self {
79        debug_assert!(
80            index < u32::MAX as usize,
81            "Index too large to fit in Ptr: {index}"
82        );
83        Ptr(NonZeroU32::new((index as u32).saturating_add(1)).unwrap())
84    }
85
86    pub(crate) fn unchecked_get(self) -> usize {
87        self.0.get() as usize - 1
88    }
89}