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
use bevy::{
platform::collections::{Equivalent, HashMap},
prelude::*,
};
use std::hash::Hash;
/// One or map
///
/// This enum is designed to primarily hold one value without any heap
/// allocation but may be promoted to a HashMap that is stored in the heap.
#[derive(Debug, Reflect)]
pub enum OneOrMap<K, V> {
One { key: K, value: V },
Map(HashMap<K, V>),
}
impl<K, V> OneOrMap<K, V> {
pub fn new(key: K, value: V) -> Self {
OneOrMap::One { key, value }
}
pub fn get<Q>(&self, key: &Q) -> Option<&V>
where
// K: Borrow<Q>,
K: Hash + Eq,
Q: Hash + Equivalent<K> + ?Sized,
{
match self {
OneOrMap::One {
key: single_key,
value,
} => {
if key.equivalent(single_key) {
Some(value)
} else {
// Create an image an ugrade to a Multiple.
None
}
}
OneOrMap::Map(map) => map.get(key),
}
}
pub fn insert(&mut self, key: K, value: V) -> Option<V>
where
K: Eq + Hash,
{
match self {
OneOrMap::One {
key: single_key,
value: single_value,
} => {
// if key.equivalent(single_key) {
if *single_key == key {
Some(std::mem::replace(single_value, value))
} else {
let mut map = HashMap::with_capacity(2);
map.insert(key, value);
let last_value = std::mem::replace(self, OneOrMap::Map(map));
match last_value {
OneOrMap::One {
key: single_key,
value: single_value,
} => {
self.insert(single_key, single_value);
}
_ => unreachable!(),
}
None
}
}
OneOrMap::Map(map) => map.insert(key, value),
}
}
}