halfbrown/vecmap/
raw_entry.rs

1// based on / take from <https://github.com/rust-lang/hashbrown/blob/62a1ae24d4678fcbf777bef6b205fadeecb781d9/src/map.rs>
2
3use super::{Borrow, VecMap};
4use std::fmt::{self, Debug};
5use std::mem;
6
7/// A builder for computing where in a [`VecMap`] a key-value pair would be stored.
8///
9/// See the [`VecMap::raw_entry_mut`] docs for usage examples.
10///
11/// [`VecMap::raw_entry_mut`]: struct.VecMap.html#method.raw_entry_mut
12pub struct RawEntryBuilderMut<'a, K, V, const N: usize, S> {
13    pub(crate) map: &'a mut VecMap<K, V, N, S>,
14}
15
16/// A view into a single entry in a map, which may either be vacant or occupied.
17///
18/// This is a lower-level version of [`Entry`].
19///
20/// This `enum` is constructed through the [`raw_entry_mut`] method on [`VecMap`],
21/// then calling one of the methods of that [`RawEntryBuilderMut`].
22///
23/// [`VecMap`]: struct.VecMap.html
24/// [`Entry`]: enum.Entry.html
25/// [`raw_entry_mut`]: struct.VecMap.html#method.raw_entry_mut
26/// [`RawEntryBuilderMut`]: struct.RawEntryBuilderMut.html
27pub enum RawEntryMut<'a, K, V, const N: usize, S> {
28    /// An occupied entry.
29    Occupied(RawOccupiedEntryMut<'a, K, V, N, S>),
30    /// A vacant entry.
31    Vacant(RawVacantEntryMut<'a, K, V, N, S>),
32}
33
34/// A view into an occupied entry in a `VecMap`.
35/// It is part of the [`RawEntryMut`] enum.
36///
37/// [`RawEntryMut`]: enum.RawEntryMut.html
38pub struct RawOccupiedEntryMut<'a, K, V, const N: usize, S> {
39    idx: usize,
40    map: &'a mut VecMap<K, V, N, S>,
41}
42
43unsafe impl<K, V, const N: usize, S> Send for RawOccupiedEntryMut<'_, K, V, N, S>
44where
45    K: Send,
46    V: Send,
47    S: Send,
48{
49}
50unsafe impl<K, V, const N: usize, S> Sync for RawOccupiedEntryMut<'_, K, V, N, S>
51where
52    K: Sync,
53    V: Sync,
54    S: Send,
55{
56}
57
58/// A view into a vacant entry in a `VecMap`.
59/// It is part of the [`RawEntryMut`] enum.
60///
61/// [`RawEntryMut`]: enum.RawEntryMut.html
62pub struct RawVacantEntryMut<'a, K, V, const N: usize, S> {
63    map: &'a mut VecMap<K, V, N, S>,
64}
65
66/// A builder for computing where in a [`VecMap`] a key-value pair would be stored.
67///
68/// See the [`VecMap::raw_entry`] docs for usage examples.
69///
70/// [`VecMap::raw_entry`]: struct.VecMap.html#method.raw_entry
71pub struct RawEntryBuilder<'map, K, V, const N: usize, S> {
72    pub(crate) map: &'map VecMap<K, V, N, S>,
73}
74
75impl<'map, K, V, const N: usize, S> RawEntryBuilderMut<'map, K, V, N, S> {
76    /// Creates a `RawEntryMut` from the given key.
77    #[inline]
78    #[allow(clippy::wrong_self_convention)]
79    pub fn from_key<Q>(self, k: &Q) -> RawEntryMut<'map, K, V, N, S>
80    where
81        K: Borrow<Q>,
82        Q: Eq + ?Sized,
83    {
84        self.from_key_hashed_nocheck(0, k)
85    }
86
87    /// Creates a `RawEntryMut` from the given key and its hash.
88    #[inline]
89    #[allow(clippy::wrong_self_convention)]
90    pub fn from_key_hashed_nocheck<Q>(self, hash: u64, k: &Q) -> RawEntryMut<'map, K, V, N, S>
91    where
92        K: Borrow<Q>,
93        Q: Eq + ?Sized,
94    {
95        self.from_hash(hash, |q| q.borrow().eq(k))
96    }
97}
98
99impl<'a, K, V, const N: usize, S> RawEntryBuilderMut<'a, K, V, N, S> {
100    /// Creates a `RawEntryMut` from the given hash.
101    /// Note for the vec mapo hash has no effect it is only
102    /// provided for convinience reasons
103    #[inline]
104    #[allow(clippy::wrong_self_convention)]
105    pub fn from_hash<F>(self, _hash: u64, is_match: F) -> RawEntryMut<'a, K, V, N, S>
106    where
107        for<'b> F: FnMut(&'b K) -> bool,
108    {
109        self.search(is_match)
110    }
111
112    #[inline]
113    fn search<F>(self, mut is_match: F) -> RawEntryMut<'a, K, V, N, S>
114    where
115        for<'b> F: FnMut(&'b K) -> bool,
116    {
117        for (idx, (key, _v)) in self.map.v.iter().enumerate() {
118            if is_match(key) {
119                return RawEntryMut::Occupied(RawOccupiedEntryMut { idx, map: self.map });
120            }
121        }
122        RawEntryMut::Vacant(RawVacantEntryMut { map: self.map })
123    }
124}
125
126impl<'a, K, V, const N: usize, S> RawEntryBuilder<'a, K, V, N, S> {
127    /// Access an entry by key.
128    #[inline]
129    #[allow(clippy::wrong_self_convention)]
130    pub fn from_key<Q>(self, k: &Q) -> Option<(&'a K, &'a V)>
131    where
132        K: Borrow<Q>,
133        Q: Eq + ?Sized,
134    {
135        self.from_key_hashed_nocheck(0, k)
136    }
137
138    /// Access an entry by a key and its hash.
139    /// Note hash has no effect for `VecMap`
140    #[inline]
141    #[allow(clippy::wrong_self_convention)]
142    pub fn from_key_hashed_nocheck<Q>(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)>
143    where
144        K: Borrow<Q>,
145        Q: Eq + ?Sized,
146    {
147        self.from_hash(hash, |q| q.borrow().eq(k))
148    }
149
150    #[inline]
151    fn search<F>(self, _hash: u64, mut is_match: F) -> Option<(&'a K, &'a V)>
152    where
153        F: FnMut(&K) -> bool,
154    {
155        for (k, v) in &self.map.v {
156            if is_match(k) {
157                return Some((k, v));
158            }
159        }
160        None
161    }
162
163    /// Access an entry by hash.
164    #[inline]
165    #[allow(clippy::wrong_self_convention)]
166    pub fn from_hash<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)>
167    where
168        F: FnMut(&K) -> bool,
169    {
170        self.search(hash, is_match)
171    }
172}
173
174impl<'a, K, V, const N: usize, S> RawEntryMut<'a, K, V, N, S> {
175    /// Sets the value of the entry, and returns a `RawOccupiedEntryMut`.
176    ///
177    /// # Examples
178    ///
179    /// ```ignore
180    /// use halfbrown::VecMap;
181    ///
182    /// let mut map: VecMap<&str, u32> = VecMap::new();
183    /// let entry = map.raw_entry_mut().from_key("horseyland").insert("horseyland", 37);
184    ///
185    /// assert_eq!(entry.remove_entry(), ("horseyland", 37));
186    /// ```
187    #[inline]
188    pub fn insert(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V, N, S> {
189        match self {
190            RawEntryMut::Occupied(mut entry) => {
191                entry.insert(value);
192                entry
193            }
194            RawEntryMut::Vacant(entry) => entry.insert_entry(key, value),
195        }
196    }
197
198    /// Ensures a value is in the entry by inserting the default if empty, and returns
199    /// mutable references to the key and value in the entry.
200    ///
201    /// # Examples
202    ///
203    /// ```ignore
204    /// use halfbrown::VecMap;
205    ///
206    /// let mut map: VecMap<&str, u32> = VecMap::new();
207    ///
208    /// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 3);
209    /// assert_eq!(map["poneyland"], 3);
210    ///
211    /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2;
212    /// assert_eq!(map["poneyland"], 6);
213    /// ```
214    #[inline]
215    pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V) {
216        match self {
217            RawEntryMut::Occupied(entry) => entry.into_key_value(),
218            RawEntryMut::Vacant(entry) => entry.insert(default_key, default_val),
219        }
220    }
221
222    /// Ensures a value is in the entry by inserting the result of the default function if empty,
223    /// and returns mutable references to the key and value in the entry.
224    ///
225    /// # Examples
226    ///
227    /// ```ignore
228    /// use halfbrown::VecMap;
229    ///
230    /// let mut map: VecMap<&strtring> = VecMap::new();
231    ///
232    /// map.raw_entry_mut().from_key("poneyland").or_insert_with(|| {
233    ///     ("poneyland", "hoho".to_string())
234    /// });
235    ///
236    /// assert_eq!(map["poneyland"], "hoho".to_string());
237    /// ```
238    #[inline]
239    pub fn or_insert_with<F>(self, default: F) -> (&'a mut K, &'a mut V)
240    where
241        F: FnOnce() -> (K, V),
242    {
243        match self {
244            RawEntryMut::Occupied(entry) => entry.into_key_value(),
245            RawEntryMut::Vacant(entry) => {
246                let (k, v) = default();
247                entry.insert(k, v)
248            }
249        }
250    }
251
252    /// Provides in-place mutable access to an occupied entry before any
253    /// potential inserts into the map.
254    ///
255    /// # Examples
256    ///
257    /// ```ignore
258    /// use halfbrown::VecMap;
259    ///
260    /// let mut map: VecMap<&str, u32> = VecMap::new();
261    ///
262    /// map.raw_entry_mut()
263    ///    .from_key("poneyland")
264    ///    .and_modify(|_k, v| { *v += 1 })
265    ///    .or_insert("poneyland", 42);
266    /// assert_eq!(map["poneyland"], 42);
267    ///
268    /// map.raw_entry_mut()
269    ///    .from_key("poneyland")
270    ///    .and_modify(|_k, v| { *v += 1 })
271    ///    .or_insert("poneyland", 0);
272    /// assert_eq!(map["poneyland"], 43);
273    /// ```
274    #[inline]
275    pub fn and_modify<F>(self, f: F) -> Self
276    where
277        F: FnOnce(&mut K, &mut V),
278    {
279        match self {
280            RawEntryMut::Occupied(mut entry) => {
281                {
282                    let (k, v) = entry.get_key_value_mut();
283                    f(k, v);
284                }
285                RawEntryMut::Occupied(entry)
286            }
287            RawEntryMut::Vacant(entry) => RawEntryMut::Vacant(entry),
288        }
289    }
290}
291
292impl<'a, K, V, const N: usize, S> RawOccupiedEntryMut<'a, K, V, N, S> {
293    /// Gets a reference to the key in the entry.
294    #[inline]
295    pub fn key(&self) -> &K {
296        unsafe { &self.map.v.get_unchecked(self.idx).0 }
297    }
298
299    /// Gets a mutable reference to the key in the entry.
300    #[inline]
301    pub fn key_mut(&mut self) -> &mut K {
302        unsafe { &mut self.map.v.get_unchecked_mut(self.idx).0 }
303    }
304
305    /// Converts the entry into a mutable reference to the key in the entry
306    /// with a lifetime bound to the map itself.
307    #[inline]
308    pub fn into_key(self) -> &'a mut K {
309        unsafe { &mut self.map.v.get_unchecked_mut(self.idx).0 }
310    }
311
312    /// Gets a reference to the value in the entry.
313    #[inline]
314    pub fn get(&self) -> &V {
315        unsafe { &self.map.v.get_unchecked(self.idx).1 }
316    }
317
318    /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry
319    /// with a lifetime bound to the map itself.
320    #[inline]
321    pub fn into_mut(self) -> &'a mut V {
322        unsafe { &mut self.map.v.get_unchecked_mut(self.idx).1 }
323    }
324
325    /// Gets a mutable reference to the value in the entry.
326    #[inline]
327    pub fn get_mut(&mut self) -> &mut V {
328        unsafe { &mut self.map.v.get_unchecked_mut(self.idx).1 }
329    }
330
331    /// Gets a reference to the key and value in the entry.
332    #[inline]
333    pub fn get_key_value(&mut self) -> (&K, &V) {
334        unsafe {
335            let (key, value) = &self.map.v.get_unchecked(self.idx);
336            (key, value)
337        }
338    }
339
340    /// Gets a mutable reference to the key and value in the entry.
341    #[inline]
342    pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) {
343        unsafe { self.map.get_mut_idx(self.idx) }
344    }
345
346    /// Converts the `OccupiedEntry` into a mutable reference to the key and value in the entry
347    /// with a lifetime bound to the map itself.
348    #[inline]
349    pub fn into_key_value(self) -> (&'a mut K, &'a mut V) {
350        unsafe { self.map.get_mut_idx(self.idx) }
351    }
352
353    /// Sets the value of the entry, and returns the entry's old value.
354    #[inline]
355    pub fn insert(&mut self, value: V) -> V {
356        mem::replace(self.get_mut(), value)
357    }
358
359    /// Sets the value of the entry, and returns the entry's old value.
360    #[inline]
361    pub fn insert_key(&mut self, key: K) -> K {
362        mem::replace(self.key_mut(), key)
363    }
364
365    /// Takes the value out of the entry, and returns it.
366    #[inline]
367    pub fn remove(self) -> V {
368        self.remove_entry().1
369    }
370
371    /// Take the ownership of the key and value from the map.
372    #[inline]
373    pub fn remove_entry(self) -> (K, V) {
374        unsafe { self.map.remove_idx(self.idx) }
375    }
376}
377
378impl<'a, K, V, const N: usize, S> RawVacantEntryMut<'a, K, V, N, S> {
379    /// Sets the value of the entry with the `VacantEntry`'s key,
380    /// and returns a mutable reference to it.
381    #[inline]
382    pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V) {
383        let i = self.map.insert_idx(key, value);
384        unsafe { self.map.get_mut_idx(i) }
385    }
386
387    /// Sets the value of the entry with the `VacantEntry`'s key,
388    /// and returns a mutable reference to it.
389    #[inline]
390    #[allow(clippy::shadow_unrelated)]
391    pub fn insert_hashed_nocheck(self, _hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) {
392        self.insert(key, value)
393    }
394
395    /// Set the value of an entry with a custom hasher function.
396    #[inline]
397    pub fn insert_with_hasher<H>(
398        self,
399        _hash: u64,
400        key: K,
401        value: V,
402        _hasher: H,
403    ) -> (&'a mut K, &'a mut V)
404    where
405        H: Fn(&K) -> u64,
406    {
407        self.insert(key, value)
408    }
409
410    #[inline]
411    fn insert_entry(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V, N, S> {
412        let idx = self.map.insert_idx(key, value);
413        RawOccupiedEntryMut { idx, map: self.map }
414    }
415}
416
417impl<K, V, const N: usize, S> Debug for RawEntryBuilderMut<'_, K, V, N, S> {
418    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419        f.debug_struct("RawEntryBuilder").finish()
420    }
421}
422
423impl<K, V, const N: usize, S> Debug for RawEntryMut<'_, K, V, N, S>
424where
425    K: Debug,
426    V: Debug,
427{
428    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
429        match *self {
430            RawEntryMut::Vacant(ref v) => f.debug_tuple("RawEntry").field(v).finish(),
431            RawEntryMut::Occupied(ref o) => f.debug_tuple("RawEntry").field(o).finish(),
432        }
433    }
434}
435
436impl<K: Debug, V: Debug, const N: usize, S> Debug for RawOccupiedEntryMut<'_, K, V, N, S> {
437    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
438        f.debug_struct("RawOccupiedEntryMut")
439            .field("key", self.key())
440            .field("value", self.get())
441            .finish()
442    }
443}
444
445impl<K, V, const N: usize, S> Debug for RawVacantEntryMut<'_, K, V, N, S> {
446    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
447        f.debug_struct("RawVacantEntryMut").finish()
448    }
449}
450
451impl<K, V, const N: usize, S> Debug for RawEntryBuilder<'_, K, V, N, S> {
452    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
453        f.debug_struct("RawEntryBuilder").finish()
454    }
455}