anathema_store/
smallmap.rs1use std::borrow::Borrow;
2
3use crate::slab::{Slab, SlabIndex};
4
5type NumType = u16;
6
7#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Hash)]
8pub struct SmallIndex(NumType);
9
10impl SmallIndex {
11 pub const MAX: Self = Self(NumType::MAX);
12 pub const ONE: Self = Self(1);
13 pub const ZERO: Self = Self(0);
14}
15
16impl From<SmallIndex> for NumType {
17 fn from(value: SmallIndex) -> Self {
18 value.0
19 }
20}
21
22impl SlabIndex for SmallIndex {
23 const MAX: usize = NumType::MAX as usize;
24
25 fn as_usize(&self) -> usize {
26 self.0 as usize
27 }
28
29 fn from_usize(index: usize) -> Self
30 where
31 Self: Sized,
32 {
33 Self(index as NumType)
34 }
35}
36
37#[derive(Debug, Clone, PartialEq)]
72pub struct SmallMap<K, V>(Slab<SmallIndex, (K, V)>);
73
74impl<K, V> SmallMap<K, V>
75where
76 K: PartialEq,
77{
78 pub fn empty() -> Self {
80 Self(Slab::empty())
81 }
82
83 pub fn set(&mut self, key: K, mut value: V) -> Option<V> {
87 let old_value = self.get_mut(&key);
88 match old_value {
89 Some(old) => {
90 std::mem::swap(old, &mut value);
91 Some(value)
92 }
93 None => {
94 self.0.insert((key, value));
95 None
96 }
97 }
98 }
99
100 pub fn insert_with<F>(&mut self, key: K, f: F) -> SmallIndex
101 where
102 F: FnOnce(SmallIndex) -> V,
103 {
104 let id = self.0.next_id();
105 let value = f(id);
106 assert_eq!(self.0.insert((key, value)), id);
107 id
108 }
109
110 pub fn get<Q>(&self, key: &Q) -> Option<&V>
112 where
113 K: Borrow<Q>,
114 Q: PartialEq + ?Sized,
115 {
116 self.0.iter().find_map(|(_, (k, v))| match k.borrow() == key {
117 true => Some(v),
118 false => None,
119 })
120 }
121
122 pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
124 where
125 K: Borrow<Q>,
126 Q: PartialEq + ?Sized,
127 {
128 self.0.iter_mut().find_map(|(_, (k, v))| match (*k).borrow() == key {
129 true => Some(v),
130 false => None,
131 })
132 }
133
134 pub fn get_index<Q>(&self, key: &Q) -> Option<SmallIndex>
135 where
136 K: Borrow<Q>,
137 Q: PartialEq + ?Sized,
138 {
139 self.0.iter().find_map(|(i, (k, _))| match k.borrow() == key {
140 true => Some(i),
141 false => None,
142 })
143 }
144
145 pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
146 where
147 K: Borrow<Q>,
148 Q: PartialEq + ?Sized,
149 {
150 let idx = self.get_index(key)?;
151 self.0.try_remove(idx).map(|(_, v)| v)
152 }
153
154 pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> + '_ {
156 self.0.iter().map(|(_, (k, v))| (k, v))
157 }
158
159 pub fn iter_mut(&mut self) -> impl Iterator<Item = (&mut K, &mut V)> + '_ {
160 self.0.iter_mut().map(|(_, (k, v))| (k, v))
161 }
162
163 pub fn get_with_index(&self, idx: SmallIndex) -> Option<&V> {
165 self.0.get(idx).map(|(_, v)| v)
166 }
167
168 pub fn get_mut_with_index(&mut self, idx: SmallIndex) -> Option<&mut V> {
170 self.0.get_mut(idx).map(|(_, v)| v)
171 }
172}
173
174#[cfg(test)]
175mod test {
176 use super::*;
177
178 #[test]
179 fn insert_twice() {
180 let mut map = SmallMap::<&str, u8>::empty();
181 map.set("a", 1);
182 map.set("b", 2);
183
184 assert_eq!(1, *map.get("a").unwrap());
185 }
186
187 #[test]
188 fn get_and_get_mut() {
189 let mut map = SmallMap::<&str, u8>::empty();
190 map.set("a", 1);
191 map.set("b", 2);
192
193 *map.get_mut("a").unwrap() += 1;
194
195 assert_eq!(2, *map.get("b").unwrap());
196 assert_eq!(2, *map.get("a").unwrap());
197 }
198
199 #[test]
200 fn double_set() {
201 let mut map = SmallMap::<&str, u8>::empty();
202 assert_eq!(None, map.set("a", 1));
203 assert_eq!(Some(1), map.set("a", 2));
204 }
205
206 #[test]
207 fn get_by_index() {
208 let mut map = SmallMap::<&str, u8>::empty();
209 map.set("a", 1);
210 let idx = map.get_index("a").unwrap();
211 assert_eq!(1, *map.get_with_index(idx).unwrap());
212 }
213
214 #[test]
215 fn get_by_index_mut() {
216 let mut map = SmallMap::<&str, u8>::empty();
217 map.set("a", 1);
218 let idx = map.get_index("a").unwrap();
219 assert_eq!(1, *map.get_mut_with_index(idx).unwrap());
220 }
221}