Skip to main content

hashed_array_tree/
lib.rs

1//
2// Copyright (c) 2025 Nathan Fiedler
3//
4
5//! An implementation of Hashed Array Trees by Edward Sitarski.
6//!
7//! From the original article:
8//!
9//! > To overcome the limitations of variable-length arrays, I created a data
10//! > structure that has fast constant access time like an array, but mostly
11//! > avoids copying elements when it grows. I call this new structure a
12//! > "Hashed-Array Tree" (HAT) because it combines some of the features of hash
13//! > tables, arrays, and trees.
14//!
15//! To achieve this, the data structure uses a standard growable vector to
16//! reference separate data blocks which hold the array elements. The index and
17//! the blocks are at most O(√N) in size. As more elements are added, the size
18//! of the index and blocks will grow by powers of two (4, 8, 16, 32, etc).
19//!
20//! # Memory Usage
21//!
22//! An empty hased array tree is approximately 72 bytes in size, and while
23//! holding elements it will have a space overhead on the order of O(√N). As
24//! elements are added the array will grow by allocating additional data blocks.
25//! Likewise, as elements are removed from the end of the array, data blocks
26//! will be deallocated as they become empty.
27//!
28//! # Performance
29//!
30//! The get and set operations are O(1) while the push and pop may take O(N) in
31//! the worst case, if the array needs to be grown or shrunk.
32//!
33//! # Safety
34//!
35//! Because this data structure is allocating memory, copying bytes using
36//! pointers, and de-allocating memory as needed, there are many `unsafe` blocks
37//! throughout the code.
38
39use std::alloc::{Layout, alloc, dealloc, handle_alloc_error};
40use std::cmp::Ordering;
41use std::fmt;
42use std::ops::{Index, IndexMut};
43
44/// Hashed Array Tree (HAT) described by Edward Sitarski.
45pub struct HashedArrayTree<T> {
46    /// top array that holds pointers to data blocks ("leaves")
47    index: Vec<*mut T>,
48    /// number of elements in the array
49    count: usize,
50    /// index and leaves are 2^k in length
51    k: usize,
52    /// bit-mask to get the index into a leaf array
53    k_mask: usize,
54    /// the number of slots in the top array and leaves
55    l: usize,
56    /// when size increases to upper_limit, an expand is required
57    upper_limit: usize,
58    /// when size decreases to lower_limit, a compress is required
59    lower_limit: usize,
60}
61
62impl<T> HashedArrayTree<T> {
63    /// Returns a hashed array tree with zero capacity.
64    pub fn new() -> Self {
65        let index: Vec<*mut T> = vec![];
66        Self {
67            index,
68            count: 0,
69            k: 2,
70            k_mask: 3,
71            l: 4,
72            upper_limit: 16,
73            lower_limit: 0,
74        }
75    }
76
77    /// Double the capacity of this array by combining its leaves into new
78    /// leaves of double the capacity.
79    fn expand(&mut self) {
80        let l_prime = 1 << (self.k + 1);
81        let old_index: Vec<*mut T> = std::mem::take(&mut self.index);
82        let mut iter = old_index.into_iter();
83        while let Some(a) = iter.next() {
84            let layout = Layout::array::<T>(l_prime).expect("unexpected overflow");
85            let buffer = unsafe {
86                let ptr = alloc(layout).cast::<T>();
87                if ptr.is_null() {
88                    handle_alloc_error(layout);
89                }
90                ptr
91            };
92            if let Some(b) = iter.next() {
93                let b_dst = unsafe { buffer.add(self.l) };
94                let old_layout = Layout::array::<T>(self.l).expect("unexpected overflow");
95                unsafe {
96                    std::ptr::copy(a, buffer, self.l);
97                    std::ptr::copy(b, b_dst, self.l);
98                    dealloc(a as *mut u8, old_layout);
99                    dealloc(b as *mut u8, old_layout);
100                }
101            } else {
102                let old_layout = Layout::array::<T>(self.l).expect("unexpected overflow");
103                unsafe {
104                    std::ptr::copy(a, buffer, self.l);
105                    dealloc(a as *mut u8, old_layout);
106                }
107            }
108            self.index.push(buffer);
109        }
110        self.k += 1;
111        self.k_mask = (1 << self.k) - 1;
112        self.l = 1 << self.k;
113        self.upper_limit = self.l * self.l;
114        self.lower_limit = self.upper_limit / 8;
115    }
116
117    /// Appends an element to the back of a collection.
118    ///
119    /// # Panics
120    ///
121    /// Panics if a new block is allocated that would exceed `isize::MAX` _bytes_.
122    ///
123    /// # Time complexity
124    ///
125    /// O(N) in the worst case (expand).
126    pub fn push(&mut self, value: T) {
127        let len = self.count;
128        if len >= self.upper_limit {
129            self.expand();
130        }
131        if len >= self.capacity() {
132            let layout = Layout::array::<T>(self.l).expect("unexpected overflow");
133            let buffer = unsafe {
134                let ptr = alloc(layout).cast::<T>();
135                if ptr.is_null() {
136                    handle_alloc_error(layout);
137                }
138                ptr
139            };
140            self.index.push(buffer);
141        }
142        let block = len >> self.k;
143        let slot = len & self.k_mask;
144        unsafe { self.index[block].add(slot).write(value) }
145        self.count += 1;
146    }
147
148    /// Appends an element if there is sufficient spare capacity, otherwise an
149    /// error is returned with the element.
150    ///
151    /// # Time complexity
152    ///
153    /// O(N) in the worst case (expand).
154    pub fn push_within_capacity(&mut self, value: T) -> Result<(), T> {
155        if self.capacity() <= self.count {
156            Err(value)
157        } else {
158            self.push(value);
159            Ok(())
160        }
161    }
162
163    /// Like [`Self::get()`] but without the `Option` wrapper.
164    ///
165    /// Will panic if the index is out of bounds.
166    fn raw_get(&self, index: usize) -> &T {
167        let block = index >> self.k;
168        let slot = index & self.k_mask;
169        unsafe { &*self.index[block].add(slot) }
170    }
171
172    /// Retrieve a reference to the element at the given offset.
173    ///
174    /// # Time complexity
175    ///
176    /// Constant time.
177    pub fn get(&self, index: usize) -> Option<&T> {
178        if index >= self.count {
179            None
180        } else {
181            Some(self.raw_get(index))
182        }
183    }
184
185    /// Returns a mutable reference to an element.
186    ///
187    /// # Time complexity
188    ///
189    /// Constant time.
190    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
191        if index >= self.count {
192            None
193        } else {
194            let block = index >> self.k;
195            let slot = index & self.k_mask;
196            unsafe { (self.index[block].add(slot)).as_mut() }
197        }
198    }
199
200    /// Shrink the capacity of this array by splitting its leaves into new
201    /// leaves of half the capacity.
202    fn compress(&mut self) {
203        let old_index: Vec<*mut T> = std::mem::take(&mut self.index);
204        for old_buffer in old_index.into_iter() {
205            let half = self.l / 2;
206            let layout = Layout::array::<T>(half).expect("unexpected overflow");
207            let a = unsafe {
208                let ptr = alloc(layout).cast::<T>();
209                if ptr.is_null() {
210                    handle_alloc_error(layout);
211                }
212                ptr
213            };
214            let b = unsafe {
215                let ptr = alloc(layout).cast::<T>();
216                if ptr.is_null() {
217                    handle_alloc_error(layout);
218                }
219                ptr
220            };
221            unsafe {
222                std::ptr::copy(old_buffer, a, half);
223                std::ptr::copy(old_buffer.add(half), b, half);
224            };
225            let layout = Layout::array::<T>(self.l).expect("unexpected overflow");
226            unsafe {
227                dealloc(old_buffer as *mut u8, layout);
228            }
229            self.index.push(a);
230            self.index.push(b);
231        }
232        self.k -= 1;
233        self.k_mask = (1 << self.k) - 1;
234        self.l = 1 << self.k;
235        self.upper_limit = self.l * self.l;
236        self.lower_limit = self.upper_limit / 8;
237    }
238
239    /// Like [`Self::pop()`] but without the `Option` wrapper.
240    ///
241    /// Will panic if the array is empty.
242    pub fn raw_pop(&mut self) -> T {
243        let index = self.count - 1;
244        // avoid compressing the leaves smaller than 4
245        if index < self.lower_limit && self.k > 2 {
246            self.compress();
247        }
248        let block = index >> self.k;
249        let slot = index & self.k_mask;
250        let ret = unsafe { self.index[block].add(slot).read() };
251        if slot == 0 {
252            // prune leaves as they become empty
253            let ptr = self.index.pop().unwrap();
254            let layout = Layout::array::<T>(self.l).expect("unexpected overflow");
255            unsafe {
256                dealloc(ptr as *mut u8, layout);
257            }
258        }
259        self.count -= 1;
260        ret
261    }
262
263    /// Removes the last element from the array and returns it, or `None` if the
264    /// array is empty.
265    ///
266    /// # Time complexity
267    ///
268    /// O(N) in the worst case (shrink).
269    pub fn pop(&mut self) -> Option<T> {
270        if self.count > 0 {
271            Some(self.raw_pop())
272        } else {
273            None
274        }
275    }
276
277    /// Removes and returns the last element from an array if the predicate
278    /// returns true, or `None`` if the predicate returns `false`` or the array
279    /// is empty (the predicate will not be called in that case).
280    ///
281    /// # Time complexity
282    ///
283    /// O(N) in the worst case (shrink).
284    pub fn pop_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option<T> {
285        if self.count == 0 {
286            None
287        } else if let Some(last) = self.get_mut(self.count - 1) {
288            if predicate(last) { self.pop() } else { None }
289        } else {
290            None
291        }
292    }
293
294    /// Removes an element from the array and returns it.
295    ///
296    /// The removed element is replaced by the last element of the array.
297    ///
298    /// This does not preserve ordering of the remaining elements.
299    ///
300    /// # Panics
301    ///
302    /// Panics if the index is out of bounds.
303    ///
304    /// # Time complexity
305    ///
306    /// O(N) in the worst case (shrink).
307    pub fn swap_remove(&mut self, index: usize) -> T {
308        if index >= self.count {
309            panic!(
310                "swap_remove index (is {index}) should be < len (is {})",
311                self.count
312            );
313        }
314        // retreive the value at index before overwriting
315        let block = index >> self.k;
316        let slot = index & self.k_mask;
317        unsafe {
318            let index_ptr = self.index[block].add(slot);
319            let value = index_ptr.read();
320            // find the pointer of the last element and copy to index pointer
321            let block = (self.count - 1) >> self.k;
322            let slot = (self.count - 1) & self.k_mask;
323            let last_ptr = self.index[block].add(slot);
324            std::ptr::copy(last_ptr, index_ptr, 1);
325            if slot == 0 {
326                // prune leaves as they become empty
327                let ptr = self.index.pop().unwrap();
328                let layout = Layout::array::<T>(self.l).expect("unexpected overflow");
329                dealloc(ptr as *mut u8, layout);
330            }
331            self.count -= 1;
332            value
333        }
334    }
335
336    /// Returns an iterator over the array.
337    ///
338    /// The iterator yields all items from start to end.
339    pub fn iter(&self) -> ArrayIter<'_, T> {
340        ArrayIter {
341            array: self,
342            index: 0,
343            count: self.count,
344        }
345    }
346
347    /// Returns an iterator that allows modifying each value.
348    ///
349    /// The iterator yields all items from start to end.
350    pub fn iter_mut(&mut self) -> ArrayIterMut<'_, T> {
351        ArrayIterMut {
352            dope: self.index.as_mut_ptr(),
353            index: 0,
354            count: self.count,
355            k: self.k,
356            k_mask: self.k_mask,
357            _marker: std::marker::PhantomData,
358        }
359    }
360
361    /// Return the number of elements in the array.
362    ///
363    /// # Time complexity
364    ///
365    /// Constant time.
366    pub fn len(&self) -> usize {
367        self.count
368    }
369
370    /// Returns the total number of elements the array can hold without
371    /// reallocating.
372    ///
373    /// # Time complexity
374    ///
375    /// Constant time.
376    pub fn capacity(&self) -> usize {
377        (1 << self.k) * self.index.len()
378    }
379
380    /// Returns true if the array has a length of 0.
381    ///
382    /// # Time complexity
383    ///
384    /// Constant time.
385    pub fn is_empty(&self) -> bool {
386        self.count == 0
387    }
388
389    /// Clears the array, removing all values and deallocating all leaves.
390    ///
391    /// # Time complexity
392    ///
393    /// O(N) if elements are droppable, otherwise O(√N)
394    pub fn clear(&mut self) {
395        use std::ptr::{drop_in_place, slice_from_raw_parts_mut};
396
397        if self.count > 0 && std::mem::needs_drop::<T>() {
398            // find the last leaf that contains values and drop them
399            let last_index = self.count - 1;
400            let last_block = last_index >> self.k;
401            let last_slot = last_index & self.k_mask;
402            unsafe {
403                // last_slot is pointing at the last element, need to add
404                // one to include it in the slice
405                drop_in_place(slice_from_raw_parts_mut(
406                    self.index[last_block],
407                    last_slot + 1,
408                ));
409            }
410
411            // drop the values in all of the preceding leaves
412            for block in 0..last_block {
413                unsafe {
414                    drop_in_place(slice_from_raw_parts_mut(self.index[block], self.l));
415                }
416            }
417        }
418
419        // deallocate all leaves using the index as the source of truth
420        let layout = Layout::array::<T>(self.l).expect("unexpected overflow");
421        for block in 0..self.index.len() {
422            unsafe {
423                dealloc(self.index[block] as *mut u8, layout);
424            }
425        }
426        self.index.clear();
427
428        self.count = 0;
429        self.k = 2;
430        self.k_mask = 3;
431        self.l = 1 << self.k;
432        self.upper_limit = self.l * self.l;
433        self.lower_limit = 0;
434    }
435
436    /// Swap two elements in the array.
437    ///
438    /// # Panics
439    ///
440    /// Panics if either index is out of bounds.
441    pub fn swap(&mut self, a: usize, b: usize) {
442        if a >= self.count {
443            panic!("swap a (is {a}) should be < len (is {})", self.count);
444        }
445        if b >= self.count {
446            panic!("swap b (is {b}) should be < len (is {})", self.count);
447        }
448        // save the value in slot a before overwriting with value from slot b,
449        // then write the saved value to slot b
450        let a_block = a >> self.k;
451        let a_slot = a & self.k_mask;
452        let b_block = b >> self.k;
453        let b_slot = b & self.k_mask;
454        unsafe {
455            let a_ptr = self.index[a_block].add(a_slot);
456            let value = a_ptr.read();
457            let b_ptr = self.index[b_block].add(b_slot);
458            std::ptr::copy(b_ptr, a_ptr, 1);
459            b_ptr.write(value);
460        }
461    }
462
463    /// Sorts the slice in ascending order with a comparison function,
464    /// **without** preserving the initial order of equal elements.
465    ///
466    /// This sort is unstable (i.e., may reorder equal elements), in-place
467    /// (i.e., does not allocate), and *O*(*n* \* log(*n*)) worst-case.
468    ///
469    /// Implements the standard heapsort algorithm.
470    pub fn sort_unstable_by<F>(&mut self, mut compare: F)
471    where
472        F: FnMut(&T, &T) -> Ordering,
473    {
474        if self.count < 2 {
475            return;
476        }
477        let mut start = self.count / 2;
478        let mut end = self.count;
479        while end > 1 {
480            if start > 0 {
481                start -= 1;
482            } else {
483                end -= 1;
484                self.swap(end, 0);
485            }
486            let mut root = start;
487            let mut child = 2 * root + 1;
488            while child < end {
489                if child + 1 < end && compare(&self[child], &self[child + 1]) == Ordering::Less {
490                    child += 1;
491                }
492                if compare(&self[root], &self[child]) == Ordering::Less {
493                    self.swap(root, child);
494                    root = child;
495                    child = 2 * root + 1;
496                } else {
497                    break;
498                }
499            }
500        }
501    }
502
503    /// Removes all but the first of consecutive elements in the array
504    /// satisfying a given equality relation.
505    ///
506    /// The `same_bucket` function is passed references to two elements from the
507    /// array and must determine if the elements compare equal. The elements are
508    /// passed in reverse order from their order in the array, so if
509    /// `same_bucket(a, b)` returns `true`, `a` is removed.
510    ///
511    /// If the array is sorted, this removes all duplicates.
512    pub fn dedup_by<F>(&mut self, mut same_bucket: F)
513    where
514        F: FnMut(&T, &T) -> bool,
515    {
516        let len = self.len();
517        if len <= 1 {
518            return;
519        }
520
521        // Check if any duplicates exist to avoid allocating, copying, and
522        // deallocating memory if nothing needs to be removed.
523        let mut first_duplicate_idx: usize = 1;
524        while first_duplicate_idx != len {
525            let found_duplicate = {
526                let prev = self.raw_get(first_duplicate_idx - 1);
527                let current = self.raw_get(first_duplicate_idx);
528                same_bucket(current, prev)
529            };
530            if found_duplicate {
531                break;
532            }
533            first_duplicate_idx += 1;
534        }
535        if first_duplicate_idx == len {
536            return;
537        }
538
539        // duplicates exist, build a new array of only unique values; steal the
540        // old index and sizes, then clear the rest of the properties in order
541        // to start over
542        let index = std::mem::take(&mut self.index);
543        let old_l = self.l;
544        let mut remaining = self.count - 1;
545        self.count = 0;
546        self.clear();
547        let layout = Layout::array::<T>(old_l).expect("unexpected overflow");
548
549        // read the first value (we know there are at least two) to get the
550        // process started
551        let mut prev = unsafe { index[0].read() };
552        let mut slot = 1;
553        for buffer in index.into_iter() {
554            while slot < old_l {
555                let current = unsafe { buffer.add(slot).read() };
556                if same_bucket(&current, &prev) {
557                    drop(current);
558                } else {
559                    self.push(prev);
560                    prev = current;
561                }
562                remaining -= 1;
563                if remaining == 0 {
564                    break;
565                }
566                slot += 1;
567            }
568            unsafe {
569                dealloc(buffer as *mut u8, layout);
570            }
571            slot = 0;
572        }
573        // the last element always gets saved
574        self.push(prev);
575    }
576
577    /// Moves all the elements of `other` into `self`, leaving `other` empty.
578    pub fn append(&mut self, other: &mut Self) {
579        let index = std::mem::take(&mut other.index);
580        let mut remaining = other.count;
581        // prevent other from performing any dropping
582        other.count = 0;
583        let layout = Layout::array::<T>(other.l).expect("unexpected overflow");
584        for buffer in index.into_iter() {
585            for slot in 0..other.l {
586                let value = unsafe { buffer.add(slot).read() };
587                self.push(value);
588                remaining -= 1;
589                if remaining == 0 {
590                    break;
591                }
592            }
593            unsafe {
594                dealloc(buffer as *mut u8, layout);
595            }
596        }
597    }
598
599    /// Splits the collection into two at the given index.
600    ///
601    /// Returns a newly allocated array containing the elements in the range
602    /// `[at, len)`. After the call, the original array will be left containing
603    /// the elements `[0, at)`.
604    ///
605    /// # Panics
606    ///
607    /// Panics if `at > len`.
608    ///
609    /// # Time complexity
610    ///
611    /// O(N)
612    pub fn split_off(&mut self, at: usize) -> Self {
613        if at >= self.count {
614            panic!("index out of bounds: {at}");
615        }
616        // Unlike Vec, cannot simply cut the array into two parts, the structure
617        // is built around the number of elements in the array, and that changes
618        // no matter what the value of `at` might be.
619        //
620        // As such, pop elements from self and push onto other, maintaining the
621        // correct structure of both arrays, then reverse the elements in the
622        // other array to correct the order.
623        let mut other = Self::new();
624        while self.count > at {
625            other.push(self.raw_pop());
626        }
627        let mut low = 0;
628        let mut high = other.count - 1;
629        while low < high {
630            unsafe {
631                let lp = other.index[low >> other.k].add(low & other.k_mask);
632                let value = lp.read();
633                let hp = other.index[high >> other.k].add(high & other.k_mask);
634                std::ptr::copy(hp, lp, 1);
635                hp.write(value);
636            }
637            low += 1;
638            high -= 1;
639        }
640        other
641    }
642
643    /// Shortens the array, keeping the first `len` elements and dropping the
644    /// rest.
645    ///
646    /// If `len` is greater or equal to the array's current length, this has no
647    /// effect.
648    ///
649    /// # Time complexity
650    ///
651    /// O(N)
652    pub fn truncate(&mut self, len: usize) {
653        while self.count > len {
654            self.raw_pop();
655            // intentionally dropping the value
656        }
657    }
658}
659
660impl<T> Default for HashedArrayTree<T> {
661    fn default() -> Self {
662        Self::new()
663    }
664}
665
666impl<T> fmt::Display for HashedArrayTree<T> {
667    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
668        write!(
669            f,
670            "HashedArrayTree(k: {}, count: {}, dope: {})",
671            self.k,
672            self.count,
673            self.index.len(),
674        )
675    }
676}
677
678impl<T> Index<usize> for HashedArrayTree<T> {
679    type Output = T;
680
681    fn index(&self, index: usize) -> &Self::Output {
682        let Some(item) = self.get(index) else {
683            panic!("index out of bounds: {}", index);
684        };
685        item
686    }
687}
688
689impl<T> IndexMut<usize> for HashedArrayTree<T> {
690    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
691        let Some(item) = self.get_mut(index) else {
692            panic!("index out of bounds: {}", index);
693        };
694        item
695    }
696}
697
698impl<T> Drop for HashedArrayTree<T> {
699    fn drop(&mut self) {
700        self.clear();
701    }
702}
703
704impl<T: Clone> Clone for HashedArrayTree<T> {
705    fn clone(&self) -> Self {
706        let mut result = HashedArrayTree::<T>::new();
707        for value in self.iter() {
708            result.push(value.clone());
709        }
710        result
711    }
712}
713
714unsafe impl<T: Send> Send for HashedArrayTree<T> {}
715
716impl<A> FromIterator<A> for HashedArrayTree<A> {
717    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
718        let mut arr: HashedArrayTree<A> = HashedArrayTree::new();
719        for value in iter {
720            arr.push(value)
721        }
722        arr
723    }
724}
725
726/// Immutable hashed array tree iterator.
727pub struct ArrayIter<'a, T> {
728    array: &'a HashedArrayTree<T>,
729    index: usize,
730    count: usize,
731}
732
733impl<'a, T> Iterator for ArrayIter<'a, T> {
734    type Item = &'a T;
735
736    fn next(&mut self) -> Option<Self::Item> {
737        if self.index < self.count {
738            let value = self.array.get(self.index);
739            self.index += 1;
740            value
741        } else {
742            None
743        }
744    }
745
746    fn size_hint(&self) -> (usize, Option<usize>) {
747        let remaining = self.count - self.index;
748        (remaining, Some(remaining))
749    }
750}
751
752impl<'a, T> ExactSizeIterator for ArrayIter<'a, T> {}
753
754/// Mutable hashed array tree iterator.
755pub struct ArrayIterMut<'a, T> {
756    dope: *mut *mut T, // pointer into the dope vector's backing array
757    index: usize,
758    count: usize,
759    k: usize,
760    k_mask: usize,
761    _marker: std::marker::PhantomData<&'a mut T>,
762}
763
764impl<'a, T> Iterator for ArrayIterMut<'a, T> {
765    type Item = &'a mut T;
766
767    fn next(&mut self) -> Option<Self::Item> {
768        if self.index < self.count {
769            let block = self.index >> self.k;
770            let slot = self.index & self.k_mask;
771            self.index += 1;
772            // SAFETY: `dope` points into the HAT's index vec, which is valid
773            // for `'a`. Each successive call increments `self.index`, so no two
774            // live references ever alias the same slot.
775            unsafe {
776                let block_ptr = *self.dope.add(block);
777                Some(&mut *block_ptr.add(slot))
778            }
779        } else {
780            None
781        }
782    }
783
784    fn size_hint(&self) -> (usize, Option<usize>) {
785        let remaining = self.count - self.index;
786        (remaining, Some(remaining))
787    }
788}
789
790impl<'a, T> ExactSizeIterator for ArrayIterMut<'a, T> {}
791
792/// An iterator that moves out of a hashed array tree.
793pub struct ArrayIntoIter<T> {
794    index: usize,
795    k: usize,
796    k_mask: usize,
797    count: usize,
798    dope: Vec<*mut T>,
799}
800
801impl<T> Iterator for ArrayIntoIter<T> {
802    type Item = T;
803
804    fn next(&mut self) -> Option<Self::Item> {
805        if self.index < self.count {
806            let block = self.index >> self.k;
807            let slot = self.index & self.k_mask;
808            self.index += 1;
809            unsafe { Some((self.dope[block].add(slot)).read()) }
810        } else {
811            None
812        }
813    }
814
815    fn size_hint(&self) -> (usize, Option<usize>) {
816        let remaining = self.count - self.index;
817        (remaining, Some(remaining))
818    }
819}
820
821impl<T> IntoIterator for HashedArrayTree<T> {
822    type Item = T;
823    type IntoIter = ArrayIntoIter<Self::Item>;
824
825    fn into_iter(self) -> Self::IntoIter {
826        let mut me = std::mem::ManuallyDrop::new(self);
827        let dope = std::mem::take(&mut me.index);
828        ArrayIntoIter {
829            index: 0,
830            count: me.count,
831            k: me.k,
832            k_mask: me.k_mask,
833            dope,
834        }
835    }
836}
837
838impl<T> ExactSizeIterator for ArrayIntoIter<T> {}
839
840impl<T> Drop for ArrayIntoIter<T> {
841    fn drop(&mut self) {
842        use std::ptr::{drop_in_place, slice_from_raw_parts_mut};
843        let block_len = 1 << self.k;
844
845        if self.count > 0 && std::mem::needs_drop::<T>() {
846            // if completely exhausted, the first block/slot will be past the
847            // end of the array and thus skip all drops below
848            let first_block = self.index >> self.k;
849            let first_slot = self.index & self.k_mask;
850            let last_block = (self.count - 1) >> self.k;
851            let last_slot = (self.count - 1) & self.k_mask;
852            if first_block == last_block {
853                // special-case, remaining values are in only one leaf
854                if first_slot <= last_slot {
855                    unsafe {
856                        // last_slot is pointing at the last element, need to
857                        // add one to include it in the slice
858                        drop_in_place(slice_from_raw_parts_mut(
859                            self.dope[first_block].add(first_slot),
860                            last_slot - first_slot + 1,
861                        ));
862                    }
863                }
864            } else if first_block < last_block {
865                // drop the remaining values in the first leaf
866                if block_len < self.count {
867                    unsafe {
868                        drop_in_place(slice_from_raw_parts_mut(
869                            self.dope[first_block].add(first_slot),
870                            block_len - first_slot,
871                        ));
872                    }
873                }
874
875                // drop the values in the last leaf
876                unsafe {
877                    drop_in_place(slice_from_raw_parts_mut(
878                        self.dope[last_block],
879                        last_slot + 1,
880                    ));
881                }
882
883                // drop the values in all of the other leaves
884                for block in first_block + 1..last_block {
885                    unsafe {
886                        drop_in_place(slice_from_raw_parts_mut(self.dope[block], block_len));
887                    }
888                }
889            }
890        }
891
892        // deallocate all of the leaves
893        for block in 0..self.dope.len() {
894            let layout = Layout::array::<T>(block_len).expect("unexpected overflow");
895            unsafe {
896                dealloc(self.dope[block] as *mut u8, layout);
897            }
898        }
899    }
900}
901
902/// Creates a [`HashedArrayTree`] containing the arguments.
903///
904/// `hat!` allows `HashedArrayTree`s to be defined with the same syntax as array
905/// expressions, much like the `vec!` mocro from the standard library.
906#[macro_export]
907macro_rules! hat {
908    () => {
909        HashedArrayTree::new()
910    };
911    // Takes a comma-separated list of expressions
912    ( $($item:expr),* $(,)? ) => {
913        {
914            let mut result = HashedArrayTree::new();
915            $(
916                result.push($item);
917            )*
918            result
919        }
920    };
921}
922
923#[cfg(test)]
924mod tests {
925    use super::*;
926
927    #[test]
928    fn test_hat_macro() {
929        let sut: HashedArrayTree<usize> = hat![];
930        assert_eq!(sut.len(), 0);
931        assert_eq!(sut.capacity(), 0);
932
933        let sut: HashedArrayTree<usize> = hat![1];
934        assert_eq!(sut.len(), 1);
935        assert_eq!(sut.capacity(), 4);
936
937        let sut = hat![1, 2, 3, 4, 5, 6, 7, 8, 9,];
938        assert_eq!(sut.len(), 9);
939        assert_eq!(sut.capacity(), 12);
940        assert_eq!(sut[0], 1);
941        assert_eq!(sut[1], 2);
942        assert_eq!(sut[2], 3);
943        assert_eq!(sut[3], 4);
944        assert_eq!(sut[4], 5);
945        assert_eq!(sut[5], 6);
946        assert_eq!(sut[6], 7);
947        assert_eq!(sut[7], 8);
948        assert_eq!(sut[8], 9);
949    }
950
951    #[test]
952    fn test_empty() {
953        let sut = HashedArrayTree::<usize>::new();
954        assert!(sut.get(0).is_none());
955    }
956
957    #[test]
958    #[should_panic(expected = "index out of bounds:")]
959    fn test_index_out_of_bounds() {
960        let mut sut: HashedArrayTree<i32> = HashedArrayTree::new();
961        sut.push(10);
962        sut.push(20);
963        let _ = sut[2];
964    }
965
966    #[test]
967    #[should_panic(expected = "index out of bounds:")]
968    fn test_index_mut_out_of_bounds() {
969        let mut sut: HashedArrayTree<i32> = HashedArrayTree::new();
970        sut.push(10);
971        sut.push(20);
972        sut[2] = 30;
973    }
974
975    #[test]
976    fn test_push_no_expand() {
977        // push few enough elements to avoid an expansion
978        let mut sut = HashedArrayTree::<usize>::new();
979        for value in 0..13 {
980            sut.push(value);
981        }
982        assert_eq!(sut.len(), 13);
983        assert_eq!(sut.capacity(), 16);
984        for value in 0..13 {
985            assert_eq!(sut[value], value);
986        }
987        // pop enough to cause the last leaf to be freed
988        sut.pop();
989        assert_eq!(sut.len(), 12);
990        assert_eq!(sut.capacity(), 12);
991    }
992
993    #[test]
994    fn test_push_with_expand() {
995        // push few enough elements to cause an expansion
996        let mut sut = HashedArrayTree::<usize>::new();
997        for value in 0..64 {
998            sut.push(value);
999        }
1000        assert_eq!(sut.len(), 64);
1001        assert_eq!(sut.capacity(), 64);
1002        for value in 0..64 {
1003            assert_eq!(sut[value], value);
1004        }
1005    }
1006
1007    #[test]
1008    fn test_expand_and_compress() {
1009        // add enough to cause multiple expansions
1010        let mut sut = HashedArrayTree::<usize>::new();
1011        for value in 0..1024 {
1012            sut.push(value);
1013        }
1014        assert_eq!(sut.len(), 1024);
1015        assert_eq!(sut.capacity(), 1024);
1016        // remove enough to cause multiple compressions
1017        for _ in 0..960 {
1018            sut.pop();
1019        }
1020        // ensure the correct elements remain
1021        assert_eq!(sut.len(), 64);
1022        assert_eq!(sut.capacity(), 64);
1023        for value in 0..64 {
1024            assert_eq!(sut[value], value);
1025        }
1026    }
1027
1028    #[test]
1029    fn test_push_get_get_mut() {
1030        let mut sut = HashedArrayTree::<usize>::new();
1031        for value in 0..12 {
1032            sut.push(value);
1033        }
1034        assert_eq!(sut.get(2), Some(&2));
1035        if let Some(value) = sut.get_mut(1) {
1036            *value = 11;
1037        } else {
1038            panic!("get_mut() returned None")
1039        }
1040        assert_eq!(sut[0], 0);
1041        assert_eq!(sut[1], 11);
1042        assert_eq!(sut[2], 2);
1043    }
1044
1045    #[test]
1046    fn test_push_within_capacity() {
1047        // empty array has no allocated space
1048        let mut sut = HashedArrayTree::<u32>::new();
1049        assert_eq!(sut.push_within_capacity(101), Err(101));
1050        // will have 4 slots after a single allocation
1051        sut.push(1);
1052        sut.push(2);
1053        assert_eq!(sut.push_within_capacity(3), Ok(()));
1054        assert_eq!(sut.push_within_capacity(4), Ok(()));
1055        assert_eq!(sut.push_within_capacity(5), Err(5));
1056    }
1057
1058    #[test]
1059    fn test_pop_small() {
1060        let mut sut = HashedArrayTree::<usize>::new();
1061        assert!(sut.is_empty());
1062        assert_eq!(sut.len(), 0);
1063        for value in 0..15 {
1064            sut.push(value);
1065        }
1066        assert!(!sut.is_empty());
1067        assert_eq!(sut.len(), 15);
1068        for value in (0..15).rev() {
1069            assert_eq!(sut.pop(), Some(value));
1070        }
1071        assert!(sut.is_empty());
1072        assert_eq!(sut.len(), 0);
1073        assert_eq!(sut.capacity(), 0);
1074    }
1075
1076    #[test]
1077    fn test_pop_if() {
1078        let mut sut = HashedArrayTree::<u32>::new();
1079        assert!(sut.pop_if(|_| panic!("should not be called")).is_none());
1080        for value in 0..10 {
1081            sut.push(value);
1082        }
1083        assert!(sut.pop_if(|_| false).is_none());
1084        let maybe = sut.pop_if(|v| *v == 9);
1085        assert_eq!(maybe.unwrap(), 9);
1086        assert!(sut.pop_if(|v| *v == 9).is_none());
1087    }
1088
1089    #[test]
1090    fn test_clear_and_reuse_ints() {
1091        let mut sut: HashedArrayTree<i32> = HashedArrayTree::new();
1092        for value in 0..512 {
1093            sut.push(value);
1094        }
1095        assert_eq!(sut.len(), 512);
1096        sut.clear();
1097        assert_eq!(sut.len(), 0);
1098        for value in 0..512 {
1099            sut.push(value);
1100        }
1101        for idx in 0..512 {
1102            let maybe = sut.get(idx);
1103            assert!(maybe.is_some(), "{idx} is none");
1104            let actual = maybe.unwrap();
1105            assert_eq!(idx, *actual as usize);
1106        }
1107    }
1108
1109    #[test]
1110    fn test_clear_and_reuse_strings() {
1111        let mut sut: HashedArrayTree<String> = HashedArrayTree::new();
1112        for _ in 0..512 {
1113            let value = ulid::Ulid::new().to_string();
1114            sut.push(value);
1115        }
1116        assert_eq!(sut.len(), 512);
1117        sut.clear();
1118        assert_eq!(sut.len(), 0);
1119        for _ in 0..512 {
1120            let value = ulid::Ulid::new().to_string();
1121            sut.push(value);
1122        }
1123        assert_eq!(sut.len(), 512);
1124        // implicitly drop()
1125    }
1126
1127    #[test]
1128    fn test_clone_ints() {
1129        let mut sut = HashedArrayTree::<usize>::new();
1130        for value in 0..512 {
1131            sut.push(value);
1132        }
1133        let cloned = sut.clone();
1134        let ai = sut.iter();
1135        let bi = cloned.iter();
1136        for (a, b) in ai.zip(bi) {
1137            assert_eq!(a, b);
1138        }
1139    }
1140
1141    #[test]
1142    fn test_clone_strings() {
1143        let mut sut = HashedArrayTree::<String>::new();
1144        for _ in 0..64 {
1145            let value = ulid::Ulid::new().to_string();
1146            sut.push(value);
1147        }
1148        let cloned = sut.clone();
1149        let ai = sut.iter();
1150        let bi = cloned.iter();
1151        for (a, b) in ai.zip(bi) {
1152            assert_eq!(a, b);
1153        }
1154    }
1155
1156    #[test]
1157    fn test_swap() {
1158        let mut sut = HashedArrayTree::<usize>::new();
1159        sut.push(1);
1160        sut.push(2);
1161        sut.push(3);
1162        sut.push(4);
1163        sut.swap(1, 3);
1164        assert_eq!(sut[0], 1);
1165        assert_eq!(sut[1], 4);
1166        assert_eq!(sut[2], 3);
1167        assert_eq!(sut[3], 2);
1168    }
1169
1170    #[test]
1171    #[should_panic(expected = "swap a (is 1) should be < len (is 1)")]
1172    fn test_swap_panic_a() {
1173        let mut sut = HashedArrayTree::<usize>::new();
1174        sut.push(1);
1175        sut.swap(1, 2);
1176    }
1177
1178    #[test]
1179    #[should_panic(expected = "swap b (is 1) should be < len (is 1)")]
1180    fn test_swap_panic_b() {
1181        let mut sut = HashedArrayTree::<usize>::new();
1182        sut.push(1);
1183        sut.swap(0, 1);
1184    }
1185
1186    #[test]
1187    fn test_sort_unstable_by_ints() {
1188        let mut sut = HashedArrayTree::<usize>::new();
1189        sut.push(10);
1190        sut.push(1);
1191        sut.push(100);
1192        sut.push(20);
1193        sut.push(2);
1194        sut.push(99);
1195        sut.push(88);
1196        sut.push(77);
1197        sut.push(66);
1198        sut.sort_unstable_by(|a, b| a.cmp(b));
1199        assert_eq!(sut[0], 1);
1200        assert_eq!(sut[1], 2);
1201        assert_eq!(sut[2], 10);
1202        assert_eq!(sut[3], 20);
1203        assert_eq!(sut[4], 66);
1204        assert_eq!(sut[5], 77);
1205        assert_eq!(sut[6], 88);
1206        assert_eq!(sut[7], 99);
1207        assert_eq!(sut[8], 100);
1208    }
1209
1210    #[test]
1211    fn test_sort_unstable_by_strings() {
1212        let mut sut = HashedArrayTree::<String>::new();
1213        sut.push("cat".into());
1214        sut.push("ape".into());
1215        sut.push("zebra".into());
1216        sut.push("dog".into());
1217        sut.push("bird".into());
1218        sut.push("tapir".into());
1219        sut.push("monkey".into());
1220        sut.push("giraffe".into());
1221        sut.push("frog".into());
1222        sut.sort_unstable_by(|a, b| a.cmp(b));
1223        assert_eq!(sut[0], "ape");
1224        assert_eq!(sut[1], "bird");
1225        assert_eq!(sut[2], "cat");
1226        assert_eq!(sut[3], "dog");
1227        assert_eq!(sut[4], "frog");
1228        assert_eq!(sut[5], "giraffe");
1229        assert_eq!(sut[6], "monkey");
1230        assert_eq!(sut[7], "tapir");
1231        assert_eq!(sut[8], "zebra");
1232    }
1233
1234    #[test]
1235    fn test_append() {
1236        let odds = ["one", "three", "five", "seven", "nine"];
1237        let mut sut = HashedArrayTree::<String>::new();
1238        for item in odds {
1239            sut.push(item.to_owned());
1240        }
1241        let evens = ["two", "four", "six", "eight", "ten"];
1242        let mut other = HashedArrayTree::<String>::new();
1243        for item in evens {
1244            other.push(item.to_owned());
1245        }
1246        sut.append(&mut other);
1247        assert_eq!(sut.len(), 10);
1248        assert_eq!(sut.capacity(), 12);
1249        assert_eq!(other.len(), 0);
1250        assert_eq!(other.capacity(), 0);
1251        sut.sort_unstable_by(|a, b| a.cmp(b));
1252        assert_eq!(sut[0], "eight");
1253        assert_eq!(sut[1], "five");
1254        assert_eq!(sut[2], "four");
1255        assert_eq!(sut[3], "nine");
1256        assert_eq!(sut[4], "one");
1257        assert_eq!(sut[5], "seven");
1258        assert_eq!(sut[6], "six");
1259        assert_eq!(sut[7], "ten");
1260        assert_eq!(sut[8], "three");
1261        assert_eq!(sut[9], "two");
1262    }
1263
1264    #[test]
1265    fn test_dedup_by_tiny() {
1266        let mut sut = HashedArrayTree::<String>::new();
1267        sut.push("one".into());
1268        sut.dedup_by(|a, b| a == b);
1269        assert_eq!(sut.len(), 1);
1270        assert_eq!(sut[0], "one");
1271    }
1272
1273    #[test]
1274    fn test_dedup_by_2_dupes() {
1275        let mut sut = HashedArrayTree::<String>::new();
1276        sut.push("one".into());
1277        sut.push("one".into());
1278        sut.dedup_by(|a, b| a == b);
1279        assert_eq!(sut.len(), 1);
1280        assert_eq!(sut[0], "one");
1281    }
1282
1283    #[test]
1284    fn test_dedup_by_2_unique() {
1285        let mut sut = HashedArrayTree::<String>::new();
1286        sut.push("one".into());
1287        sut.push("two".into());
1288        sut.dedup_by(|a, b| a == b);
1289        assert_eq!(sut.len(), 2);
1290        assert_eq!(sut[0], "one");
1291        assert_eq!(sut[1], "two");
1292    }
1293
1294    #[test]
1295    fn test_dedup_by_all_unique() {
1296        let inputs = [
1297            "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
1298        ];
1299        let mut sut = HashedArrayTree::<String>::new();
1300        for item in inputs {
1301            sut.push(item.to_owned());
1302        }
1303        sut.dedup_by(|a, b| a == b);
1304        assert_eq!(sut.len(), 9);
1305        for (idx, elem) in sut.into_iter().enumerate() {
1306            assert_eq!(inputs[idx], elem);
1307        }
1308    }
1309
1310    #[test]
1311    fn test_dedup_by_all_dupes() {
1312        let inputs = [
1313            "one", "one", "one", "one", "one", "one", "one", "one", "one", "one",
1314        ];
1315        let mut sut = HashedArrayTree::<String>::new();
1316        for item in inputs {
1317            sut.push(item.to_owned());
1318        }
1319        assert_eq!(sut.len(), 10);
1320        sut.dedup_by(|a, b| a == b);
1321        assert_eq!(sut.len(), 1);
1322        assert_eq!(inputs[0], "one");
1323    }
1324
1325    #[test]
1326    fn test_dedup_by_some_dupes_ints() {
1327        let inputs = [1, 2, 2, 3, 2];
1328        let mut sut = HashedArrayTree::<usize>::new();
1329        for item in inputs {
1330            sut.push(item.to_owned());
1331        }
1332        assert_eq!(sut.len(), 5);
1333        sut.dedup_by(|a, b| a == b);
1334        assert_eq!(sut.len(), 4);
1335        assert_eq!(sut[0], 1);
1336        assert_eq!(sut[1], 2);
1337        assert_eq!(sut[2], 3);
1338        assert_eq!(sut[3], 2);
1339    }
1340
1341    #[test]
1342    fn test_dedup_by_some_dupes_strings() {
1343        let inputs = ["foo", "bar", "Bar", "baz", "bar"];
1344        let mut sut = HashedArrayTree::<String>::new();
1345        for item in inputs {
1346            sut.push(item.to_owned());
1347        }
1348        assert_eq!(sut.len(), 5);
1349        sut.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
1350        assert_eq!(sut.len(), 4);
1351        assert_eq!(sut[0], "foo");
1352        assert_eq!(sut[1], "bar");
1353        assert_eq!(sut[2], "baz");
1354        assert_eq!(sut[3], "bar");
1355    }
1356
1357    #[test]
1358    #[should_panic(expected = "index out of bounds: 10")]
1359    fn test_split_off_bounds_panic() {
1360        let mut sut = HashedArrayTree::<usize>::new();
1361        sut.split_off(10);
1362    }
1363
1364    #[test]
1365    fn test_split_off_middle() {
1366        let mut sut = HashedArrayTree::<usize>::new();
1367        for value in 0..16 {
1368            sut.push(value);
1369        }
1370        assert_eq!(sut.len(), 16);
1371        assert_eq!(sut.capacity(), 16);
1372        let other = sut.split_off(8);
1373        assert_eq!(sut.len(), 8);
1374        assert_eq!(sut.capacity(), 8);
1375        for value in 0..8 {
1376            assert_eq!(sut[value], value);
1377        }
1378        assert_eq!(other.len(), 8);
1379        assert_eq!(other.capacity(), 8);
1380        for (index, value) in (8..16).enumerate() {
1381            assert_eq!(other[index], value);
1382        }
1383    }
1384
1385    #[test]
1386    fn test_split_off_almost_start() {
1387        let mut sut = HashedArrayTree::<usize>::new();
1388        for value in 0..16 {
1389            sut.push(value);
1390        }
1391        assert_eq!(sut.len(), 16);
1392        assert_eq!(sut.capacity(), 16);
1393        let other = sut.split_off(1);
1394        assert_eq!(sut.len(), 1);
1395        assert_eq!(sut.capacity(), 4);
1396        for value in 0..1 {
1397            assert_eq!(sut[value], value);
1398        }
1399        assert_eq!(other.len(), 15);
1400        assert_eq!(other.capacity(), 16);
1401        for (index, value) in (1..16).enumerate() {
1402            assert_eq!(other[index], value);
1403        }
1404    }
1405
1406    #[test]
1407    fn test_split_off_almost_end() {
1408        let mut sut = HashedArrayTree::<usize>::new();
1409        for value in 0..16 {
1410            sut.push(value);
1411        }
1412        assert_eq!(sut.len(), 16);
1413        assert_eq!(sut.capacity(), 16);
1414        let other = sut.split_off(15);
1415        assert_eq!(sut.len(), 15);
1416        assert_eq!(sut.capacity(), 16);
1417        for value in 0..15 {
1418            assert_eq!(sut[value], value);
1419        }
1420        assert_eq!(other.len(), 1);
1421        assert_eq!(other.capacity(), 4);
1422        assert_eq!(other[0], 15);
1423    }
1424
1425    #[test]
1426    fn test_split_off_odd_other() {
1427        let mut sut = HashedArrayTree::<usize>::new();
1428        for value in 0..16 {
1429            sut.push(value);
1430        }
1431        assert_eq!(sut.len(), 16);
1432        assert_eq!(sut.capacity(), 16);
1433        let other = sut.split_off(11);
1434        assert_eq!(sut.len(), 11);
1435        assert_eq!(sut.capacity(), 12);
1436        for value in 0..11 {
1437            assert_eq!(sut[value], value);
1438        }
1439        assert_eq!(other.len(), 5);
1440        assert_eq!(other.capacity(), 8);
1441        for (index, value) in (11..16).enumerate() {
1442            assert_eq!(other[index], value);
1443        }
1444    }
1445
1446    #[test]
1447    fn test_truncate_typical() {
1448        let mut sut = hat![1, 2, 3, 4, 5, 6, 7, 8];
1449        assert_eq!(sut.len(), 8);
1450        assert_eq!(sut.capacity(), 8);
1451        sut.truncate(5);
1452        assert_eq!(sut.len(), 5);
1453        assert_eq!(sut.capacity(), 8);
1454        for (index, value) in (1..6).enumerate() {
1455            assert_eq!(sut[index], value);
1456        }
1457    }
1458
1459    #[test]
1460    fn test_truncate_out_of_bounds() {
1461        let mut sut = hat![1, 2, 3, 4, 5,];
1462        assert_eq!(sut.len(), 5);
1463        assert_eq!(sut.capacity(), 8);
1464        sut.truncate(8);
1465        assert_eq!(sut.len(), 5);
1466        assert_eq!(sut.capacity(), 8);
1467        for (index, value) in (1..6).enumerate() {
1468            assert_eq!(sut[index], value);
1469        }
1470    }
1471
1472    #[test]
1473    fn test_truncate_to_empty() {
1474        let mut sut = hat![1, 2, 3, 4, 5,];
1475        assert_eq!(sut.len(), 5);
1476        assert_eq!(sut.capacity(), 8);
1477        sut.truncate(0);
1478        assert_eq!(sut.len(), 0);
1479        assert_eq!(sut.capacity(), 0);
1480    }
1481
1482    #[test]
1483    fn test_from_iterator() {
1484        let mut inputs: Vec<i32> = Vec::new();
1485        for value in 0..10_000 {
1486            inputs.push(value);
1487        }
1488        let sut: HashedArrayTree<i32> = inputs.into_iter().collect();
1489        assert_eq!(sut.len(), 10_000);
1490        for idx in 0..10_000i32 {
1491            let maybe = sut.get(idx as usize);
1492            assert!(maybe.is_some(), "{idx} is none");
1493            let actual = maybe.unwrap();
1494            assert_eq!(idx, *actual);
1495        }
1496    }
1497
1498    #[test]
1499    fn test_iterator() {
1500        let mut sut = HashedArrayTree::<usize>::new();
1501        for value in 0..512 {
1502            sut.push(value);
1503        }
1504        assert_eq!(sut.len(), 512);
1505        for (idx, elem) in sut.iter().enumerate() {
1506            assert_eq!(sut[idx], *elem);
1507        }
1508    }
1509
1510    #[test]
1511    fn test_iter_mut() {
1512        let mut sut = HashedArrayTree::<usize>::new();
1513        for value in 0..512 {
1514            sut.push(value);
1515        }
1516        // double every element through the mutable iterator
1517        for elem in sut.iter_mut() {
1518            *elem *= 2;
1519        }
1520        for idx in 0..512 {
1521            assert_eq!(sut[idx], idx * 2);
1522        }
1523    }
1524
1525    #[test]
1526    fn test_iter_mut_empty() {
1527        let mut sut = HashedArrayTree::<usize>::new();
1528        assert_eq!(sut.iter_mut().count(), 0);
1529    }
1530
1531    #[test]
1532    fn test_into_iterator_edge_case() {
1533        // iterate to the end (of the last data block)
1534        let inputs = [
1535            "one", "two", "three", "four", "five", "six", "seven", "eight",
1536        ];
1537        let mut sut: HashedArrayTree<String> = HashedArrayTree::new();
1538        for item in inputs {
1539            sut.push(item.to_owned());
1540        }
1541        for (idx, elem) in sut.into_iter().enumerate() {
1542            assert_eq!(inputs[idx], elem);
1543        }
1544        // sut.len(); // error: ownership of sut was moved
1545    }
1546
1547    #[test]
1548    fn test_into_iterator_multiple_leaves() {
1549        let inputs = [
1550            "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
1551        ];
1552        let mut sut: HashedArrayTree<String> = HashedArrayTree::new();
1553        for item in inputs {
1554            sut.push(item.to_owned());
1555        }
1556        for (idx, elem) in sut.into_iter().enumerate() {
1557            assert_eq!(inputs[idx], elem);
1558        }
1559        // sut.len(); // error: ownership of sut was moved
1560    }
1561
1562    #[test]
1563    fn test_into_iterator_drop_empty() {
1564        let sut: HashedArrayTree<String> = HashedArrayTree::new();
1565        assert_eq!(sut.into_iter().count(), 0);
1566    }
1567
1568    #[test]
1569    fn test_into_iterator_drop_single_leaf() {
1570        // an array that only requires a single segment and only some need to be
1571        // dropped after partially iterating the values
1572        let inputs = ["one", "two", "three", "four"];
1573        let mut sut: HashedArrayTree<String> = HashedArrayTree::new();
1574        for item in inputs {
1575            sut.push(item.to_owned());
1576        }
1577        for (idx, _) in sut.into_iter().enumerate() {
1578            if idx > 1 {
1579                break;
1580            }
1581        }
1582        // implicitly drop()
1583    }
1584
1585    #[test]
1586    fn test_into_iterator_drop_large() {
1587        // by adding 512 values and iterating less than 32 times, there will be
1588        // values in the first segment and some in the last segment, and two
1589        // segments inbetween that all need to be dropped
1590        let mut sut: HashedArrayTree<String> = HashedArrayTree::new();
1591        for _ in 0..512 {
1592            let value = ulid::Ulid::new().to_string();
1593            sut.push(value);
1594        }
1595        for (idx, _) in sut.into_iter().enumerate() {
1596            if idx >= 28 {
1597                break;
1598            }
1599        }
1600        // implicitly drop()
1601    }
1602
1603    #[test]
1604    fn test_swap_remove_single_segment() {
1605        let mut sut: HashedArrayTree<u32> = HashedArrayTree::new();
1606        sut.push(1);
1607        sut.push(2);
1608        assert_eq!(sut.len(), 2);
1609        let one = sut.swap_remove(0);
1610        assert_eq!(one, 1);
1611        assert_eq!(sut[0], 2);
1612    }
1613
1614    #[test]
1615    fn test_swap_remove_prune_empty() {
1616        let mut sut: HashedArrayTree<u32> = HashedArrayTree::new();
1617        for value in 0..13 {
1618            sut.push(value);
1619        }
1620        assert_eq!(sut.len(), 13);
1621        assert_eq!(sut.capacity(), 16);
1622        let value = sut.swap_remove(8);
1623        assert_eq!(value, 8);
1624        assert_eq!(sut[8], 12);
1625        assert_eq!(sut.len(), 12);
1626        assert_eq!(sut.capacity(), 12);
1627    }
1628
1629    #[test]
1630    fn test_swap_remove_multiple_segments() {
1631        let mut sut: HashedArrayTree<u32> = HashedArrayTree::new();
1632        for value in 0..512 {
1633            sut.push(value);
1634        }
1635        assert_eq!(sut.len(), 512);
1636        let eighty = sut.swap_remove(80);
1637        assert_eq!(eighty, 80);
1638        assert_eq!(sut.pop(), Some(510));
1639        assert_eq!(sut[80], 511);
1640    }
1641
1642    #[test]
1643    #[should_panic(expected = "swap_remove index (is 0) should be < len (is 0)")]
1644    fn test_swap_remove_panic_empty() {
1645        let mut sut: HashedArrayTree<u32> = HashedArrayTree::new();
1646        sut.swap_remove(0);
1647    }
1648
1649    #[test]
1650    #[should_panic(expected = "swap_remove index (is 1) should be < len (is 1)")]
1651    fn test_swap_remove_panic_range_edge() {
1652        let mut sut: HashedArrayTree<u32> = HashedArrayTree::new();
1653        sut.push(1);
1654        sut.swap_remove(1);
1655    }
1656
1657    #[test]
1658    #[should_panic(expected = "swap_remove index (is 2) should be < len (is 1)")]
1659    fn test_swap_remove_panic_range_exceed() {
1660        let mut sut: HashedArrayTree<u32> = HashedArrayTree::new();
1661        sut.push(1);
1662        sut.swap_remove(2);
1663    }
1664
1665    #[test]
1666    fn test_push_get_many_instances_ints() {
1667        // test allocating, filling, and then dropping many instances
1668        for _ in 0..1_000 {
1669            let mut sut: HashedArrayTree<usize> = HashedArrayTree::new();
1670            for value in 0..10_000 {
1671                sut.push(value);
1672            }
1673            assert_eq!(sut.len(), 10_000);
1674        }
1675    }
1676
1677    #[test]
1678    fn test_push_get_many_instances_strings() {
1679        // test allocating, filling, and then dropping many instances
1680        for _ in 0..1_000 {
1681            let mut sut: HashedArrayTree<String> = HashedArrayTree::new();
1682            for _ in 0..1_000 {
1683                let value = ulid::Ulid::new().to_string();
1684                sut.push(value);
1685            }
1686            assert_eq!(sut.len(), 1_000);
1687        }
1688    }
1689}