@@ -21,9 +21,145 @@ use core::mem;
21
21
/// See the [`raw_entry_v1`][self] module documentation for more information.
22
22
pub trait RawEntryApiV1 < K , V , S > : private:: Sealed {
23
23
/// Creates a raw immutable entry builder for the [`IndexMap`].
24
+ ///
25
+ /// Raw entries provide the lowest level of control for searching and
26
+ /// manipulating a map. They must be manually initialized with a hash and
27
+ /// then manually searched.
28
+ ///
29
+ /// This is useful for
30
+ /// * Hash memoization
31
+ /// * Using a search key that doesn't work with the [`Equivalent`] trait
32
+ /// * Using custom comparison logic without newtype wrappers
33
+ ///
34
+ /// Unless you are in such a situation, higher-level and more foolproof APIs like
35
+ /// [`get`][IndexMap::get] should be preferred.
36
+ ///
37
+ /// Immutable raw entries have very limited use; you might instead want
38
+ /// [`raw_entry_mut_v1`][Self::raw_entry_mut_v1].
39
+ ///
40
+ /// # Examples
41
+ ///
42
+ /// ```
43
+ /// use core::hash::{BuildHasher, Hash};
44
+ /// use indexmap::map::{IndexMap, RawEntryApiV1};
45
+ ///
46
+ /// let mut map = IndexMap::new();
47
+ /// map.extend([("a", 100), ("b", 200), ("c", 300)]);
48
+ ///
49
+ /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
50
+ /// use core::hash::Hasher;
51
+ /// let mut state = hash_builder.build_hasher();
52
+ /// key.hash(&mut state);
53
+ /// state.finish()
54
+ /// }
55
+ ///
56
+ /// for k in ["a", "b", "c", "d", "e", "f"] {
57
+ /// let hash = compute_hash(map.hasher(), k);
58
+ /// let v = map.get(k).cloned();
59
+ /// let kv = v.as_ref().map(|v| (&k, v));
60
+ ///
61
+ /// println!("Key: {} and value: {:?}", k, v);
62
+ ///
63
+ /// assert_eq!(map.raw_entry_v1().from_key(k), kv);
64
+ /// assert_eq!(map.raw_entry_v1().from_hash(hash, |q| *q == k), kv);
65
+ /// assert_eq!(map.raw_entry_v1().from_key_hashed_nocheck(hash, k), kv);
66
+ /// }
67
+ /// ```
24
68
fn raw_entry_v1 ( & self ) -> RawEntryBuilder < ' _ , K , V , S > ;
25
69
26
70
/// Creates a raw entry builder for the [`IndexMap`].
71
+ ///
72
+ /// Raw entries provide the lowest level of control for searching and
73
+ /// manipulating a map. They must be manually initialized with a hash and
74
+ /// then manually searched. After this, insertions into a vacant entry
75
+ /// still require an owned key to be provided.
76
+ ///
77
+ /// Raw entries are useful for such exotic situations as:
78
+ ///
79
+ /// * Hash memoization
80
+ /// * Deferring the creation of an owned key until it is known to be required
81
+ /// * Using a search key that doesn't work with the [`Equivalent`] trait
82
+ /// * Using custom comparison logic without newtype wrappers
83
+ ///
84
+ /// Because raw entries provide much more low-level control, it's much easier
85
+ /// to put the `IndexMap` into an inconsistent state which, while memory-safe,
86
+ /// will cause the map to produce seemingly random results. Higher-level and more
87
+ /// foolproof APIs like [`entry`][IndexMap::entry] should be preferred when possible.
88
+ ///
89
+ /// Raw entries give mutable access to the keys. This must not be used
90
+ /// to modify how the key would compare or hash, as the map will not re-evaluate
91
+ /// where the key should go, meaning the keys may become "lost" if their
92
+ /// location does not reflect their state. For instance, if you change a key
93
+ /// so that the map now contains keys which compare equal, search may start
94
+ /// acting erratically, with two keys randomly masking each other. Implementations
95
+ /// are free to assume this doesn't happen (within the limits of memory-safety).
96
+ ///
97
+ /// # Examples
98
+ ///
99
+ /// ```
100
+ /// use core::hash::{BuildHasher, Hash};
101
+ /// use indexmap::map::{IndexMap, RawEntryApiV1};
102
+ /// use indexmap::map::raw_entry_v1::RawEntryMut;
103
+ ///
104
+ /// let mut map = IndexMap::new();
105
+ /// map.extend([("a", 100), ("b", 200), ("c", 300)]);
106
+ ///
107
+ /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
108
+ /// use core::hash::Hasher;
109
+ /// let mut state = hash_builder.build_hasher();
110
+ /// key.hash(&mut state);
111
+ /// state.finish()
112
+ /// }
113
+ ///
114
+ /// // Existing key (insert and update)
115
+ /// match map.raw_entry_mut_v1().from_key("a") {
116
+ /// RawEntryMut::Vacant(_) => unreachable!(),
117
+ /// RawEntryMut::Occupied(mut view) => {
118
+ /// assert_eq!(view.get(), &100);
119
+ /// let v = view.get_mut();
120
+ /// let new_v = (*v) * 10;
121
+ /// *v = new_v;
122
+ /// assert_eq!(view.insert(1111), 1000);
123
+ /// }
124
+ /// }
125
+ ///
126
+ /// assert_eq!(map["a"], 1111);
127
+ /// assert_eq!(map.len(), 3);
128
+ ///
129
+ /// // Existing key (take)
130
+ /// let hash = compute_hash(map.hasher(), "c");
131
+ /// match map.raw_entry_mut_v1().from_key_hashed_nocheck(hash, "c") {
132
+ /// RawEntryMut::Vacant(_) => unreachable!(),
133
+ /// RawEntryMut::Occupied(view) => {
134
+ /// assert_eq!(view.shift_remove_entry(), ("c", 300));
135
+ /// }
136
+ /// }
137
+ /// assert_eq!(map.raw_entry_v1().from_key("c"), None);
138
+ /// assert_eq!(map.len(), 2);
139
+ ///
140
+ /// // Nonexistent key (insert and update)
141
+ /// let key = "d";
142
+ /// let hash = compute_hash(map.hasher(), key);
143
+ /// match map.raw_entry_mut_v1().from_hash(hash, |q| *q == key) {
144
+ /// RawEntryMut::Occupied(_) => unreachable!(),
145
+ /// RawEntryMut::Vacant(view) => {
146
+ /// let (k, value) = view.insert("d", 4000);
147
+ /// assert_eq!((*k, *value), ("d", 4000));
148
+ /// *value = 40000;
149
+ /// }
150
+ /// }
151
+ /// assert_eq!(map["d"], 40000);
152
+ /// assert_eq!(map.len(), 3);
153
+ ///
154
+ /// match map.raw_entry_mut_v1().from_hash(hash, |q| *q == key) {
155
+ /// RawEntryMut::Vacant(_) => unreachable!(),
156
+ /// RawEntryMut::Occupied(view) => {
157
+ /// assert_eq!(view.swap_remove_entry(), ("d", 40000));
158
+ /// }
159
+ /// }
160
+ /// assert_eq!(map.get("d"), None);
161
+ /// assert_eq!(map.len(), 2);
162
+ /// ```
27
163
fn raw_entry_mut_v1 ( & mut self ) -> RawEntryBuilderMut < ' _ , K , V , S > ;
28
164
}
29
165
0 commit comments