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
23fn 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#[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 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 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
165fn 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 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: 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 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 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 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 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 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 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(¤t.map, *index);
533 if let Bit::Zero = bit {
534 return Ok(None);
535 }
536 let data_index = popcount(¤t.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 let mut current = self.nodes.get(&self.root).await?;
564 for lvl in 0..hash_len {
565 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 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 let mut current = self.nodes.get(&self.root).await?;
598 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 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 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 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 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 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 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 ];
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}