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