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        }
344    }
345
346    /// Return the number of elements in the array.
347    ///
348    /// # Time complexity
349    ///
350    /// Constant time.
351    pub fn len(&self) -> usize {
352        self.count
353    }
354
355    /// Returns the total number of elements the array can hold without
356    /// reallocating.
357    ///
358    /// # Time complexity
359    ///
360    /// Constant time.
361    pub fn capacity(&self) -> usize {
362        (1 << self.k) * self.index.len()
363    }
364
365    /// Returns true if the array has a length of 0.
366    ///
367    /// # Time complexity
368    ///
369    /// Constant time.
370    pub fn is_empty(&self) -> bool {
371        self.count == 0
372    }
373
374    /// Clears the array, removing all values and deallocating all leaves.
375    ///
376    /// # Time complexity
377    ///
378    /// O(N) if elements are droppable, otherwise O(√N)
379    pub fn clear(&mut self) {
380        use std::ptr::{drop_in_place, slice_from_raw_parts_mut};
381
382        if self.count > 0 && std::mem::needs_drop::<T>() {
383            // find the last leaf that contains values and drop them
384            let last_index = self.count - 1;
385            let last_block = last_index >> self.k;
386            let last_slot = last_index & self.k_mask;
387            unsafe {
388                // last_slot is pointing at the last element, need to add
389                // one to include it in the slice
390                drop_in_place(slice_from_raw_parts_mut(
391                    self.index[last_block],
392                    last_slot + 1,
393                ));
394            }
395
396            // drop the values in all of the preceding leaves
397            for block in 0..last_block {
398                unsafe {
399                    drop_in_place(slice_from_raw_parts_mut(self.index[block], self.l));
400                }
401            }
402        }
403
404        // deallocate all leaves using the index as the source of truth
405        let layout = Layout::array::<T>(self.l).expect("unexpected overflow");
406        for block in 0..self.index.len() {
407            unsafe {
408                dealloc(self.index[block] as *mut u8, layout);
409            }
410        }
411        self.index.clear();
412
413        self.count = 0;
414        self.k = 2;
415        self.k_mask = 3;
416        self.l = 1 << self.k;
417        self.upper_limit = self.l * self.l;
418        self.lower_limit = 0;
419    }
420
421    /// Swap two elements in the array.
422    ///
423    /// # Panics
424    ///
425    /// Panics if either index is out of bounds.
426    pub fn swap(&mut self, a: usize, b: usize) {
427        if a >= self.count {
428            panic!("swap a (is {a}) should be < len (is {})", self.count);
429        }
430        if b >= self.count {
431            panic!("swap b (is {b}) should be < len (is {})", self.count);
432        }
433        // save the value in slot a before overwriting with value from slot b,
434        // then write the saved value to slot b
435        let a_block = a >> self.k;
436        let a_slot = a & self.k_mask;
437        let b_block = b >> self.k;
438        let b_slot = b & self.k_mask;
439        unsafe {
440            let a_ptr = self.index[a_block].add(a_slot);
441            let value = a_ptr.read();
442            let b_ptr = self.index[b_block].add(b_slot);
443            std::ptr::copy(b_ptr, a_ptr, 1);
444            b_ptr.write(value);
445        }
446    }
447
448    /// Sorts the slice in ascending order with a comparison function,
449    /// **without** preserving the initial order of equal elements.
450    ///
451    /// This sort is unstable (i.e., may reorder equal elements), in-place
452    /// (i.e., does not allocate), and *O*(*n* \* log(*n*)) worst-case.
453    ///
454    /// Implements the standard heapsort algorithm.
455    pub fn sort_unstable_by<F>(&mut self, mut compare: F)
456    where
457        F: FnMut(&T, &T) -> Ordering,
458    {
459        if self.count < 2 {
460            return;
461        }
462        let mut start = self.count / 2;
463        let mut end = self.count;
464        while end > 1 {
465            if start > 0 {
466                start -= 1;
467            } else {
468                end -= 1;
469                self.swap(end, 0);
470            }
471            let mut root = start;
472            let mut child = 2 * root + 1;
473            while child < end {
474                if child + 1 < end && compare(&self[child], &self[child + 1]) == Ordering::Less {
475                    child += 1;
476                }
477                if compare(&self[root], &self[child]) == Ordering::Less {
478                    self.swap(root, child);
479                    root = child;
480                    child = 2 * root + 1;
481                } else {
482                    break;
483                }
484            }
485        }
486    }
487
488    /// Removes all but the first of consecutive elements in the array
489    /// satisfying a given equality relation.
490    ///
491    /// The `same_bucket` function is passed references to two elements from the
492    /// array and must determine if the elements compare equal. The elements are
493    /// passed in reverse order from their order in the array, so if
494    /// `same_bucket(a, b)` returns `true`, `a` is removed.
495    ///
496    /// If the array is sorted, this removes all duplicates.
497    pub fn dedup_by<F>(&mut self, mut same_bucket: F)
498    where
499        F: FnMut(&T, &T) -> bool,
500    {
501        let len = self.len();
502        if len <= 1 {
503            return;
504        }
505
506        // Check if any duplicates exist to avoid allocating, copying, and
507        // deallocating memory if nothing needs to be removed.
508        let mut first_duplicate_idx: usize = 1;
509        while first_duplicate_idx != len {
510            let found_duplicate = {
511                let prev = self.raw_get(first_duplicate_idx - 1);
512                let current = self.raw_get(first_duplicate_idx);
513                same_bucket(current, prev)
514            };
515            if found_duplicate {
516                break;
517            }
518            first_duplicate_idx += 1;
519        }
520        if first_duplicate_idx == len {
521            return;
522        }
523
524        // duplicates exist, build a new array of only unique values; steal the
525        // old index and sizes, then clear the rest of the properties in order
526        // to start over
527        let index = std::mem::take(&mut self.index);
528        let old_l = self.l;
529        let mut remaining = self.count - 1;
530        self.count = 0;
531        self.clear();
532        let layout = Layout::array::<T>(old_l).expect("unexpected overflow");
533
534        // read the first value (we know there are at least two) to get the
535        // process started
536        let mut prev = unsafe { index[0].read() };
537        let mut slot = 1;
538        for buffer in index.into_iter() {
539            while slot < old_l {
540                let current = unsafe { buffer.add(slot).read() };
541                if same_bucket(&current, &prev) {
542                    drop(current);
543                } else {
544                    self.push(prev);
545                    prev = current;
546                }
547                remaining -= 1;
548                if remaining == 0 {
549                    break;
550                }
551                slot += 1;
552            }
553            unsafe {
554                dealloc(buffer as *mut u8, layout);
555            }
556            slot = 0;
557        }
558        // the last element always gets saved
559        self.push(prev);
560    }
561
562    /// Moves all the elements of `other` into `self`, leaving `other` empty.
563    pub fn append(&mut self, other: &mut Self) {
564        let index = std::mem::take(&mut other.index);
565        let mut remaining = other.count;
566        // prevent other from performing any dropping
567        other.count = 0;
568        let layout = Layout::array::<T>(other.l).expect("unexpected overflow");
569        for buffer in index.into_iter() {
570            for slot in 0..other.l {
571                let value = unsafe { buffer.add(slot).read() };
572                self.push(value);
573                remaining -= 1;
574                if remaining == 0 {
575                    break;
576                }
577            }
578            unsafe {
579                dealloc(buffer as *mut u8, layout);
580            }
581        }
582    }
583
584    /// Splits the collection into two at the given index.
585    ///
586    /// Returns a newly allocated array containing the elements in the range
587    /// `[at, len)`. After the call, the original array will be left containing
588    /// the elements `[0, at)`.
589    ///
590    /// # Panics
591    ///
592    /// Panics if `at > len`.
593    ///
594    /// # Time complexity
595    ///
596    /// O(N)
597    pub fn split_off(&mut self, at: usize) -> Self {
598        if at >= self.count {
599            panic!("index out of bounds: {at}");
600        }
601        // Unlike Vec, cannot simply cut the array into two parts, the structure
602        // is built around the number of elements in the array, and that changes
603        // no matter what the value of `at` might be.
604        //
605        // As such, pop elements from self and push onto other, maintaining the
606        // correct structure of both arrays, then reverse the elements in the
607        // other array to correct the order.
608        let mut other = Self::new();
609        while self.count > at {
610            other.push(self.raw_pop());
611        }
612        let mut low = 0;
613        let mut high = other.count - 1;
614        while low < high {
615            unsafe {
616                let lp = other.index[low >> other.k].add(low & other.k_mask);
617                let value = lp.read();
618                let hp = other.index[high >> other.k].add(high & other.k_mask);
619                std::ptr::copy(hp, lp, 1);
620                hp.write(value);
621            }
622            low += 1;
623            high -= 1;
624        }
625        other
626    }
627
628    /// Shortens the array, keeping the first `len` elements and dropping the
629    /// rest.
630    ///
631    /// If `len` is greater or equal to the array's current length, this has no
632    /// effect.
633    ///
634    /// # Time complexity
635    ///
636    /// O(N)
637    pub fn truncate(&mut self, len: usize) {
638        while self.count > len {
639            self.raw_pop();
640            // intentionally dropping the value
641        }
642    }
643}
644
645impl<T> Default for HashedArrayTree<T> {
646    fn default() -> Self {
647        Self::new()
648    }
649}
650
651impl<T> fmt::Display for HashedArrayTree<T> {
652    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
653        write!(
654            f,
655            "HashedArrayTree(k: {}, count: {}, dope: {})",
656            self.k,
657            self.count,
658            self.index.len(),
659        )
660    }
661}
662
663impl<T> Index<usize> for HashedArrayTree<T> {
664    type Output = T;
665
666    fn index(&self, index: usize) -> &Self::Output {
667        let Some(item) = self.get(index) else {
668            panic!("index out of bounds: {}", index);
669        };
670        item
671    }
672}
673
674impl<T> IndexMut<usize> for HashedArrayTree<T> {
675    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
676        let Some(item) = self.get_mut(index) else {
677            panic!("index out of bounds: {}", index);
678        };
679        item
680    }
681}
682
683impl<T> Drop for HashedArrayTree<T> {
684    fn drop(&mut self) {
685        self.clear();
686    }
687}
688
689impl<T: Clone> Clone for HashedArrayTree<T> {
690    fn clone(&self) -> Self {
691        let mut result = HashedArrayTree::<T>::new();
692        for value in self.iter() {
693            result.push(value.clone());
694        }
695        result
696    }
697}
698
699unsafe impl<T: Send> Send for HashedArrayTree<T> {}
700
701impl<A> FromIterator<A> for HashedArrayTree<A> {
702    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
703        let mut arr: HashedArrayTree<A> = HashedArrayTree::new();
704        for value in iter {
705            arr.push(value)
706        }
707        arr
708    }
709}
710
711/// Immutable hashed array tree iterator.
712pub struct ArrayIter<'a, T> {
713    array: &'a HashedArrayTree<T>,
714    index: usize,
715}
716
717impl<'a, T> Iterator for ArrayIter<'a, T> {
718    type Item = &'a T;
719
720    fn next(&mut self) -> Option<Self::Item> {
721        let value = self.array.get(self.index);
722        self.index += 1;
723        value
724    }
725}
726
727/// An iterator that moves out of a hashed array tree.
728pub struct ArrayIntoIter<T> {
729    index: usize,
730    k: usize,
731    k_mask: usize,
732    count: usize,
733    dope: Vec<*mut T>,
734}
735
736impl<T> Iterator for ArrayIntoIter<T> {
737    type Item = T;
738
739    fn next(&mut self) -> Option<Self::Item> {
740        if self.index < self.count {
741            let block = self.index >> self.k;
742            let slot = self.index & self.k_mask;
743            self.index += 1;
744            unsafe { Some((self.dope[block].add(slot)).read()) }
745        } else {
746            None
747        }
748    }
749}
750
751impl<T> IntoIterator for HashedArrayTree<T> {
752    type Item = T;
753    type IntoIter = ArrayIntoIter<Self::Item>;
754
755    fn into_iter(self) -> Self::IntoIter {
756        let mut me = std::mem::ManuallyDrop::new(self);
757        let dope = std::mem::take(&mut me.index);
758        ArrayIntoIter {
759            index: 0,
760            count: me.count,
761            k: me.k,
762            k_mask: me.k_mask,
763            dope,
764        }
765    }
766}
767
768impl<T> Drop for ArrayIntoIter<T> {
769    fn drop(&mut self) {
770        use std::ptr::{drop_in_place, slice_from_raw_parts_mut};
771        let block_len = 1 << self.k;
772
773        if self.count > 0 && std::mem::needs_drop::<T>() {
774            // if completely exhausted, the first block/slot will be past the
775            // end of the array and thus skip all drops below
776            let first_block = self.index >> self.k;
777            let first_slot = self.index & self.k_mask;
778            let last_block = (self.count - 1) >> self.k;
779            let last_slot = (self.count - 1) & self.k_mask;
780            if first_block == last_block {
781                // special-case, remaining values are in only one leaf
782                if first_slot <= last_slot {
783                    unsafe {
784                        // last_slot is pointing at the last element, need to
785                        // add one to include it in the slice
786                        drop_in_place(slice_from_raw_parts_mut(
787                            self.dope[first_block].add(first_slot),
788                            last_slot - first_slot + 1,
789                        ));
790                    }
791                }
792            } else if first_block < last_block {
793                // drop the remaining values in the first leaf
794                if block_len < self.count {
795                    unsafe {
796                        drop_in_place(slice_from_raw_parts_mut(
797                            self.dope[first_block].add(first_slot),
798                            block_len - first_slot,
799                        ));
800                    }
801                }
802
803                // drop the values in the last leaf
804                unsafe {
805                    drop_in_place(slice_from_raw_parts_mut(
806                        self.dope[last_block],
807                        last_slot + 1,
808                    ));
809                }
810
811                // drop the values in all of the other leaves
812                for block in first_block + 1..last_block {
813                    unsafe {
814                        drop_in_place(slice_from_raw_parts_mut(self.dope[block], block_len));
815                    }
816                }
817            }
818        }
819
820        // deallocate all of the leaves
821        for block in 0..self.dope.len() {
822            let layout = Layout::array::<T>(block_len).expect("unexpected overflow");
823            unsafe {
824                dealloc(self.dope[block] as *mut u8, layout);
825            }
826        }
827    }
828}
829
830/// Creates a [`HashedArrayTree`] containing the arguments.
831///
832/// `hat!` allows `HashedArrayTree`s to be defined with the same syntax as array
833/// expressions, much like the `vec!` mocro from the standard library.
834#[macro_export]
835macro_rules! hat {
836    () => {
837        HashedArrayTree::new()
838    };
839    // Takes a comma-separated list of expressions
840    ( $($item:expr),* $(,)? ) => {
841        {
842            let mut result = HashedArrayTree::new();
843            $(
844                result.push($item);
845            )*
846            result
847        }
848    };
849}
850
851#[cfg(test)]
852mod tests {
853    use super::*;
854
855    #[test]
856    fn test_hat_macro() {
857        let sut: HashedArrayTree<usize> = hat![];
858        assert_eq!(sut.len(), 0);
859        assert_eq!(sut.capacity(), 0);
860
861        let sut: HashedArrayTree<usize> = hat![1];
862        assert_eq!(sut.len(), 1);
863        assert_eq!(sut.capacity(), 4);
864
865        let sut = hat![1, 2, 3, 4, 5, 6, 7, 8, 9,];
866        assert_eq!(sut.len(), 9);
867        assert_eq!(sut.capacity(), 12);
868        assert_eq!(sut[0], 1);
869        assert_eq!(sut[1], 2);
870        assert_eq!(sut[2], 3);
871        assert_eq!(sut[3], 4);
872        assert_eq!(sut[4], 5);
873        assert_eq!(sut[5], 6);
874        assert_eq!(sut[6], 7);
875        assert_eq!(sut[7], 8);
876        assert_eq!(sut[8], 9);
877    }
878
879    #[test]
880    fn test_empty() {
881        let sut = HashedArrayTree::<usize>::new();
882        assert!(sut.get(0).is_none());
883    }
884
885    #[test]
886    #[should_panic(expected = "index out of bounds:")]
887    fn test_index_out_of_bounds() {
888        let mut sut: HashedArrayTree<i32> = HashedArrayTree::new();
889        sut.push(10);
890        sut.push(20);
891        let _ = sut[2];
892    }
893
894    #[test]
895    #[should_panic(expected = "index out of bounds:")]
896    fn test_index_mut_out_of_bounds() {
897        let mut sut: HashedArrayTree<i32> = HashedArrayTree::new();
898        sut.push(10);
899        sut.push(20);
900        sut[2] = 30;
901    }
902
903    #[test]
904    fn test_push_no_expand() {
905        // push few enough elements to avoid an expansion
906        let mut sut = HashedArrayTree::<usize>::new();
907        for value in 0..13 {
908            sut.push(value);
909        }
910        assert_eq!(sut.len(), 13);
911        assert_eq!(sut.capacity(), 16);
912        for value in 0..13 {
913            assert_eq!(sut[value], value);
914        }
915        // pop enough to cause the last leaf to be freed
916        sut.pop();
917        assert_eq!(sut.len(), 12);
918        assert_eq!(sut.capacity(), 12);
919    }
920
921    #[test]
922    fn test_push_with_expand() {
923        // push few enough elements to cause an expansion
924        let mut sut = HashedArrayTree::<usize>::new();
925        for value in 0..64 {
926            sut.push(value);
927        }
928        assert_eq!(sut.len(), 64);
929        assert_eq!(sut.capacity(), 64);
930        for value in 0..64 {
931            assert_eq!(sut[value], value);
932        }
933    }
934
935    #[test]
936    fn test_expand_and_compress() {
937        // add enough to cause multiple expansions
938        let mut sut = HashedArrayTree::<usize>::new();
939        for value in 0..1024 {
940            sut.push(value);
941        }
942        assert_eq!(sut.len(), 1024);
943        assert_eq!(sut.capacity(), 1024);
944        // remove enough to cause multiple compressions
945        for _ in 0..960 {
946            sut.pop();
947        }
948        // ensure the correct elements remain
949        assert_eq!(sut.len(), 64);
950        assert_eq!(sut.capacity(), 64);
951        for value in 0..64 {
952            assert_eq!(sut[value], value);
953        }
954    }
955
956    #[test]
957    fn test_push_get_get_mut() {
958        let mut sut = HashedArrayTree::<usize>::new();
959        for value in 0..12 {
960            sut.push(value);
961        }
962        assert_eq!(sut.get(2), Some(&2));
963        if let Some(value) = sut.get_mut(1) {
964            *value = 11;
965        } else {
966            panic!("get_mut() returned None")
967        }
968        assert_eq!(sut[0], 0);
969        assert_eq!(sut[1], 11);
970        assert_eq!(sut[2], 2);
971    }
972
973    #[test]
974    fn test_push_within_capacity() {
975        // empty array has no allocated space
976        let mut sut = HashedArrayTree::<u32>::new();
977        assert_eq!(sut.push_within_capacity(101), Err(101));
978        // will have 4 slots after a single allocation
979        sut.push(1);
980        sut.push(2);
981        assert_eq!(sut.push_within_capacity(3), Ok(()));
982        assert_eq!(sut.push_within_capacity(4), Ok(()));
983        assert_eq!(sut.push_within_capacity(5), Err(5));
984    }
985
986    #[test]
987    fn test_pop_small() {
988        let mut sut = HashedArrayTree::<usize>::new();
989        assert!(sut.is_empty());
990        assert_eq!(sut.len(), 0);
991        for value in 0..15 {
992            sut.push(value);
993        }
994        assert!(!sut.is_empty());
995        assert_eq!(sut.len(), 15);
996        for value in (0..15).rev() {
997            assert_eq!(sut.pop(), Some(value));
998        }
999        assert!(sut.is_empty());
1000        assert_eq!(sut.len(), 0);
1001        assert_eq!(sut.capacity(), 0);
1002    }
1003
1004    #[test]
1005    fn test_pop_if() {
1006        let mut sut = HashedArrayTree::<u32>::new();
1007        assert!(sut.pop_if(|_| panic!("should not be called")).is_none());
1008        for value in 0..10 {
1009            sut.push(value);
1010        }
1011        assert!(sut.pop_if(|_| false).is_none());
1012        let maybe = sut.pop_if(|v| *v == 9);
1013        assert_eq!(maybe.unwrap(), 9);
1014        assert!(sut.pop_if(|v| *v == 9).is_none());
1015    }
1016
1017    #[test]
1018    fn test_clear_and_reuse_ints() {
1019        let mut sut: HashedArrayTree<i32> = HashedArrayTree::new();
1020        for value in 0..512 {
1021            sut.push(value);
1022        }
1023        assert_eq!(sut.len(), 512);
1024        sut.clear();
1025        assert_eq!(sut.len(), 0);
1026        for value in 0..512 {
1027            sut.push(value);
1028        }
1029        for idx in 0..512 {
1030            let maybe = sut.get(idx);
1031            assert!(maybe.is_some(), "{idx} is none");
1032            let actual = maybe.unwrap();
1033            assert_eq!(idx, *actual as usize);
1034        }
1035    }
1036
1037    #[test]
1038    fn test_clear_and_reuse_strings() {
1039        let mut sut: HashedArrayTree<String> = HashedArrayTree::new();
1040        for _ in 0..512 {
1041            let value = ulid::Ulid::new().to_string();
1042            sut.push(value);
1043        }
1044        assert_eq!(sut.len(), 512);
1045        sut.clear();
1046        assert_eq!(sut.len(), 0);
1047        for _ in 0..512 {
1048            let value = ulid::Ulid::new().to_string();
1049            sut.push(value);
1050        }
1051        assert_eq!(sut.len(), 512);
1052        // implicitly drop()
1053    }
1054
1055    #[test]
1056    fn test_clone_ints() {
1057        let mut sut = HashedArrayTree::<usize>::new();
1058        for value in 0..512 {
1059            sut.push(value);
1060        }
1061        let cloned = sut.clone();
1062        let ai = sut.iter();
1063        let bi = cloned.iter();
1064        for (a, b) in ai.zip(bi) {
1065            assert_eq!(a, b);
1066        }
1067    }
1068
1069    #[test]
1070    fn test_clone_strings() {
1071        let mut sut = HashedArrayTree::<String>::new();
1072        for _ in 0..64 {
1073            let value = ulid::Ulid::new().to_string();
1074            sut.push(value);
1075        }
1076        let cloned = sut.clone();
1077        let ai = sut.iter();
1078        let bi = cloned.iter();
1079        for (a, b) in ai.zip(bi) {
1080            assert_eq!(a, b);
1081        }
1082    }
1083
1084    #[test]
1085    fn test_swap() {
1086        let mut sut = HashedArrayTree::<usize>::new();
1087        sut.push(1);
1088        sut.push(2);
1089        sut.push(3);
1090        sut.push(4);
1091        sut.swap(1, 3);
1092        assert_eq!(sut[0], 1);
1093        assert_eq!(sut[1], 4);
1094        assert_eq!(sut[2], 3);
1095        assert_eq!(sut[3], 2);
1096    }
1097
1098    #[test]
1099    #[should_panic(expected = "swap a (is 1) should be < len (is 1)")]
1100    fn test_swap_panic_a() {
1101        let mut sut = HashedArrayTree::<usize>::new();
1102        sut.push(1);
1103        sut.swap(1, 2);
1104    }
1105
1106    #[test]
1107    #[should_panic(expected = "swap b (is 1) should be < len (is 1)")]
1108    fn test_swap_panic_b() {
1109        let mut sut = HashedArrayTree::<usize>::new();
1110        sut.push(1);
1111        sut.swap(0, 1);
1112    }
1113
1114    #[test]
1115    fn test_sort_unstable_by_ints() {
1116        let mut sut = HashedArrayTree::<usize>::new();
1117        sut.push(10);
1118        sut.push(1);
1119        sut.push(100);
1120        sut.push(20);
1121        sut.push(2);
1122        sut.push(99);
1123        sut.push(88);
1124        sut.push(77);
1125        sut.push(66);
1126        sut.sort_unstable_by(|a, b| a.cmp(b));
1127        assert_eq!(sut[0], 1);
1128        assert_eq!(sut[1], 2);
1129        assert_eq!(sut[2], 10);
1130        assert_eq!(sut[3], 20);
1131        assert_eq!(sut[4], 66);
1132        assert_eq!(sut[5], 77);
1133        assert_eq!(sut[6], 88);
1134        assert_eq!(sut[7], 99);
1135        assert_eq!(sut[8], 100);
1136    }
1137
1138    #[test]
1139    fn test_sort_unstable_by_strings() {
1140        let mut sut = HashedArrayTree::<String>::new();
1141        sut.push("cat".into());
1142        sut.push("ape".into());
1143        sut.push("zebra".into());
1144        sut.push("dog".into());
1145        sut.push("bird".into());
1146        sut.push("tapir".into());
1147        sut.push("monkey".into());
1148        sut.push("giraffe".into());
1149        sut.push("frog".into());
1150        sut.sort_unstable_by(|a, b| a.cmp(b));
1151        assert_eq!(sut[0], "ape");
1152        assert_eq!(sut[1], "bird");
1153        assert_eq!(sut[2], "cat");
1154        assert_eq!(sut[3], "dog");
1155        assert_eq!(sut[4], "frog");
1156        assert_eq!(sut[5], "giraffe");
1157        assert_eq!(sut[6], "monkey");
1158        assert_eq!(sut[7], "tapir");
1159        assert_eq!(sut[8], "zebra");
1160    }
1161
1162    #[test]
1163    fn test_append() {
1164        let odds = ["one", "three", "five", "seven", "nine"];
1165        let mut sut = HashedArrayTree::<String>::new();
1166        for item in odds {
1167            sut.push(item.to_owned());
1168        }
1169        let evens = ["two", "four", "six", "eight", "ten"];
1170        let mut other = HashedArrayTree::<String>::new();
1171        for item in evens {
1172            other.push(item.to_owned());
1173        }
1174        sut.append(&mut other);
1175        assert_eq!(sut.len(), 10);
1176        assert_eq!(sut.capacity(), 12);
1177        assert_eq!(other.len(), 0);
1178        assert_eq!(other.capacity(), 0);
1179        sut.sort_unstable_by(|a, b| a.cmp(b));
1180        assert_eq!(sut[0], "eight");
1181        assert_eq!(sut[1], "five");
1182        assert_eq!(sut[2], "four");
1183        assert_eq!(sut[3], "nine");
1184        assert_eq!(sut[4], "one");
1185        assert_eq!(sut[5], "seven");
1186        assert_eq!(sut[6], "six");
1187        assert_eq!(sut[7], "ten");
1188        assert_eq!(sut[8], "three");
1189        assert_eq!(sut[9], "two");
1190    }
1191
1192    #[test]
1193    fn test_dedup_by_tiny() {
1194        let mut sut = HashedArrayTree::<String>::new();
1195        sut.push("one".into());
1196        sut.dedup_by(|a, b| a == b);
1197        assert_eq!(sut.len(), 1);
1198        assert_eq!(sut[0], "one");
1199    }
1200
1201    #[test]
1202    fn test_dedup_by_2_dupes() {
1203        let mut sut = HashedArrayTree::<String>::new();
1204        sut.push("one".into());
1205        sut.push("one".into());
1206        sut.dedup_by(|a, b| a == b);
1207        assert_eq!(sut.len(), 1);
1208        assert_eq!(sut[0], "one");
1209    }
1210
1211    #[test]
1212    fn test_dedup_by_2_unique() {
1213        let mut sut = HashedArrayTree::<String>::new();
1214        sut.push("one".into());
1215        sut.push("two".into());
1216        sut.dedup_by(|a, b| a == b);
1217        assert_eq!(sut.len(), 2);
1218        assert_eq!(sut[0], "one");
1219        assert_eq!(sut[1], "two");
1220    }
1221
1222    #[test]
1223    fn test_dedup_by_all_unique() {
1224        let inputs = [
1225            "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
1226        ];
1227        let mut sut = HashedArrayTree::<String>::new();
1228        for item in inputs {
1229            sut.push(item.to_owned());
1230        }
1231        sut.dedup_by(|a, b| a == b);
1232        assert_eq!(sut.len(), 9);
1233        for (idx, elem) in sut.into_iter().enumerate() {
1234            assert_eq!(inputs[idx], elem);
1235        }
1236    }
1237
1238    #[test]
1239    fn test_dedup_by_all_dupes() {
1240        let inputs = [
1241            "one", "one", "one", "one", "one", "one", "one", "one", "one", "one",
1242        ];
1243        let mut sut = HashedArrayTree::<String>::new();
1244        for item in inputs {
1245            sut.push(item.to_owned());
1246        }
1247        assert_eq!(sut.len(), 10);
1248        sut.dedup_by(|a, b| a == b);
1249        assert_eq!(sut.len(), 1);
1250        assert_eq!(inputs[0], "one");
1251    }
1252
1253    #[test]
1254    fn test_dedup_by_some_dupes_ints() {
1255        let inputs = [1, 2, 2, 3, 2];
1256        let mut sut = HashedArrayTree::<usize>::new();
1257        for item in inputs {
1258            sut.push(item.to_owned());
1259        }
1260        assert_eq!(sut.len(), 5);
1261        sut.dedup_by(|a, b| a == b);
1262        assert_eq!(sut.len(), 4);
1263        assert_eq!(sut[0], 1);
1264        assert_eq!(sut[1], 2);
1265        assert_eq!(sut[2], 3);
1266        assert_eq!(sut[3], 2);
1267    }
1268
1269    #[test]
1270    fn test_dedup_by_some_dupes_strings() {
1271        let inputs = ["foo", "bar", "Bar", "baz", "bar"];
1272        let mut sut = HashedArrayTree::<String>::new();
1273        for item in inputs {
1274            sut.push(item.to_owned());
1275        }
1276        assert_eq!(sut.len(), 5);
1277        sut.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
1278        assert_eq!(sut.len(), 4);
1279        assert_eq!(sut[0], "foo");
1280        assert_eq!(sut[1], "bar");
1281        assert_eq!(sut[2], "baz");
1282        assert_eq!(sut[3], "bar");
1283    }
1284
1285    #[test]
1286    #[should_panic(expected = "index out of bounds: 10")]
1287    fn test_split_off_bounds_panic() {
1288        let mut sut = HashedArrayTree::<usize>::new();
1289        sut.split_off(10);
1290    }
1291
1292    #[test]
1293    fn test_split_off_middle() {
1294        let mut sut = HashedArrayTree::<usize>::new();
1295        for value in 0..16 {
1296            sut.push(value);
1297        }
1298        assert_eq!(sut.len(), 16);
1299        assert_eq!(sut.capacity(), 16);
1300        let other = sut.split_off(8);
1301        assert_eq!(sut.len(), 8);
1302        assert_eq!(sut.capacity(), 8);
1303        for value in 0..8 {
1304            assert_eq!(sut[value], value);
1305        }
1306        assert_eq!(other.len(), 8);
1307        assert_eq!(other.capacity(), 8);
1308        for (index, value) in (8..16).enumerate() {
1309            assert_eq!(other[index], value);
1310        }
1311    }
1312
1313    #[test]
1314    fn test_split_off_almost_start() {
1315        let mut sut = HashedArrayTree::<usize>::new();
1316        for value in 0..16 {
1317            sut.push(value);
1318        }
1319        assert_eq!(sut.len(), 16);
1320        assert_eq!(sut.capacity(), 16);
1321        let other = sut.split_off(1);
1322        assert_eq!(sut.len(), 1);
1323        assert_eq!(sut.capacity(), 4);
1324        for value in 0..1 {
1325            assert_eq!(sut[value], value);
1326        }
1327        assert_eq!(other.len(), 15);
1328        assert_eq!(other.capacity(), 16);
1329        for (index, value) in (1..16).enumerate() {
1330            assert_eq!(other[index], value);
1331        }
1332    }
1333
1334    #[test]
1335    fn test_split_off_almost_end() {
1336        let mut sut = HashedArrayTree::<usize>::new();
1337        for value in 0..16 {
1338            sut.push(value);
1339        }
1340        assert_eq!(sut.len(), 16);
1341        assert_eq!(sut.capacity(), 16);
1342        let other = sut.split_off(15);
1343        assert_eq!(sut.len(), 15);
1344        assert_eq!(sut.capacity(), 16);
1345        for value in 0..15 {
1346            assert_eq!(sut[value], value);
1347        }
1348        assert_eq!(other.len(), 1);
1349        assert_eq!(other.capacity(), 4);
1350        assert_eq!(other[0], 15);
1351    }
1352
1353    #[test]
1354    fn test_split_off_odd_other() {
1355        let mut sut = HashedArrayTree::<usize>::new();
1356        for value in 0..16 {
1357            sut.push(value);
1358        }
1359        assert_eq!(sut.len(), 16);
1360        assert_eq!(sut.capacity(), 16);
1361        let other = sut.split_off(11);
1362        assert_eq!(sut.len(), 11);
1363        assert_eq!(sut.capacity(), 12);
1364        for value in 0..11 {
1365            assert_eq!(sut[value], value);
1366        }
1367        assert_eq!(other.len(), 5);
1368        assert_eq!(other.capacity(), 8);
1369        for (index, value) in (11..16).enumerate() {
1370            assert_eq!(other[index], value);
1371        }
1372    }
1373
1374    #[test]
1375    fn test_truncate_typical() {
1376        let mut sut = hat![1, 2, 3, 4, 5, 6, 7, 8];
1377        assert_eq!(sut.len(), 8);
1378        assert_eq!(sut.capacity(), 8);
1379        sut.truncate(5);
1380        assert_eq!(sut.len(), 5);
1381        assert_eq!(sut.capacity(), 8);
1382        for (index, value) in (1..6).enumerate() {
1383            assert_eq!(sut[index], value);
1384        }
1385    }
1386
1387    #[test]
1388    fn test_truncate_out_of_bounds() {
1389        let mut sut = hat![1, 2, 3, 4, 5,];
1390        assert_eq!(sut.len(), 5);
1391        assert_eq!(sut.capacity(), 8);
1392        sut.truncate(8);
1393        assert_eq!(sut.len(), 5);
1394        assert_eq!(sut.capacity(), 8);
1395        for (index, value) in (1..6).enumerate() {
1396            assert_eq!(sut[index], value);
1397        }
1398    }
1399
1400    #[test]
1401    fn test_truncate_to_empty() {
1402        let mut sut = hat![1, 2, 3, 4, 5,];
1403        assert_eq!(sut.len(), 5);
1404        assert_eq!(sut.capacity(), 8);
1405        sut.truncate(0);
1406        assert_eq!(sut.len(), 0);
1407        assert_eq!(sut.capacity(), 0);
1408    }
1409
1410    #[test]
1411    fn test_from_iterator() {
1412        let mut inputs: Vec<i32> = Vec::new();
1413        for value in 0..10_000 {
1414            inputs.push(value);
1415        }
1416        let sut: HashedArrayTree<i32> = inputs.into_iter().collect();
1417        assert_eq!(sut.len(), 10_000);
1418        for idx in 0..10_000i32 {
1419            let maybe = sut.get(idx as usize);
1420            assert!(maybe.is_some(), "{idx} is none");
1421            let actual = maybe.unwrap();
1422            assert_eq!(idx, *actual);
1423        }
1424    }
1425
1426    #[test]
1427    fn test_iterator() {
1428        let mut sut = HashedArrayTree::<usize>::new();
1429        for value in 0..512 {
1430            sut.push(value);
1431        }
1432        assert_eq!(sut.len(), 512);
1433        for (idx, elem) in sut.iter().enumerate() {
1434            assert_eq!(sut[idx], *elem);
1435        }
1436    }
1437
1438    #[test]
1439    fn test_into_iterator_edge_case() {
1440        // iterate to the end (of the last data block)
1441        let inputs = [
1442            "one", "two", "three", "four", "five", "six", "seven", "eight",
1443        ];
1444        let mut sut: HashedArrayTree<String> = HashedArrayTree::new();
1445        for item in inputs {
1446            sut.push(item.to_owned());
1447        }
1448        for (idx, elem) in sut.into_iter().enumerate() {
1449            assert_eq!(inputs[idx], elem);
1450        }
1451        // sut.len(); // error: ownership of sut was moved
1452    }
1453
1454    #[test]
1455    fn test_into_iterator_multiple_leaves() {
1456        let inputs = [
1457            "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
1458        ];
1459        let mut sut: HashedArrayTree<String> = HashedArrayTree::new();
1460        for item in inputs {
1461            sut.push(item.to_owned());
1462        }
1463        for (idx, elem) in sut.into_iter().enumerate() {
1464            assert_eq!(inputs[idx], elem);
1465        }
1466        // sut.len(); // error: ownership of sut was moved
1467    }
1468
1469    #[test]
1470    fn test_into_iterator_drop_empty() {
1471        let sut: HashedArrayTree<String> = HashedArrayTree::new();
1472        assert_eq!(sut.into_iter().count(), 0);
1473    }
1474
1475    #[test]
1476    fn test_into_iterator_drop_single_leaf() {
1477        // an array that only requires a single segment and only some need to be
1478        // dropped after partially iterating the values
1479        let inputs = ["one", "two", "three", "four"];
1480        let mut sut: HashedArrayTree<String> = HashedArrayTree::new();
1481        for item in inputs {
1482            sut.push(item.to_owned());
1483        }
1484        for (idx, _) in sut.into_iter().enumerate() {
1485            if idx > 1 {
1486                break;
1487            }
1488        }
1489        // implicitly drop()
1490    }
1491
1492    #[test]
1493    fn test_into_iterator_drop_large() {
1494        // by adding 512 values and iterating less than 32 times, there will be
1495        // values in the first segment and some in the last segment, and two
1496        // segments inbetween that all need to be dropped
1497        let mut sut: HashedArrayTree<String> = HashedArrayTree::new();
1498        for _ in 0..512 {
1499            let value = ulid::Ulid::new().to_string();
1500            sut.push(value);
1501        }
1502        for (idx, _) in sut.into_iter().enumerate() {
1503            if idx >= 28 {
1504                break;
1505            }
1506        }
1507        // implicitly drop()
1508    }
1509
1510    #[test]
1511    fn test_swap_remove_single_segment() {
1512        let mut sut: HashedArrayTree<u32> = HashedArrayTree::new();
1513        sut.push(1);
1514        sut.push(2);
1515        assert_eq!(sut.len(), 2);
1516        let one = sut.swap_remove(0);
1517        assert_eq!(one, 1);
1518        assert_eq!(sut[0], 2);
1519    }
1520
1521    #[test]
1522    fn test_swap_remove_prune_empty() {
1523        let mut sut: HashedArrayTree<u32> = HashedArrayTree::new();
1524        for value in 0..13 {
1525            sut.push(value);
1526        }
1527        assert_eq!(sut.len(), 13);
1528        assert_eq!(sut.capacity(), 16);
1529        let value = sut.swap_remove(8);
1530        assert_eq!(value, 8);
1531        assert_eq!(sut[8], 12);
1532        assert_eq!(sut.len(), 12);
1533        assert_eq!(sut.capacity(), 12);
1534    }
1535
1536    #[test]
1537    fn test_swap_remove_multiple_segments() {
1538        let mut sut: HashedArrayTree<u32> = HashedArrayTree::new();
1539        for value in 0..512 {
1540            sut.push(value);
1541        }
1542        assert_eq!(sut.len(), 512);
1543        let eighty = sut.swap_remove(80);
1544        assert_eq!(eighty, 80);
1545        assert_eq!(sut.pop(), Some(510));
1546        assert_eq!(sut[80], 511);
1547    }
1548
1549    #[test]
1550    #[should_panic(expected = "swap_remove index (is 0) should be < len (is 0)")]
1551    fn test_swap_remove_panic_empty() {
1552        let mut sut: HashedArrayTree<u32> = HashedArrayTree::new();
1553        sut.swap_remove(0);
1554    }
1555
1556    #[test]
1557    #[should_panic(expected = "swap_remove index (is 1) should be < len (is 1)")]
1558    fn test_swap_remove_panic_range_edge() {
1559        let mut sut: HashedArrayTree<u32> = HashedArrayTree::new();
1560        sut.push(1);
1561        sut.swap_remove(1);
1562    }
1563
1564    #[test]
1565    #[should_panic(expected = "swap_remove index (is 2) should be < len (is 1)")]
1566    fn test_swap_remove_panic_range_exceed() {
1567        let mut sut: HashedArrayTree<u32> = HashedArrayTree::new();
1568        sut.push(1);
1569        sut.swap_remove(2);
1570    }
1571
1572    #[test]
1573    fn test_push_get_many_instances_ints() {
1574        // test allocating, filling, and then dropping many instances
1575        for _ in 0..1_000 {
1576            let mut sut: HashedArrayTree<usize> = HashedArrayTree::new();
1577            for value in 0..10_000 {
1578                sut.push(value);
1579            }
1580            assert_eq!(sut.len(), 10_000);
1581        }
1582    }
1583
1584    #[test]
1585    fn test_push_get_many_instances_strings() {
1586        // test allocating, filling, and then dropping many instances
1587        for _ in 0..1_000 {
1588            let mut sut: HashedArrayTree<String> = HashedArrayTree::new();
1589            for _ in 0..1_000 {
1590                let value = ulid::Ulid::new().to_string();
1591                sut.push(value);
1592            }
1593            assert_eq!(sut.len(), 1_000);
1594        }
1595    }
1596}