1#![no_std]
8
9use core::mem;
11use core::ops::{Deref, DerefMut};
12
13use canonical::{Canon, CanonError, Id};
14use canonical_derive::Canon;
15
16use microkelvin::{
17 Annotation, Branch, BranchMut, Child, ChildMut, Compound, GenericChild,
18 GenericTree, Link, Step, Walker,
19};
20
21#[derive(Clone, Debug, Canon)]
22pub struct KvPair<K, V> {
23 pub key: K,
24 pub val: V,
25}
26
27#[derive(Clone, Canon, Debug)]
28enum Bucket<K, V, A>
29where
30 A: Annotation<KvPair<K, V>>,
31{
32 Empty,
33 Leaf(KvPair<K, V>),
34 Node(Link<Hamt<K, V, A>, A>),
35}
36
37#[derive(Clone, Canon, Debug)]
38pub struct Hamt<K, V, A>([Bucket<K, V, A>; 4])
39where
40 A: Annotation<KvPair<K, V>>;
41
42pub type Map<K, V> = Hamt<K, V, ()>;
43
44impl<K, V, A> Compound<A> for Hamt<K, V, A>
45where
46 A: Annotation<KvPair<K, V>>,
47 K: Canon,
48 V: Canon,
49 A: Canon,
50{
51 type Leaf = KvPair<K, V>;
52
53 fn child(&self, ofs: usize) -> Child<Self, A> {
54 match self.0.get(ofs) {
55 Some(Bucket::Empty) => Child::Empty,
56 Some(Bucket::Leaf(ref kv)) => Child::Leaf(kv),
57 Some(Bucket::Node(ref nd)) => Child::Node(nd),
58 None => Child::EndOfNode,
59 }
60 }
61
62 fn child_mut(&mut self, ofs: usize) -> ChildMut<Self, A> {
63 match self.0.get_mut(ofs) {
64 Some(Bucket::Empty) => ChildMut::Empty,
65 Some(Bucket::Leaf(ref mut kv)) => ChildMut::Leaf(kv),
66 Some(Bucket::Node(ref mut nd)) => ChildMut::Node(nd),
67 None => ChildMut::EndOfNode,
68 }
69 }
70
71 fn from_generic(generic: &GenericTree) -> Result<Self, CanonError> {
72 let mut s = Self::default();
73 for (i, child) in generic.children().iter().enumerate() {
74 match child {
75 GenericChild::Empty => (),
76 GenericChild::Leaf(leaf) => s.0[i] = Bucket::Leaf(leaf.cast()?),
77 GenericChild::Link(id, a) => {
78 s.0[i] = Bucket::Node(Link::new_persisted(*id, a.cast()?));
79 }
80 }
81 }
82 Ok(s)
83 }
84}
85
86impl<K, V, A> Bucket<K, V, A>
87where
88 A: Annotation<KvPair<K, V>>,
89{
90 fn take(&mut self) -> Self {
91 mem::replace(self, Bucket::Empty)
92 }
93}
94
95impl<K, V, A> Default for Bucket<K, V, A>
96where
97 A: Annotation<KvPair<K, V>>,
98{
99 fn default() -> Self {
100 Bucket::Empty
101 }
102}
103
104impl<K, V, A> Default for Hamt<K, V, A>
105where
106 A: Annotation<KvPair<K, V>>,
107{
108 fn default() -> Self {
109 Hamt(Default::default())
110 }
111}
112
113fn slot<H>(hash: &H, depth: usize) -> usize
114where
115 H: AsRef<[u8]>,
116{
117 (hash.as_ref()[depth] % 4) as usize
119}
120
121struct PathWalker<'a> {
122 hash: &'a [u8; 32],
123 depth: usize,
124}
125
126impl<'a> PathWalker<'a> {
127 fn new(hash: &'a [u8; 32]) -> Self {
128 PathWalker { hash, depth: 0 }
129 }
130}
131
132impl<'a, C, A> Walker<C, A> for PathWalker<'a>
133where
134 C: Compound<A>,
135{
136 fn walk(&mut self, walk: microkelvin::Walk<C, A>) -> microkelvin::Step {
137 let slot = slot(self.hash, self.depth);
138 self.depth += 1;
139 match walk.child(slot) {
140 Child::Leaf(_) => Step::Found(slot),
141 Child::Node(_) => Step::Into(slot),
142 Child::Empty | Child::EndOfNode => Step::Abort,
143 }
144 }
145}
146
147impl<K, V, A> Hamt<K, V, A>
148where
149 K: Eq + Canon,
150 V: Canon,
151 A: Annotation<KvPair<K, V>> + Canon,
152{
153 pub fn new() -> Self {
155 Self::default()
156 }
157
158 pub fn insert(&mut self, key: K, val: V) -> Result<Option<V>, CanonError> {
159 let hash = Id::new(&key).hash();
160 self._insert(key, val, hash, 0)
161 }
162
163 fn _insert(
164 &mut self,
165 key: K,
166 val: V,
167 hash: [u8; 32],
168 depth: usize,
169 ) -> Result<Option<V>, CanonError> {
170 let slot = slot(&hash, depth);
171 let bucket = &mut self.0[slot];
172
173 match bucket.take() {
174 Bucket::Empty => {
175 *bucket = Bucket::Leaf(KvPair { key, val });
176 Ok(None)
177 }
178 Bucket::Leaf(KvPair {
179 key: old_key,
180 val: old_val,
181 }) => {
182 if key == old_key {
183 *bucket = Bucket::Leaf(KvPair { key, val });
184 Ok(Some(old_val))
185 } else {
186 let mut new_node = Hamt::new();
187 let old_hash = Id::new(&old_key).hash();
188
189 new_node._insert(key, val, hash, depth + 1)?;
190 new_node._insert(old_key, old_val, old_hash, depth + 1)?;
191 *bucket = Bucket::Node(Link::new(new_node));
192 Ok(None)
193 }
194 }
195 Bucket::Node(mut node) => {
196 let result =
197 node.inner_mut()?._insert(key, val, hash, depth + 1);
198 *bucket = Bucket::Node(node);
200 result
201 }
202 }
203 }
204
205 fn collapse(&mut self) -> Option<(K, V)> {
207 match &mut self.0 {
208 [leaf @ Bucket::Leaf(..), Bucket::Empty, Bucket::Empty, Bucket::Empty]
209 | [Bucket::Empty, leaf @ Bucket::Leaf(..), Bucket::Empty, Bucket::Empty]
210 | [Bucket::Empty, Bucket::Empty, leaf @ Bucket::Leaf(..), Bucket::Empty]
211 | [Bucket::Empty, Bucket::Empty, Bucket::Empty, leaf @ Bucket::Leaf(..)] => {
212 if let Bucket::Leaf(KvPair { key, val }) =
213 mem::replace(leaf, Bucket::Empty)
214 {
215 Some((key, val))
216 } else {
217 unreachable!("Match above guarantees a `Bucket::Leaf`")
218 }
219 }
220 _ => None,
221 }
222 }
223
224 pub fn remove(&mut self, key: &K) -> Result<Option<V>, CanonError> {
225 let hash = Id::new(key).hash();
226 self._remove(key, hash, 0)
227 }
228
229 fn _remove(
230 &mut self,
231 key: &K,
232 hash: [u8; 32],
233 depth: usize,
234 ) -> Result<Option<V>, CanonError> {
235 let slot = slot(&hash, depth);
236 let bucket = &mut self.0[slot];
237
238 match bucket.take() {
239 Bucket::Empty => Ok(None),
240 Bucket::Leaf(KvPair {
241 key: old_key,
242 val: old_val,
243 }) => {
244 if *key == old_key {
245 Ok(Some(old_val))
246 } else {
247 Ok(None)
248 }
249 }
250
251 Bucket::Node(mut link) => {
252 let mut node = link.inner_mut()?;
253 let result = node._remove(key, hash, depth + 1);
254 if let Some((key, val)) = node.collapse() {
256 *bucket = Bucket::Leaf(KvPair { key, val });
257 } else {
258 drop(node);
259 *bucket = Bucket::Node(link);
260 }
261 result
262 }
263 }
264 }
265
266 pub fn get<'a>(
267 &'a self,
268 key: &K,
269 ) -> Result<Option<impl Deref<Target = V> + 'a>, CanonError> {
270 let hash = Id::new(key).hash();
271
272 Ok(Branch::walk(self, PathWalker::new(&hash))?
273 .filter(|branch| &(*branch).key == key)
274 .map(|b| b.map_leaf(|leaf| &leaf.val)))
275 }
276
277 pub fn get_mut<'a>(
278 &'a mut self,
279 key: &K,
280 ) -> Result<Option<impl DerefMut<Target = V> + 'a>, CanonError> {
281 let hash = Id::new(key).hash();
282 Ok(BranchMut::walk(self, PathWalker::new(&hash))?
283 .filter(|branch| &(*branch).key == key)
284 .map(|b| b.map_leaf(|leaf| &mut leaf.val)))
285 }
286}