ipld_collections/
map.rs

1use Bit::{One, Zero};
2
3use libipld::cache::{Cache, IpldCache};
4use libipld::cbor::DagCbor;
5use libipld::cbor::DagCborCodec;
6use libipld::cid::Cid;
7use libipld::error::Result;
8use libipld::ipld::Ipld;
9use libipld::multihash::Code;
10use libipld::multihash::Hasher;
11use libipld::prelude::{Decode, Encode};
12use libipld::store::Store;
13use libipld::store::StoreParams;
14use libipld::DagCbor;
15use std::cmp::PartialEq;
16use std::collections::BTreeMap;
17use std::fmt::Debug;
18use std::iter::once;
19
20const BUCKET_SIZE: usize = 1;
21const MAP_LEN: usize = 32;
22
23// For testing need a hash with easy collisions
24fn hash(bytes: &[u8]) -> Vec<u8> {
25    use libipld::multihash::{Identity256, Sha2_256};
26    if cfg!(test) {
27        Identity256::digest(bytes).as_ref().to_vec()
28    } else {
29        Sha2_256::digest(bytes).as_ref().to_vec()
30    }
31}
32
33macro_rules! validate {
34    ($block:expr) => {
35        if $block.data.len() != 0 && $block.data.len() != popcount_all(&$block.map) as usize {
36            todo!("Return error: Malformed block");
37        }
38    };
39}
40
41macro_rules! validate_or_empty {
42    ($block:expr) => {
43        if $block.data.len() == 0 && *$block.map != [0; 32]
44            || $block.data.len() != 0 && $block.data.len() != popcount_all(&$block.map) as usize
45        {
46            todo!("Return error: Malformed block");
47        }
48    };
49}
50
51#[derive(Clone, Debug, PartialEq, Eq)]
52struct PathNode<T: DagCbor> {
53    idx: usize,
54    block: Node<T>,
55}
56
57impl<T: DagCbor> PathNode<T> {
58    fn new(block: Node<T>, idx: usize) -> Self {
59        Self { block, idx }
60    }
61}
62
63// all the information needed to retrace the path down the tree, to "bubble up" changes
64// elements should alternate: block -> idx -> block -> idx -> ... -> block
65#[derive(Clone, Debug, PartialEq, Eq)]
66struct Path<T: DagCbor>(Vec<PathNode<T>>);
67
68impl<T: DagCbor> IntoIterator for Path<T> {
69    type Item = PathNode<T>;
70    type IntoIter = std::vec::IntoIter<Self::Item>;
71    fn into_iter(self) -> Self::IntoIter {
72        self.0.into_iter()
73    }
74}
75
76impl<T: DagCbor> Path<T> {
77    fn new() -> Self {
78        Path(vec![])
79    }
80    fn len(&self) -> usize {
81        self.0.len()
82    }
83    fn record(&mut self, block: Node<T>, idx: usize) {
84        self.0.push(PathNode::new(block, idx));
85    }
86    fn record_last(self, last: Node<T>) -> FullPath<T> {
87        FullPath::new(last, self)
88    }
89    fn pop(&mut self) -> Option<PathNode<T>> {
90        self.0.pop()
91    }
92}
93#[derive(Clone, Debug, PartialEq, Eq)]
94struct FullPath<T: DagCbor> {
95    path: Path<T>,
96    last: Node<T>,
97}
98
99impl<T: DagCbor> FullPath<T> {
100    fn new(last: Node<T>, path: Path<T>) -> Self {
101        Self { last, path }
102    }
103    // collapses last node in the path into the previous one if possible
104    fn reduce(&mut self, bucket_size: usize) {
105        let last = &self.last;
106        if !last.has_children() && !last.more_entries_than(bucket_size) && self.len() != 0 {
107            let next = self.path.pop().unwrap();
108            let PathNode { block, idx } = next;
109            let entries = self.last.extract();
110            let _ = std::mem::replace(&mut self.last, block);
111            self.last.data[idx] = Element::Bucket(entries);
112        }
113    }
114    fn len(&self) -> usize {
115        self.path.len()
116    }
117    // collapses all nodes that are possible into previous ones
118    fn full_reduce(&mut self, bucket_size: usize) {
119        let mut old = self.len();
120        let mut new = 0;
121        while old != new {
122            old = new;
123            self.reduce(bucket_size);
124            new = self.len();
125        }
126        self.last.unset_empty();
127    }
128}
129
130#[derive(Clone, Debug, PartialEq, Eq)]
131enum Bit {
132    Zero,
133    One,
134}
135
136#[derive(Clone, Debug, PartialEq, Eq)]
137enum InsertError<T: DagCbor> {
138    Id(Entry<T>, Cid, usize),
139    Overflow(Vec<Entry<T>>, usize),
140}
141
142#[derive(Clone, Debug, PartialEq, Eq)]
143enum RemoveError {
144    Id(Cid, usize),
145}
146
147#[cfg(test)]
148impl<T: DagCbor> InsertError<T> {
149    fn is_id(&self) -> bool {
150        if let InsertError::Id(_, _, _) = self {
151            true
152        } else {
153            false
154        }
155    }
156    fn is_overflow(&self) -> bool {
157        if let InsertError::Overflow(_, _) = self {
158            true
159        } else {
160            false
161        }
162    }
163}
164
165// number of bits from the left up to and excluding bit itself equal 1
166fn popcount(map: &[u8], bit: u8) -> u8 {
167    debug_assert!(map.len() * 8 >= bit.into());
168    let in_byte = (bit / 8) as usize;
169    let shifted = if bit % 8 == 0 {
170        0
171    } else {
172        let shifts = (7 - bit % 8) % 8 + 1;
173        map[in_byte] >> shifts
174    };
175    let mut count_ones = 0x00;
176    for &byte in map[0..in_byte].iter().chain(once(&shifted)) {
177        let mut shifted = byte;
178        for _bit in 0..=7 {
179            count_ones += 0x01 & shifted;
180            shifted >>= 1;
181        }
182    }
183    count_ones
184}
185
186fn popcount_all(map: &[u8]) -> u8 {
187    // if not true, can overflow
188    debug_assert!(map.len() * 8 <= 256);
189    let mut count_ones = 0x00;
190    for &byte in map.iter() {
191        let mut shifted = byte;
192        for _bit in 0..=7 {
193            count_ones += 0x01 & shifted;
194            shifted >>= 1;
195        }
196    }
197    count_ones
198}
199
200fn get_bit(map: &[u8], bit: u8) -> Bit {
201    debug_assert!(map.len() * 8 >= bit.into());
202    let in_byte = (bit / 8) as usize;
203    let shifts = (7 - bit % 8) % 8;
204    let byte = map[in_byte];
205    let bit = byte >> shifts & 0x01;
206    if bit == 0x01 {
207        One
208    } else {
209        Zero
210    }
211}
212
213fn set_bit(map: &mut [u8], bit: u8, val: Bit) {
214    debug_assert!(map.len() * 8 >= bit.into());
215    let in_byte = (bit / 8) as usize;
216    let shifts = (7 - bit % 8) % 8;
217    let bit = 0x01 << shifts;
218    match val {
219        Bit::One => {
220            map[in_byte] |= bit;
221        }
222        Bit::Zero => {
223            map[in_byte] &= !bit;
224        }
225    }
226}
227
228#[derive(Clone, Debug, Eq, PartialEq, DagCbor)]
229struct Node<T: DagCbor> {
230    // map has 2.pow(bit_width) bits, here 256
231    map: Box<[u8]>,
232    data: Vec<Element<T>>,
233}
234
235impl<T: DagCbor> Node<T> {
236    fn new() -> Self {
237        Self {
238            map: Box::new([0; MAP_LEN]),
239            data: vec![],
240        }
241    }
242    fn has_children(&self) -> bool {
243        self.data.iter().any(|elt| elt.is_hash_node())
244    }
245    fn more_entries_than(&self, bucket_size: usize) -> bool {
246        let mut acc = 0_usize;
247        for elt in self.data.iter() {
248            if let Element::Bucket(bucket) = elt {
249                acc += bucket.len();
250                if acc > bucket_size {
251                    return true;
252                }
253            }
254        }
255        false
256    }
257    fn extract(&mut self) -> Vec<Entry<T>> {
258        let mut entries = Vec::with_capacity(3);
259        for elt in self.data.iter_mut() {
260            match elt {
261                Element::Bucket(bucket) => {
262                    for elt in bucket.drain(0..) {
263                        entries.push(elt);
264                    }
265                }
266                _ => unreachable!(),
267            }
268        }
269        entries
270    }
271    fn get(&self, bit: u8) -> Option<&Element<T>> {
272        let idx = popcount(&self.map, bit);
273        match get_bit(&self.map, bit) {
274            Zero => None,
275            One => self.data.get(idx as usize),
276        }
277    }
278    fn unset_empty(&mut self) {
279        for bit in 0..=255 {
280            match self.get(bit) {
281                Some(Element::Bucket(bucket)) if bucket.is_empty() => {
282                    self.unset(bit);
283                }
284                _ => {}
285            }
286        }
287    }
288    #[cfg(test)]
289    fn set(&mut self, index: u8, element: Element<T>) {
290        let idx = popcount(&self.map, index);
291        match get_bit(&self.map, index) {
292            Zero => {
293                set_bit(&mut self.map, index, One);
294                self.data.insert(idx as usize, element);
295            }
296            One => {
297                self.data[idx as usize] = element;
298            }
299        }
300    }
301    fn unset(&mut self, index: u8) {
302        let idx = popcount(&self.map, index);
303        match get_bit(&self.map, index) {
304            Zero => {}
305            One => {
306                self.data.remove(idx as usize);
307                set_bit(&mut self.map, index, Zero);
308            }
309        }
310    }
311    // return Overflow with the removed elements if inserting element would overflow bucket
312    fn insert(
313        &mut self,
314        level: usize,
315        entry_with_hash: EntryWithHash<T>,
316        bucket_size: usize,
317    ) -> Result<(), InsertError<T>> {
318        use InsertError::{Id, Overflow};
319        let hash = entry_with_hash.hash;
320        let map_index = hash[level];
321        let bit = get_bit(&self.map, map_index);
322        let data_index = popcount(&self.map, map_index) as usize;
323        let EntryWithHash { entry, .. } = entry_with_hash;
324        match bit {
325            Zero => {
326                self.data.insert(data_index, Element::Bucket(vec![entry]));
327                set_bit(&mut self.map, map_index, One);
328                Ok(())
329            }
330            One => {
331                match &mut self.data[data_index] {
332                    Element::HashNode(cid) => Err(Id(entry, *cid, data_index)),
333                    Element::Bucket(ref mut bucket) => {
334                        let found = bucket
335                            .iter_mut()
336                            .find(|elt_mut_ref| elt_mut_ref.key == entry.key);
337                        match found {
338                            Some(elt) => elt.value = entry.value,
339                            None => {
340                                if bucket.len() < bucket_size {
341                                    bucket.push(entry)
342                                } else {
343                                    let mut overflow = vec![entry];
344                                    overflow.append(bucket);
345                                    return Err(Overflow(overflow, data_index));
346                                }
347                            }
348                        }
349                        // todo!("Inserting place has to be sorted.");
350                        Ok(())
351                    }
352                }
353            }
354        }
355    }
356    fn insert_all(
357        &mut self,
358        level: usize,
359        queue: &mut Queue<T>,
360        bucket_size: usize,
361    ) -> Result<(), InsertError<T>> {
362        while let Some(entry_with_hash) = queue.take() {
363            self.insert(level, entry_with_hash, bucket_size)?
364        }
365        Ok(())
366    }
367    fn remove(&mut self, level: usize, key: &[u8], hash: &[u8]) -> Result<(), RemoveError> {
368        use RemoveError::Id;
369        let map_index = hash[level];
370        let bit = get_bit(&self.map, map_index);
371        let data_index = popcount(&self.map, map_index) as usize;
372        match bit {
373            Zero => Ok(()),
374            One => {
375                let elt = &mut self.data[data_index];
376                match elt {
377                    Element::HashNode(cid) => Err(Id(*cid, data_index)),
378                    Element::Bucket(bucket) if bucket.len() != 1 => {
379                        for i in 0..bucket.len() {
380                            if &*bucket[i].key == key {
381                                bucket.remove(i);
382                                return Ok(());
383                            }
384                        }
385                        // todo!("Inserting place has to be sorted.");
386                        Ok(())
387                    }
388                    Element::Bucket(_) => {
389                        self.data.remove(data_index);
390                        set_bit(&mut self.map, map_index, Bit::Zero);
391                        Ok(())
392                    }
393                }
394            }
395        }
396    }
397}
398
399#[derive(Clone, Debug, Eq, PartialEq, DagCbor)]
400enum Element<T: DagCbor> {
401    HashNode(Cid),
402    Bucket(Vec<Entry<T>>),
403}
404
405impl<T: DagCbor> Default for Element<T> {
406    fn default() -> Self {
407        Element::Bucket(vec![])
408    }
409}
410
411impl<T: DagCbor> Element<T> {
412    fn is_hash_node(&self) -> bool {
413        match self {
414            Element::HashNode(_) => true,
415            Element::Bucket(_) => false,
416        }
417    }
418}
419
420#[derive(Clone, Debug, Eq, PartialEq, DagCbor)]
421struct Entry<T: DagCbor> {
422    key: Box<[u8]>,
423    value: T,
424}
425
426impl<T: DagCbor> Entry<T> {
427    pub fn new<I: Into<Box<[u8]>>>(key: I, value: T) -> Self {
428        Entry {
429            key: key.into(),
430            value,
431        }
432    }
433    fn with_hash(self) -> EntryWithHash<T> {
434        let hash = hash(&self.key);
435        EntryWithHash { entry: self, hash }
436    }
437}
438
439#[derive(Clone, Debug, Eq, PartialEq)]
440struct Queue<T: DagCbor> {
441    entries: Vec<EntryWithHash<T>>,
442}
443
444impl<T: DagCbor> Queue<T> {
445    fn new() -> Self {
446        Self { entries: vec![] }
447    }
448    fn take(&mut self) -> Option<EntryWithHash<T>> {
449        self.entries.pop()
450    }
451    fn add(&mut self, entry: Entry<T>) {
452        self.entries.insert(0, entry.with_hash());
453    }
454}
455
456#[derive(Clone, Debug, Eq, PartialEq)]
457struct EntryWithHash<T: DagCbor> {
458    entry: Entry<T>,
459    hash: Vec<u8>,
460}
461
462pub struct Hamt<S: Store, T: DagCbor> {
463    bucket_size: usize,
464    nodes: IpldCache<S, DagCborCodec, Node<T>>,
465    root: Cid,
466}
467
468impl<S: Store, T: Clone + DagCbor + Send + Sync> Hamt<S, T>
469where
470    S: Store,
471    S::Params: StoreParams<Hashes = Code>,
472    <S::Params as StoreParams>::Codecs: Into<DagCborCodec>,
473    DagCborCodec: Into<<S::Params as StoreParams>::Codecs>,
474    T: Decode<DagCborCodec> + Encode<DagCborCodec> + Clone + Send + Sync,
475    Ipld: Decode<<S::Params as StoreParams>::Codecs>,
476{
477    pub async fn from<I: Into<Box<[u8]>>>(
478        store: S,
479        cache_size: usize,
480        btree: BTreeMap<I, T>,
481    ) -> Result<Self> {
482        let mut hamt = Hamt::new(store, cache_size).await?;
483        for (key, value) in btree {
484            hamt.insert(key.into(), value).await?;
485        }
486        Ok(hamt)
487    }
488    // retrace the path traveled backwards, "bubbling up" the changes
489    async fn bubble_up(&mut self, full_path: FullPath<T>) -> Result<Cid> {
490        let FullPath {
491            last: mut block,
492            path,
493        } = full_path;
494        let path = path.into_iter().rev();
495        let mut cid = self.nodes.insert(block).await?;
496        for elt in path {
497            let PathNode { idx, block: node } = elt;
498            block = node;
499            block.data[idx] = Element::HashNode(cid);
500            cid = self.nodes.insert(block).await?;
501        }
502        Ok(cid)
503    }
504    pub async fn new(store: S, cache_size: usize) -> Result<Self> {
505        let cache = IpldCache::new(store, DagCborCodec, Code::Blake2b256, cache_size);
506        let root = cache.insert(Node::new()).await?;
507        Ok(Self {
508            bucket_size: BUCKET_SIZE,
509            nodes: cache,
510            root,
511        })
512    }
513
514    pub async fn open(store: S, cache_size: usize, root: Cid) -> Result<Self> {
515        let cache = IpldCache::new(store, DagCborCodec, Code::Blake2b256, cache_size);
516        // warm up the cache and make sure it's available
517        cache.get(&root).await?;
518        Ok(Self {
519            bucket_size: 3,
520            nodes: cache,
521            root,
522        })
523    }
524
525    pub async fn get(&mut self, key: &[u8]) -> Result<Option<T>> {
526        // TODO calculate correct hash
527        let hash = hash(&key);
528
529        let mut current = self.nodes.get(&self.root).await?;
530        validate_or_empty!(current);
531        for index in hash.iter() {
532            let bit = get_bit(&current.map, *index);
533            if let Bit::Zero = bit {
534                return Ok(None);
535            }
536            let data_index = popcount(&current.map, *index) as usize;
537            let Node { mut data, .. } = current;
538            current = match data.remove(data_index) {
539                Element::HashNode(cid) => self.nodes.get(&cid).await?,
540                Element::Bucket(bucket) => {
541                    for elt in bucket {
542                        if &*elt.key == key {
543                            let Entry { value, .. } = elt;
544                            return Ok(Some(value));
545                        }
546                    }
547                    return Ok(None);
548                }
549            };
550            validate!(current);
551        }
552        Ok(None)
553    }
554    pub fn root(&self) -> &Cid {
555        &self.root
556    }
557    pub async fn insert(&mut self, key: Box<[u8]>, value: T) -> Result<()> {
558        let mut queue = Queue::new();
559        let hash_len = hash(&key).len();
560        queue.add(Entry::new(key, value));
561        let mut path = Path::new();
562        // start from root going down
563        let mut current = self.nodes.get(&self.root).await?;
564        for lvl in 0..hash_len {
565            // validate_or_empty!(current);
566            use InsertError::{Id, Overflow};
567            match current.insert_all(lvl, &mut queue, self.bucket_size) {
568                Ok(_) => {
569                    let full_path = path.record_last(current);
570                    // recalculate cids recursively
571                    self.root = self.bubble_up(full_path).await?;
572                    return Ok(());
573                }
574                Err(Id(entry, cid, data_index)) => {
575                    path.record(current, data_index);
576                    queue.add(entry);
577                    current = self.nodes.get(&cid).await?;
578                    validate!(current);
579                }
580                Err(Overflow(overflow, data_index)) => {
581                    for elt in overflow {
582                        queue.add(elt);
583                    }
584                    path.record(current, data_index);
585                    current = Node::new();
586                }
587            }
588        }
589        todo!("Output error due to maximum collision depth reached");
590    }
591    pub async fn remove(&mut self, key: &[u8]) -> Result<()> {
592        use RemoveError::Id;
593        let hash = hash(key);
594        let hash_len = hash.len();
595        let mut path = Path::new();
596        // start from root going down
597        let mut current = self.nodes.get(&self.root).await?;
598        // validate_or_empty!(current);
599        for lvl in 0..hash_len {
600            match current.remove(lvl, key, &hash) {
601                Ok(_) => {
602                    let mut full_path = path.record_last(current);
603                    full_path.full_reduce(self.bucket_size);
604                    // recalculate cids recursively
605                    self.root = self.bubble_up(full_path).await?;
606                    return Ok(());
607                }
608                Err(Id(cid, data_index)) => {
609                    path.record(current, data_index);
610                    current = self.nodes.get(&cid).await?;
611                    validate!(current);
612                }
613            }
614        }
615        todo!("Output error due to maximum collision depth reached");
616    }
617}
618
619#[cfg(test)]
620mod tests {
621    use super::*;
622    use async_std::task;
623    use libipld::mem::MemStore;
624    use libipld::store::DefaultParams;
625    use proptest::prelude::*;
626
627    #[test]
628    fn test_popcount() {
629        assert_eq!(popcount(&[0b0000_0001], 0), 0);
630        assert_eq!(popcount(&[0b0000_0001], 7), 0);
631        assert_eq!(popcount(&[0b0000_0010], 7), 1);
632        assert_eq!(popcount(&[0b0000_0011], 7), 1);
633        assert_eq!(popcount(&[0b0000_0100], 7), 1);
634        assert_eq!(popcount(&[0b0000_0101], 7), 1);
635        assert_eq!(popcount(&[0b0000_0110], 7), 2);
636        assert_eq!(popcount(&[0b0000_0111], 7), 2);
637        assert_eq!(popcount(&[0b0000_1000], 7), 1);
638    }
639
640    fn strat_bit_value() -> impl Strategy<Value = Bit> {
641        prop_oneof![Just(Bit::Zero), Just(Bit::One),]
642    }
643
644    fn strat_vec_and_bit() -> impl Strategy<Value = (Vec<u8>, u8)> {
645        prop::collection::vec(0..255u8, 2..32).prop_flat_map(|vec| {
646            let len = vec.len();
647            (Just(vec), 8..(len * 8) as u8)
648        })
649    }
650
651    proptest! {
652        #[test]
653        fn test_popcount_invariant((vec, bit) in strat_vec_and_bit()) {
654            let mut shift = vec.clone();
655
656            shift.pop();
657            shift.insert(0, 0);
658            assert_eq!(popcount(&shift, bit), popcount(&vec, bit - 8));
659        }
660
661        #[test]
662        fn test_popcount_shift((vec, bit) in strat_vec_and_bit()) {
663            let mut set_one_zero = vec.clone();
664            set_bit(&mut set_one_zero, bit - 1, Bit::Zero);
665            assert_eq!(popcount(&set_one_zero, bit), popcount(&vec, bit - 1));
666        }
667
668        #[test]
669        fn test_set_and_get((mut vec, bit) in strat_vec_and_bit(),val in strat_bit_value()) {
670            set_bit(&mut vec, bit, val.clone());
671            assert_eq!(get_bit(&vec, bit), val);
672        }
673    }
674
675    #[test]
676    fn test_get_bit() {
677        assert_eq!(get_bit(&[0b0000_0001], 7), Bit::One);
678        assert_eq!(get_bit(&[0b0000_0010], 6), Bit::One);
679        assert_eq!(get_bit(&[0b0000_0100], 5), Bit::One);
680        assert_eq!(get_bit(&[0b0000_1000], 4), Bit::One);
681        assert_eq!(get_bit(&[0b0001_0000], 3), Bit::One);
682        assert_eq!(get_bit(&[0b0010_0000], 2), Bit::One);
683        assert_eq!(get_bit(&[0b0100_0000], 1), Bit::One);
684        assert_eq!(get_bit(&[0b1000_0000], 0), Bit::One);
685    }
686
687    fn dummy_node() -> Node<u8> {
688        Node {
689            map: Box::new([0_u8]),
690            data: vec![],
691        }
692    }
693
694    async fn dummy_hamt() -> Hamt<MemStore<DefaultParams>, u8> {
695        let store = MemStore::default();
696        Hamt::new(store, 12).await.unwrap()
697    }
698
699    #[async_std::test]
700    async fn test_dummy_hamt() {
701        let hamt = dummy_hamt().await;
702        assert_eq!(
703            &[
704                17, 5, 205, 113, 186, 135, 108, 41, 45, 228, 103, 3, 117, 148, 111, 12, 194, 34,
705                144, 30, 201, 157, 222, 81, 41, 154, 114, 30, 207, 222, 150, 53
706            ],
707            hamt.root.hash().digest()
708        );
709    }
710
711    #[test]
712    fn test_node_insert() {
713        let mut node = dummy_node();
714        assert_eq!(
715            node.insert(0, Entry::new([0, 0, 0], 0).with_hash(), 3),
716            Ok(())
717        );
718        assert_eq!(
719            node.insert(0, Entry::new([0, 0, 1], 0).with_hash(), 3),
720            Ok(())
721        );
722        assert_eq!(
723            node.insert(0, Entry::new([0, 0, 2], 1).with_hash(), 3),
724            Ok(())
725        );
726        assert!(node
727            .insert(0, Entry::new([0, 0, 3], 3).with_hash(), 3)
728            .unwrap_err()
729            .is_overflow());
730    }
731    #[test]
732    fn test_node_remove() {
733        let mut node = dummy_node();
734        assert_eq!(node.insert(1, Entry::new([0, 0], 0).with_hash(), 1), Ok(()));
735        assert_eq!(node.insert(1, Entry::new([0, 1], 0).with_hash(), 1), Ok(()));
736        assert_eq!(node.remove(1, &[0, 0], &[0, 0]), Ok(()));
737        assert_eq!(node.remove(1, &[0, 1], &[0, 1]), Ok(()));
738        assert_eq!(node, dummy_node());
739    }
740
741    #[test]
742    fn test_node_methods() {
743        let mut node = dummy_node();
744        let entries = vec![
745            Entry::new([0, 0, 0], 0),
746            Entry::new([0, 0, 1], 0),
747            Entry::new([0, 0, 2], 0),
748            Entry::new([1, 0, 2], 0),
749        ];
750        for elt in entries.iter().take(3) {
751            let _ = node.insert(0, elt.clone().with_hash(), 3);
752        }
753        assert!(!node.has_children());
754        assert!(!node.more_entries_than(3));
755        let _ = node.insert(0, entries[3].clone().with_hash(), 3);
756        assert!(node.more_entries_than(3));
757        assert_eq!(node.extract(), entries);
758
759        let mut node: Node<u8> = Node::new();
760        node.set(3, Element::default());
761        node.unset(3);
762        assert_eq!(node, Node::new());
763        for i in 0..=255 {
764            node.set(i, Element::default());
765            node.set(i, Element::default());
766        }
767        for i in 0..=255 {
768            node.unset(i);
769            node.unset(i);
770        }
771        assert_eq!(node, Node::new());
772    }
773
774    #[async_std::test]
775    async fn test_bubble_up() {
776        let mut hamt = dummy_hamt().await;
777        let mut node1 = dummy_node();
778        let mut node2 = dummy_node();
779        node1.set(0, Element::Bucket(vec![]));
780        let cid = hamt.nodes.insert(node1).await.unwrap();
781        node2.set(0, Element::HashNode(cid));
782        let cid = hamt.nodes.insert(node2).await.unwrap();
783        hamt.root = cid;
784
785        let mut hamt_clone = dummy_hamt().await;
786        let mut node1_clone = dummy_node();
787        node1_clone.set(0, Element::Bucket(vec![]));
788        let mut node2_clone = dummy_node();
789        let mut path = Path::new();
790        node2_clone.set(0, Element::Bucket(vec![]));
791        path.record(node2_clone, 0);
792        let full_path = path.record_last(node1_clone);
793        let cid = hamt_clone.bubble_up(full_path).await.unwrap();
794        hamt_clone.root = cid;
795
796        assert_eq!(hamt.root, hamt_clone.root);
797        let block = hamt.nodes.get(&hamt.root).await.unwrap();
798        let block_compare = hamt_clone.nodes.get(&hamt_clone.root).await.unwrap();
799        assert_eq!(block, block_compare);
800    }
801
802    #[async_std::test]
803    async fn test_reduce() {
804        let size = 2;
805        let entries = vec![Entry::new([0, 0], 0), Entry::new([0, 1], 0)];
806        let mut node = Node::new();
807        node.set(0, Element::HashNode(Cid::default()));
808        let mut path = Path::new();
809        path.record(node, 0);
810        let mut next = Node::new();
811        next.set(0, Element::Bucket(vec![entries[0].clone()]));
812        next.set(1, Element::Bucket(vec![entries[1].clone()]));
813        let mut full_path = path.record_last(next);
814        let pre_len = full_path.len();
815
816        full_path.reduce(size);
817        let post_len = full_path.len();
818        assert!(pre_len != post_len);
819    }
820
821    #[async_std::test]
822    async fn test_hamt_insert() {
823        // insert single element
824        let mut hamt = dummy_hamt().await;
825        let entry = Entry::new([0, 0, 0], 0);
826        hamt.insert(entry.key, entry.value).await.unwrap();
827        let mut node = Node::new();
828        let _ = node.insert(0, Entry::new([0, 0, 0], 0).with_hash(), 3);
829        assert_eq!(node, hamt.nodes.get(&hamt.root).await.unwrap());
830        let mut hamt = dummy_hamt().await;
831        let entry1 = Entry::new([0, 0, 0], 0);
832        let entry2 = Entry::new([0, 0, 1], 0);
833        let entry3 = Entry::new([0, 0, 2], 0);
834        let entry4 = Entry::new([0, 0, 3], 0);
835        let entries = vec![entry1, entry2, entry3, entry4];
836        let copy = entries.clone();
837        for entry in entries {
838            hamt.insert(entry.key, entry.value).await.unwrap();
839        }
840        let mut node = hamt.nodes.get(&hamt.root).await.unwrap();
841        assert_eq!(
842            &hamt.root.hash().digest(),
843            &[
844                10, 133, 110, 7, 1, 116, 103, 149, 130, 193, 198, 132, 161, 142, 33, 76, 89, 142,
845                81, 181, 60, 135, 167, 116, 140, 112, 168, 13, 40, 172, 223, 90
846            ]
847        );
848        assert!(node
849            .insert(0, copy[0].clone().with_hash(), 3)
850            .unwrap_err()
851            .is_id());
852        for entry in copy {
853            assert_eq!(Some(entry.value), hamt.get(&entry.key).await.unwrap());
854        }
855    }
856    proptest! {
857        #[test]
858        fn test_hamt_set_and_get(batch in prop::collection::vec((prop::collection::vec(0..=255u8, 6), 0..1u8), 20)) {
859            let _ = task::block_on(batch_set_and_get(batch)).unwrap();
860        }
861        #[test]
862        fn test_hamt_remove_and_get(batch in prop::collection::vec((prop::collection::vec(0..=255u8, 6), 0..1u8), 20)) {
863            let _ = task::block_on(batch_remove_and_get(batch)).unwrap();
864        }
865    }
866
867    async fn batch_set_and_get(batch: Vec<(Vec<u8>, u8)>) -> Result<()> {
868        let mut hamt = dummy_hamt().await;
869        for elt in batch.into_iter() {
870            let (key, val) = elt;
871            hamt.insert(key.clone().into(), val).await?;
872            let elt = hamt.get(&key).await?;
873            assert_eq!(elt, Some(val));
874        }
875        Ok(())
876    }
877    async fn batch_remove_and_get(mut batch: Vec<(Vec<u8>, u8)>) -> Result<()> {
878        let mut other = dummy_hamt().await;
879        let mut hamt = dummy_hamt().await;
880        let size = batch.len();
881
882        // make sure there are no repeated keys
883        batch.sort();
884        batch.dedup_by(|a, b| a.0 == b.0);
885
886        let insert_batch = batch.clone();
887        let mut remove_batch = vec![];
888        let mut get_batch = vec![];
889        for (counter, elt) in batch.into_iter().enumerate() {
890            if counter <= size / 2 {
891                get_batch.push(elt);
892            } else {
893                remove_batch.push(elt);
894            }
895        }
896        for elt in insert_batch.into_iter() {
897            let (key, val) = elt;
898            hamt.insert(key.clone().into(), val).await?;
899        }
900        for elt in remove_batch.into_iter() {
901            let (key, _) = elt;
902            hamt.remove(&key).await?;
903        }
904
905        // inserting n elements into a hamt other should give equal root cid as
906        // inserting additional n elements and deleting them
907        let insert_other_batch = get_batch.clone();
908        for elt in insert_other_batch.into_iter() {
909            let (key, val) = elt;
910            other.insert(key.clone().into(), val).await?;
911        }
912
913        // the non-removed elements should be retrievable
914        for elt in get_batch.into_iter() {
915            let (key, _) = elt;
916            assert!(hamt.get(&key).await?.is_some());
917        }
918
919        assert_eq!(hamt.root, other.root);
920        Ok(())
921    }
922    #[async_std::test]
923    async fn test_remove() {
924        // first deletion test
925        let mut other = dummy_hamt().await;
926        let mut hamt = dummy_hamt().await;
927        let entries = vec![
928            Entry::new([0, 0], 0),
929            Entry::new([0, 1], 0),
930            // Entry::new(vec![0, 2], 0),
931            // Entry::new(vec![0, 3], 0),
932        ];
933        let mut entries_clone = entries.clone();
934        for entry in entries {
935            hamt.insert(entry.key, entry.value).await.unwrap();
936        }
937        let entry = entries_clone.pop().unwrap();
938        other.insert(entry.key, entry.value).await.unwrap();
939        for entry in entries_clone {
940            hamt.remove(&entry.key).await.unwrap();
941        }
942        assert_eq!(hamt.root, other.root);
943    }
944}