Skip to main content

embed_collections/
various_map.rs

1use alloc::collections::BTreeMap;
2use alloc::collections::btree_map;
3use core::borrow::Borrow;
4use core::mem::MaybeUninit;
5use core::option;
6
7/// A tempoary map optimise for empty or one condition,
8/// to delay allocation.
9///
10/// Initial to be Option<(K, V)>.
11/// If multi item inserted, transit from Option to std::collections::BTreeMap.
12pub enum VariousMap<K, V> {
13    One(Option<(K, V)>),
14    Multi(BTreeMap<K, V>),
15}
16
17impl<K: Ord, V> VariousMap<K, V> {
18    #[inline]
19    pub fn new() -> Self {
20        Self::One(None)
21    }
22
23    #[inline]
24    pub fn get<Q>(&self, key: &Q) -> Option<&V>
25    where
26        K: Borrow<Q> + Ord,
27        Q: Ord + ?Sized,
28    {
29        match self {
30            Self::One(Some(item)) => {
31                if item.0.borrow() == key {
32                    Some(&item.1)
33                } else {
34                    None
35                }
36            }
37            Self::Multi(map) => map.get(key),
38            _ => None,
39        }
40    }
41
42    #[inline]
43    pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
44    where
45        K: Borrow<Q> + Ord,
46        Q: Ord + ?Sized,
47    {
48        match self {
49            Self::One(Some(item)) => {
50                if item.0.borrow() == key {
51                    Some(&mut item.1)
52                } else {
53                    None
54                }
55            }
56            Self::Multi(map) => map.get_mut(key),
57            _ => None,
58        }
59    }
60
61    #[inline]
62    pub fn insert(&mut self, key: K, value: V) -> Option<V>
63    where
64        K: Ord,
65    {
66        let (old_k, old_v) = match self {
67            Self::One(item) => {
68                if item.is_none() {
69                    item.replace((key, value));
70                    return None;
71                }
72                let (old_k, old_v) = item.take().unwrap();
73                if old_k == key {
74                    item.replace((key, value));
75                    return Some(old_v);
76                }
77                (old_k, old_v)
78            }
79            Self::Multi(map) => {
80                return map.insert(key, value);
81            }
82        };
83        let mut map = BTreeMap::new();
84        map.insert(key, value);
85        map.insert(old_k, old_v);
86        *self = Self::Multi(map);
87        None
88    }
89
90    #[inline]
91    pub fn iter(&self) -> Iter<'_, K, V> {
92        match self {
93            Self::One(o) => Iter::One(o.iter()),
94            Self::Multi(map) => Iter::Multi(map.iter()),
95        }
96    }
97
98    #[inline]
99    pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
100        let mut exists = false;
101        match self {
102            Self::One(Some(item)) => {
103                if item.0 == key {
104                    exists = true;
105                }
106            }
107            Self::Multi(map) => match map.entry(key) {
108                btree_map::Entry::Occupied(ent) => {
109                    return Entry::Occupied(OccupiedEntry::Multi(ent));
110                }
111                btree_map::Entry::Vacant(ent) => return Entry::Vacant(VacantEntry::Multi(ent)),
112            },
113            _ => {}
114        }
115        if !exists {
116            return Entry::Vacant(VacantEntry::One(VacantEntryOne { key, map: self }));
117        }
118        // in order to resolve borrow issue,
119        // return field ref only after returning self ref.
120        if let Self::One(item) = self {
121            return Entry::Occupied(OccupiedEntry::One(item));
122        }
123        unreachable!();
124    }
125
126    #[inline]
127    pub fn len(&self) -> usize {
128        match self {
129            Self::One(Some(_item)) => 1,
130            Self::Multi(map) => map.len(),
131            _ => 0,
132        }
133    }
134
135    #[inline]
136    pub fn is_empty(&self) -> bool {
137        match self {
138            Self::One(item) => item.is_none(),
139            Self::Multi(map) => map.is_empty(),
140        }
141    }
142
143    #[inline]
144    pub fn contains_key<Q>(&self, key: &Q) -> bool
145    where
146        K: Borrow<Q> + Ord,
147        Q: Ord + ?Sized,
148    {
149        match self {
150            Self::One(Some(item)) => item.0.borrow() == key,
151            Self::Multi(map) => map.contains_key(key),
152            _ => false,
153        }
154    }
155}
156
157impl<K, V> IntoIterator for VariousMap<K, V> {
158    type Item = (K, V);
159    type IntoIter = IntoIter<K, V>;
160
161    #[inline]
162    fn into_iter(self) -> Self::IntoIter {
163        match self {
164            Self::One(o) => IntoIter::One(o),
165            Self::Multi(map) => IntoIter::Multi(map.into_iter()),
166        }
167    }
168}
169
170pub enum Iter<'a, K, V> {
171    One(option::Iter<'a, (K, V)>),
172    Multi(btree_map::Iter<'a, K, V>),
173}
174
175impl<'a, K, V> Iterator for Iter<'a, K, V> {
176    type Item = (&'a K, &'a V);
177
178    #[inline]
179    fn next(&mut self) -> Option<Self::Item> {
180        match self {
181            Iter::One(iter) => {
182                if let Some(item) = iter.next() {
183                    Some((&item.0, &item.1))
184                } else {
185                    None
186                }
187            }
188            Iter::Multi(iter) => iter.next(),
189        }
190    }
191}
192
193pub enum IntoIter<K, V> {
194    One(Option<(K, V)>),
195    Multi(btree_map::IntoIter<K, V>),
196}
197
198impl<K, V> Iterator for IntoIter<K, V> {
199    type Item = (K, V);
200
201    #[inline]
202    fn next(&mut self) -> Option<Self::Item> {
203        match self {
204            Self::One(iter) => iter.take(),
205            Self::Multi(iter) => iter.next(),
206        }
207    }
208}
209
210pub enum Entry<'a, K: 'a, V: 'a> {
211    Occupied(OccupiedEntry<'a, K, V>),
212    Vacant(VacantEntry<'a, K, V>),
213}
214
215pub enum OccupiedEntry<'a, K: 'a, V: 'a> {
216    One(&'a mut Option<(K, V)>),
217    Multi(btree_map::OccupiedEntry<'a, K, V>),
218}
219
220impl<'a, K, V> OccupiedEntry<'a, K, V>
221where
222    K: Ord,
223{
224    #[inline]
225    pub fn get(&self) -> &V {
226        match self {
227            Self::One(o) => &o.as_ref().unwrap().1,
228            Self::Multi(ent) => ent.get(),
229        }
230    }
231
232    #[inline]
233    pub fn get_mut(&mut self) -> &mut V {
234        match self {
235            Self::One(o) => &mut o.as_mut().unwrap().1,
236            Self::Multi(ent) => ent.get_mut(),
237        }
238    }
239
240    #[inline]
241    pub fn key(&self) -> &K {
242        match self {
243            Self::One(o) => &o.as_ref().unwrap().0,
244            Self::Multi(ent) => ent.key(),
245        }
246    }
247
248    #[inline]
249    pub fn remove(self) -> V {
250        match self {
251            Self::One(o) => {
252                let (_k, v) = o.take().unwrap();
253                v
254            }
255            Self::Multi(ent) => ent.remove(),
256        }
257    }
258
259    #[inline]
260    pub fn remove_entry(self) -> (K, V) {
261        match self {
262            Self::One(o) => o.take().unwrap(),
263            Self::Multi(ent) => ent.remove_entry(),
264        }
265    }
266
267    #[inline]
268    pub fn insert(self, value: V) -> V {
269        match self {
270            Self::One(o) => {
271                let (k, old_v) = o.take().unwrap();
272                o.replace((k, value));
273                old_v
274            }
275            Self::Multi(mut ent) => ent.insert(value),
276        }
277    }
278
279    #[inline]
280    pub fn into_mut(self) -> &'a mut V {
281        match self {
282            Self::One(o) => &mut o.as_mut().unwrap().1,
283            Self::Multi(ent) => ent.into_mut(),
284        }
285    }
286}
287
288pub enum VacantEntry<'a, K, V> {
289    One(VacantEntryOne<'a, K, V>),
290    Multi(btree_map::VacantEntry<'a, K, V>),
291}
292
293struct VacantEntryOne<'a, K: 'a, V: 'a> {
294    pub(crate) key: K,                        // Owned key to insert
295    pub(crate) map: &'a mut VariousMap<K, V>, // Reference to the VariousMap
296}
297
298impl<'a, K, V> VacantEntry<'a, K, V>
299where
300    K: Ord,
301{
302    #[inline]
303    pub fn key(&self) -> &K {
304        match self {
305            Self::One(ent) => &ent.key,
306            Self::Multi(ent) => ent.key(),
307        }
308    }
309
310    #[inline]
311    pub fn into_key(self) -> K {
312        match self {
313            Self::One(ent) => ent.key,
314            Self::Multi(ent) => ent.into_key(),
315        }
316    }
317
318    #[inline]
319    pub fn insert(self, value: V) -> &'a mut V {
320        match self {
321            Self::One(ent) => {
322                let mut _value = MaybeUninit::new(value);
323                let mut _key = MaybeUninit::new(ent.key);
324                let map = ent.map;
325                if let VariousMap::One(item) = map {
326                    if item.is_none() {
327                        unsafe {
328                            // we should have return here, but don't because of the borrow checker
329                            item.replace((_key.assume_init_read(), _value.assume_init_read()));
330                        }
331                    } else {
332                        let (old_k, old_v) = item.take().unwrap();
333                        unsafe {
334                            if &old_k == _key.assume_init_ref() {
335                                // we should have return here, but don't because of the borrow checker
336                                item.replace((_key.assume_init_read(), _value.assume_init_read()));
337                            } else {
338                                let _ = item;
339                                let mut _map = BTreeMap::new();
340                                _map.insert(old_k, old_v);
341                                *map = VariousMap::Multi(_map);
342                            }
343                        }
344                    }
345                }
346                match map {
347                    VariousMap::One(Some(item)) => &mut item.1,
348                    VariousMap::Multi(map) => unsafe {
349                        map.entry(_key.assume_init_read()).or_insert(_value.assume_init_read())
350                    },
351                    _ => unreachable!(),
352                }
353            }
354            Self::Multi(ent) => ent.insert(value),
355        }
356    }
357}
358
359impl<'a, K, V> Entry<'a, K, V>
360where
361    K: Ord,
362    V: Default,
363{
364    #[inline]
365    pub fn or_insert(self, default: V) -> &'a mut V {
366        match self {
367            Entry::Occupied(entry) => entry.into_mut(),
368            Entry::Vacant(entry) => entry.insert(default),
369        }
370    }
371
372    #[inline]
373    pub fn or_insert_with<F: FnOnce() -> V>(self, default_fn: F) -> &'a mut V {
374        match self {
375            Entry::Occupied(entry) => entry.into_mut(),
376            Entry::Vacant(entry) => entry.insert(default_fn()),
377        }
378    }
379
380    #[inline]
381    pub fn and_modify<F>(mut self, f: F) -> Self
382    where
383        F: FnOnce(&mut V),
384    {
385        if let Entry::Occupied(ref mut entry) = self {
386            f(entry.get_mut());
387        }
388        self
389    }
390
391    #[inline]
392    pub fn key(&self) -> &K {
393        match self {
394            Entry::Occupied(entry) => entry.key(),
395            Entry::Vacant(entry) => entry.key(),
396        }
397    }
398
399    #[inline]
400    pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> {
401        match self {
402            Entry::Occupied(mut ent) => {
403                match ent {
404                    OccupiedEntry::One(ref mut o) => {
405                        let (k, _old_v) = o.take().unwrap();
406                        o.replace((k, value));
407                    }
408                    OccupiedEntry::Multi(ref mut ent) => {
409                        ent.insert(value);
410                    }
411                }
412                ent
413            }
414            Entry::Vacant(VacantEntry::One(entry)) => {
415                let mut _value = MaybeUninit::new(value);
416                let mut _key = MaybeUninit::new(entry.key);
417                let map = entry.map;
418                if let VariousMap::One(item) = map {
419                    if item.is_none() {
420                        unsafe {
421                            item.replace((_key.assume_init_read(), _value.assume_init_read()));
422                        }
423                    } else {
424                        let (old_k, old_v) = item.take().unwrap();
425                        unsafe {
426                            if &old_k == _key.assume_init_ref() {
427                                item.replace((_key.assume_init_read(), _value.assume_init_read()));
428                            } else {
429                                let _ = item;
430                                let mut _map = BTreeMap::new();
431                                _map.insert(old_k, old_v);
432                                *map = VariousMap::Multi(_map);
433                            }
434                        }
435                    }
436                }
437                match map {
438                    VariousMap::One(o) => OccupiedEntry::One(o),
439                    VariousMap::Multi(map) => {
440                        let ent = unsafe {
441                            map.entry(_key.assume_init_read())
442                                .insert_entry(_value.assume_init_read())
443                        };
444                        OccupiedEntry::Multi(ent)
445                    }
446                }
447            }
448            Entry::Vacant(VacantEntry::Multi(ent)) => OccupiedEntry::Multi(ent.insert_entry(value)),
449        }
450    }
451
452    #[inline]
453    pub fn or_default(self) -> &'a mut V
454    where
455        V: Default,
456    {
457        self.or_insert_with(Default::default)
458    }
459}
460
461#[cfg(test)]
462mod tests {
463    use super::*;
464
465    #[test]
466    fn test_new() {
467        let map: VariousMap<i32, String> = VariousMap::new();
468        assert!(matches!(map, VariousMap::One(None)));
469    }
470
471    #[test]
472    fn test_insert_and_get_one() {
473        let mut map = VariousMap::<usize, usize>::new();
474        assert_eq!(map.insert(1, 1), None);
475        assert!(matches!(map, VariousMap::One(Some((ref k, ref v))) if *k == 1 && *v == 1));
476        assert_eq!(map.get(&1), Some(&1));
477        assert_eq!(map.get(&2), None);
478        **(map.get_mut(&1).as_mut().unwrap()) = 2;
479        assert_eq!(map.get(&1), Some(&2));
480        assert_eq!(map.insert(1, 3), Some(2));
481        assert_eq!(map.get(&1), Some(&3));
482    }
483
484    #[test]
485    fn test_insert_transition_to_multi() {
486        let mut map = VariousMap::new();
487        map.insert(1, "one".to_string());
488        assert_eq!(map.insert(2, "two".to_string()), None);
489
490        // After inserting a second element, it should transition to BTreeMap
491        match map {
492            VariousMap::Multi(ref btree_map) => {
493                assert_eq!(btree_map.len(), 2);
494                assert_eq!(btree_map.get(&1), Some(&"one".to_string()));
495                assert_eq!(btree_map.get(&2), Some(&"two".to_string()));
496            }
497            _ => panic!("Expected Multi variant after inserting two elements"),
498        }
499
500        assert_eq!(map.get(&1), Some(&"one".to_string()));
501        assert_eq!(map.get(&2), Some(&"two".to_string()));
502        assert_eq!(map.get(&3), None);
503
504        **map.get_mut(&2).as_mut().unwrap() = "two_update".to_string();
505        assert_eq!(map.get(&2), Some(&"two_update".to_string()));
506    }
507
508    #[test]
509    fn test_iter_one() {
510        let mut map = VariousMap::new();
511        map.insert(1, "one".to_string());
512        let mut collected: Vec<_> = map.iter().collect();
513        collected.sort_by_key(|(k, _)| *k);
514        assert_eq!(collected, vec![(&1, &"one".to_string())]);
515    }
516
517    #[test]
518    fn test_iter_multi() {
519        let mut map = VariousMap::new();
520        map.insert(1, "one".to_string());
521        map.insert(2, "two".to_string()); // Transition to Multi
522        map.insert(3, "three".to_string());
523
524        let mut collected: Vec<_> = map.iter().collect();
525        collected.sort_by_key(|(k, _)| *k);
526        assert_eq!(
527            collected,
528            vec![(&1, &"one".to_string()), (&2, &"two".to_string()), (&3, &"three".to_string())]
529        );
530    }
531
532    #[test]
533    fn test_into_iter_one() {
534        let mut map = VariousMap::new();
535        map.insert(1, "one".to_string());
536        let mut collected: Vec<_> = map.into_iter().collect();
537        collected.sort_by_key(|(k, _)| *k);
538        assert_eq!(collected, vec![(1, "one".to_string())]);
539    }
540
541    #[test]
542    fn test_contains_key() {
543        let mut map = VariousMap::new();
544        map.insert(1, "one".to_string());
545        assert!(map.contains_key(&1));
546        assert!(!map.contains_key(&2));
547
548        map.insert(2, "two".to_string()); // Transition to Multi
549        assert!(map.contains_key(&1));
550        assert!(map.contains_key(&2));
551        assert!(!map.contains_key(&3));
552    }
553
554    #[test]
555    fn test_entry_api_one() {
556        let mut map = VariousMap::new();
557        map.insert(1, "one".to_string());
558
559        // Occupied
560        match map.entry(1) {
561            Entry::Occupied(ent) => {
562                assert_eq!(ent.get(), &"one".to_string());
563                ent.insert("one_updated".to_string());
564            }
565            Entry::Vacant(_) => panic!("Should be occupied"),
566        }
567        assert_eq!(map.get(&1), Some(&"one_updated".to_string()));
568
569        // Vacant
570        match map.entry(2) {
571            Entry::Occupied(_) => panic!("Should be vacant"),
572            Entry::Vacant(ent) => {
573                ent.insert("two".to_string());
574            }
575        }
576        assert!(map.contains_key(&2));
577    }
578
579    #[test]
580    fn test_entry_api_or_insert() {
581        let mut map = VariousMap::new();
582        map.entry(1).or_insert("one".to_string());
583
584        // Occupied
585        let v = map
586            .entry(1)
587            .and_modify(|v| {
588                *v = "one_3".to_string();
589            })
590            .or_insert("one_2".to_string());
591        assert_eq!(v, &"one_3".to_string());
592
593        // Vacant
594        map.entry(2).or_insert("two".to_string());
595        assert_eq!(map.get(&2), Some(&"two".to_string()));
596    }
597
598    #[test]
599    fn test_entry_api_insert_entry() {
600        let mut map = VariousMap::new();
601
602        // Vacant -> insert_entry
603        let occupied = map.entry(1).insert_entry("one".to_string());
604        assert_eq!(occupied.get(), &"one".to_string());
605
606        // Occupied -> insert_entry
607        let occupied = map.entry(1).insert_entry("one_updated".to_string());
608        assert_eq!(occupied.get(), &"one_updated".to_string());
609        assert_eq!(map.get(&1), Some(&"one_updated".to_string()));
610    }
611}