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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use NonZeroU32;
pub use CursorMut;
pub use Entry;
pub use IntoIter;
pub use Iter;
pub use OccupiedEntry;
pub use VacantEntry;
extern crate alloc;
type RandomState = RandomState;
type RandomState = DefaultHashBuilder;
/// A hash map that maintains the relative order of entries, implemented as a
/// doubly-linked list backed by a hash table for O(1) lookups.
///
/// This is the main type alias using the default hasher. For custom hashers,
/// use [`linked_hash_map::LinkedHashMap`] directly.
///
/// # Examples
///
/// ```
/// use tether_map::LinkedHashMap;
///
/// let mut map = LinkedHashMap::new();
/// map.insert("a", 1);
/// map.insert("b", 2);
///
/// // Maintains relative order
/// let entries: Vec<_> = map.iter().collect();
/// assert_eq!(entries, [(&"a", &1), (&"b", &2)]);
/// ```
pub type LinkedHashMap<K, V> = crateLinkedHashMap;
/// A pointer type used to identify entries in the linked hash map.
///
/// This is an opaque handle that can be used to directly access entries
/// without key lookup. It provides O(1) access to entries.
///
/// By default, `Ptr` is **non-generational**, meaning that once an entry is
/// removed, the pointer may be re-used for a new entry. With the `generational`
/// feature enabled, `Ptr` includes generation tracking that will panic or
/// return None when attempting to use a stale pointer after its entry has been
/// removed.
///
/// # Examples
///
/// ```
/// # #[cfg(not(feature = "generational"))] {
/// use tether_map::Entry;
/// use tether_map::LinkedHashMap;
/// use tether_map::Ptr;
///
/// let mut map = LinkedHashMap::new();
/// let ptr = match map.entry("key") {
/// Entry::Vacant(entry) => entry.insert_tail(42).0,
/// Entry::Occupied(entry) => entry.ptr(),
/// };
///
/// // Use the pointer for direct access
/// assert_eq!(map.ptr_get(ptr), Some(&42));
///
/// // Remove the entry
/// map.remove(&"key");
///
/// // Using the stale pointer is a logic error but will not panic
/// assert_eq!(map.ptr_get(ptr), None);
///
/// // Insert a new entry, which may reuse the same Ptr value
/// map.insert("key", 100);
///
/// // The old pointer is stale, but may point to the new entry by coincidence
/// // This may work or not depending on whether the same Ptr value was reused:
/// // assert_eq!(map.ptr_get(ptr), Some(100));
///
/// # }
/// ```
///
/// With the `generational` feature enabled, using a stale pointer will return
/// None or panic:
///
/// ```
/// # #[cfg(feature = "generational")] {
/// use tether_map::Entry;
/// use tether_map::LinkedHashMap;
/// use tether_map::Ptr;
///
/// let mut map = LinkedHashMap::new();
/// let ptr = match map.entry("key") {
/// Entry::Vacant(entry) => entry.insert_tail(42).0,
/// Entry::Occupied(entry) => entry.ptr(),
/// };
///
/// // Remove the entry
/// map.remove(&"key");
///
/// // Using the stale pointer will return None or panic
/// assert_eq!(map.ptr_get(ptr), None);
///
/// // Insert a new entry, which may reuse the same Ptr value
/// map.insert("key", 100);
/// // The old pointer is stale, so this will definitely return None
/// assert_eq!(map.ptr_get(ptr), None);
///
/// # }
/// ```