blart/collections/map/iterators/
range.rs

1//! This module contains types and functions relating to iterating over a
2//! range of the [`TreeMap`].
3
4use core::{
5    cmp::Ordering,
6    fmt,
7    iter::FusedIterator,
8    ops::{Bound, ControlFlow},
9};
10
11use crate::{
12    allocator::{Allocator, Global},
13    map::{NonEmptyTree, DEFAULT_PREFIX_LEN},
14    raw::{
15        match_concrete_node_ptr, maximum_unchecked, minimum_unchecked,
16        AttemptOptimisticPrefixMatch, ConcreteNodePtr, InnerNode, LeafNode, NodePtr, OpaqueNodePtr,
17        PrefixMatchBehavior, RawIterator,
18    },
19    AsBytes, TreeMap,
20};
21
22/// This struct contains details of where and why the search stopped in an inner
23/// node.
24pub(crate) struct InnerNodeSearchResult<K, V, const PREFIX_LEN: usize> {
25    /// This is a pointer to the inner node where search stopped.
26    pub node_ptr: OpaqueNodePtr<K, V, PREFIX_LEN>,
27
28    /// The number of bytes of the key that were consumed, not including the
29    /// byte that was used to look for a child node.
30    pub current_depth: usize,
31
32    /// This is a comparison from the full prefix of the inner node to the
33    /// corresponding segment of the search key.
34    pub node_prefix_comparison_to_search_key_segment: Ordering,
35
36    /// This field indicates why the search stopped in the inner node.
37    pub reason: InnerNodeSearchResultReason,
38}
39
40impl<K, V, const PREFIX_LEN: usize> fmt::Debug for InnerNodeSearchResult<K, V, PREFIX_LEN> {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        f.debug_struct("InnerNodeSearchResult")
43            .field("node_ptr", &self.node_ptr)
44            .field("current_depth", &self.current_depth)
45            .field(
46                "node_prefix_comparison_to_search_key_segment",
47                &self.node_prefix_comparison_to_search_key_segment,
48            )
49            .field("reason", &self.reason)
50            .finish()
51    }
52}
53
54/// These are search termination reasons specific to inner nodes.
55#[derive(Debug)]
56pub(crate) enum InnerNodeSearchResultReason {
57    /// This variant means the search terminated in a mismatched prefix of an
58    /// inner node OR the prefix matched, but there were insufficient key bytes
59    /// to lookup a child of the inner node.
60    PrefixMismatchOrInsufficientBytes,
61    /// This variant means the search terminated in an inner node, when there
62    /// was no corresponding child for a key byte.
63    MissingChild,
64}
65
66/// This enum provides the different cases of search result when looking for a
67/// starting/ending point for iteration.
68pub(crate) enum TerminatingNodeSearchResult<K, V, const PREFIX_LEN: usize> {
69    /// This variant means the search terminated at a leaf node.
70    Leaf {
71        /// The leaf node pointer where search terminated.
72        leaf_ptr: NodePtr<PREFIX_LEN, LeafNode<K, V, PREFIX_LEN>>,
73        /// The ordering of the leaf key bytes relative to the search bytes.
74        leaf_key_comparison_to_search_key: Ordering,
75    },
76    /// This variant means the search terminated at an inner node.
77    InnerNode(InnerNodeSearchResult<K, V, PREFIX_LEN>),
78}
79
80impl<K, V, const PREFIX_LEN: usize> fmt::Debug for TerminatingNodeSearchResult<K, V, PREFIX_LEN> {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        match self {
83            Self::Leaf {
84                leaf_ptr,
85                leaf_key_comparison_to_search_key,
86            } => f
87                .debug_struct("Leaf")
88                .field("leaf_ptr", leaf_ptr)
89                .field(
90                    "leaf_key_comparison_to_search_key",
91                    leaf_key_comparison_to_search_key,
92                )
93                .finish(),
94            Self::InnerNode(arg0) => f.debug_tuple("InnerNode").field(arg0).finish(),
95        }
96    }
97}
98
99/// Find the node (inner or leaf) that is identified by the given bytestring.
100///
101/// # Safety
102///
103/// This function cannot be called concurrently with any mutating operation
104/// on `root` or any child node of `root`. This function will arbitrarily
105/// read to any child in the given tree.
106pub(crate) unsafe fn find_terminating_node<K: AsBytes, V, const PREFIX_LEN: usize>(
107    root: OpaqueNodePtr<K, V, PREFIX_LEN>,
108    key_bytes: &[u8],
109) -> TerminatingNodeSearchResult<K, V, PREFIX_LEN> {
110    /// This function will search some key bytes at a specific depth in the
111    /// given inner node, returning different results depending on if the search
112    /// terminated or needs to continue down the trie.
113    ///
114    /// If this function returns [`ControlFlow::Continue`] then the search
115    /// continues down the trie, otherwise it terminates at this inner node.
116    ///
117    /// # Safety
118    ///
119    /// Callers must guarantee that there is no concurrent mutation of the given
120    /// inner node for the duration of this function.
121    unsafe fn check_prefix_lookup_child<K, V, N, const PREFIX_LEN: usize>(
122        inner_ptr: NodePtr<PREFIX_LEN, N>,
123        key_bytes: &[u8],
124        current_depth: &mut usize,
125        prefix_match_behavior: &mut PrefixMatchBehavior,
126    ) -> ControlFlow<InnerNodeSearchResult<K, V, PREFIX_LEN>, OpaqueNodePtr<K, V, PREFIX_LEN>>
127    where
128        N: InnerNode<PREFIX_LEN, Key = K, Value = V>,
129        K: AsBytes,
130    {
131        // SAFETY: The lifetime produced from this is bounded to this scope and does not
132        // escape. Further, no other code mutates the node referenced, which is further
133        // enforced the "no concurrent reads or writes" requirement on the
134        // `check_prefix_lookup_child` function.
135        let inner_node = unsafe { inner_ptr.as_ref() };
136        let match_prefix =
137            prefix_match_behavior.match_prefix(inner_node, &key_bytes[*current_depth..]);
138        match match_prefix {
139            Err(_) => {
140                let (full_prefix, _) = inner_node.read_full_prefix(*current_depth);
141                let upper_bound = (*current_depth + full_prefix.len()).min(key_bytes.len());
142                let key_segment = &key_bytes[(*current_depth)..upper_bound];
143
144                let node_prefix_comparison_to_search_key_segment = full_prefix.cmp(key_segment);
145
146                ControlFlow::Break(InnerNodeSearchResult {
147                    node_ptr: inner_ptr.to_opaque(),
148                    current_depth: *current_depth,
149                    reason: InnerNodeSearchResultReason::PrefixMismatchOrInsufficientBytes,
150                    node_prefix_comparison_to_search_key_segment,
151                })
152            },
153            Ok(AttemptOptimisticPrefixMatch { matched_bytes, .. }) => {
154                // Since the prefix matched, advance the depth by the size of the prefix
155                *current_depth += matched_bytes;
156
157                let next_key_fragment = if *current_depth < key_bytes.len() {
158                    key_bytes[*current_depth]
159                } else {
160                    // the key has insufficient bytes, it is a prefix of an existing key. Thus, the
161                    // key must not exist in the tree by the requirements of the insert function
162                    // (any key in the tree must not be the prefix of any other key in the tree)
163                    return ControlFlow::Break(InnerNodeSearchResult {
164                        node_ptr: inner_ptr.to_opaque(),
165                        current_depth: *current_depth,
166                        reason: InnerNodeSearchResultReason::PrefixMismatchOrInsufficientBytes,
167                        node_prefix_comparison_to_search_key_segment: Ordering::Equal,
168                    });
169                };
170
171                let child_lookup = inner_node.lookup_child(next_key_fragment);
172
173                match child_lookup {
174                    Some(child_ptr) => {
175                        // Since the prefix matched and it found a child, advance the depth by 1
176                        // more key byte
177                        *current_depth += 1;
178                        ControlFlow::Continue(child_ptr)
179                    },
180                    None => ControlFlow::Break(InnerNodeSearchResult {
181                        node_ptr: inner_ptr.to_opaque(),
182                        current_depth: *current_depth,
183                        reason: InnerNodeSearchResultReason::MissingChild,
184                        node_prefix_comparison_to_search_key_segment: Ordering::Equal,
185                    }),
186                }
187            },
188        }
189    }
190
191    let mut current_node = root;
192    let mut current_depth = 0;
193    let mut prefix_match_behavior = PrefixMatchBehavior::default();
194
195    loop {
196        let next_node = match_concrete_node_ptr!(match (current_node.to_node_ptr()) {
197            InnerNode(inner_ptr) => unsafe {
198                // SAFETY: The safety requirement is covered by the safety documentation on the
199                // containing function
200                check_prefix_lookup_child(
201                    inner_ptr,
202                    key_bytes,
203                    &mut current_depth,
204                    &mut prefix_match_behavior,
205                )
206            },
207            LeafNode(leaf_ptr) => {
208                // SAFETY: The shared reference is bounded to this block and there are no
209                // concurrent modifications, by the safety conditions of this function.
210                let leaf_node = unsafe { leaf_ptr.as_ref() };
211
212                let leaf_key_comparison_to_search_key =
213                    prefix_match_behavior.compare_leaf_key(leaf_node, key_bytes, current_depth);
214
215                return TerminatingNodeSearchResult::Leaf {
216                    leaf_ptr,
217                    leaf_key_comparison_to_search_key,
218                };
219            },
220        });
221
222        match next_node {
223            ControlFlow::Continue(next_node) => {
224                current_node = next_node;
225            },
226            ControlFlow::Break(reason) => {
227                return TerminatingNodeSearchResult::InnerNode(reason);
228            },
229        }
230    }
231}
232
233/// Panic if the given range bounds
234#[track_caller]
235pub(crate) fn validate_range_bounds(start_bound: &Bound<&[u8]>, end_bound: &Bound<&[u8]>) {
236    match (*start_bound, *end_bound) {
237        (Bound::Excluded(s), Bound::Excluded(e)) if s == e => {
238            panic!("range start and end are equal and excluded: ({s:?})")
239        },
240        (Bound::Included(s) | Bound::Excluded(s), Bound::Included(e) | Bound::Excluded(e))
241            if s > e =>
242        {
243            panic!("range start ({s:?}) is greater than range end ({e:?})")
244        },
245        _ => {},
246    }
247}
248
249type KeyByteAndChild<K, V, const PREFIX_LEN: usize> = Option<(u8, OpaqueNodePtr<K, V, PREFIX_LEN>)>;
250
251/// This function searches a trie for the smallest/largest leaf node that is
252/// greater/less than the given bound.
253///
254/// If `is_start` is true, its looking for the smallest leaf node that is
255/// greater than the given bound. If `is_start` is false, we're looking for the
256/// greatest leaf node that is smaller than the given bound.
257///
258/// # Safety
259///
260/// Callers must guarantee that there is no concurrent mutation of the given
261/// trie for the duration of this function.
262pub(crate) unsafe fn find_leaf_pointer_for_bound<K: AsBytes, V, const PREFIX_LEN: usize>(
263    tree: &NonEmptyTree<K, V, PREFIX_LEN>,
264    bound: Bound<&[u8]>,
265    is_start: bool,
266) -> Option<NodePtr<PREFIX_LEN, LeafNode<K, V, PREFIX_LEN>>> {
267    Some(match bound {
268        Bound::Included(key_bytes) | Bound::Excluded(key_bytes) => {
269            // SAFETY: Covered by function safety doc
270            let terminating_node = unsafe { find_terminating_node(tree.root, key_bytes) };
271
272            match terminating_node {
273                TerminatingNodeSearchResult::Leaf {
274                    leaf_ptr,
275                    leaf_key_comparison_to_search_key,
276                } => match leaf_key_comparison_to_search_key {
277                    Ordering::Less => {
278                        if is_start {
279                            // SAFETY: Covered by function safety doc
280                            let leaf = unsafe { leaf_ptr.as_ref() };
281                            leaf.next?
282                        } else {
283                            leaf_ptr
284                        }
285                    },
286                    Ordering::Equal => {
287                        if matches!(bound, Bound::Excluded(_)) {
288                            // SAFETY: Covered by function safety doc
289                            let leaf = unsafe { leaf_ptr.as_ref() };
290                            if is_start { leaf.next } else { leaf.previous }?
291                        } else {
292                            leaf_ptr
293                        }
294                    },
295                    Ordering::Greater => {
296                        if is_start {
297                            leaf_ptr
298                        } else {
299                            // SAFETY: Covered by function safety doc
300                            let leaf = unsafe { leaf_ptr.as_ref() };
301                            leaf.previous?
302                        }
303                    },
304                },
305                TerminatingNodeSearchResult::InnerNode(InnerNodeSearchResult {
306                    node_ptr,
307                    current_depth,
308                    reason,
309                    node_prefix_comparison_to_search_key_segment,
310                }) => match reason {
311                    InnerNodeSearchResultReason::PrefixMismatchOrInsufficientBytes => {
312                        match (is_start, node_prefix_comparison_to_search_key_segment) {
313                            (true, Ordering::Equal | Ordering::Greater) => unsafe {
314                                // SAFETY: Covered by function safety doc
315                                minimum_unchecked(node_ptr)
316                            },
317                            (true, Ordering::Less) => unsafe {
318                                // SAFETY: Covered by function safety doc
319                                let max_leaf_ptr = maximum_unchecked(node_ptr);
320                                let max_leaf = max_leaf_ptr.as_ref();
321                                max_leaf.next?
322                            },
323                            (false, Ordering::Equal | Ordering::Less) => unsafe {
324                                // SAFETY: Covered by function safety doc
325                                maximum_unchecked(node_ptr)
326                            },
327                            (false, Ordering::Greater) => unsafe {
328                                // SAFETY: Covered by function safety doc
329                                let min_leaf_ptr = minimum_unchecked(node_ptr);
330                                let min_leaf = min_leaf_ptr.as_ref();
331                                min_leaf.previous?
332                            },
333                        }
334                    },
335                    InnerNodeSearchResultReason::MissingChild => {
336                        fn access_closest_child<
337                            const PREFIX_LEN: usize,
338                            N: InnerNode<PREFIX_LEN>,
339                        >(
340                            inner_ptr: NodePtr<PREFIX_LEN, N>,
341                            child_bounds: (Bound<u8>, Bound<u8>),
342                            is_start: bool,
343                        ) -> KeyByteAndChild<N::Key, N::Value, PREFIX_LEN> {
344                            // SAFETY: Covered by function safety doc
345                            let inner = unsafe { inner_ptr.as_ref() };
346                            let mut child_it = inner.range(child_bounds);
347                            if is_start {
348                                child_it.next()
349                            } else {
350                                child_it.next_back()
351                            }
352                        }
353
354                        let child_bounds = if is_start {
355                            (bound.map(|_| key_bytes[current_depth]), Bound::Unbounded)
356                        } else {
357                            (Bound::Unbounded, bound.map(|_| key_bytes[current_depth]))
358                        };
359                        let possible_next_child =
360                            match_concrete_node_ptr!(match (node_ptr.to_node_ptr()) {
361                                InnerNode(inner_ptr) => {
362                                    access_closest_child(inner_ptr, child_bounds, is_start)
363                                },
364                                LeafNode(_leaf) => unreachable!(
365                                    "This branch is unreachable because the \
366                                     TerminatingNodeSearchResult had the value InnerNode"
367                                ),
368                            });
369                        let (_, next_child) = possible_next_child?;
370
371                        if is_start {
372                            // SAFETY: Covered by function safety doc
373                            unsafe { minimum_unchecked(next_child) }
374                        } else {
375                            // SAFETY: Covered by function safety doc
376                            unsafe { maximum_unchecked(next_child) }
377                        }
378                    },
379                },
380            }
381        },
382        Bound::Unbounded => {
383            if is_start {
384                tree.min_leaf
385            } else {
386                tree.max_leaf
387            }
388        },
389    })
390}
391
392macro_rules! implement_range_iter {
393    (
394        $(#[$outer:meta])*
395        struct $name:ident {
396            tree: $tree_ty:ty,
397            item: $item_ty:ty,
398            $leaf_accessor_func:ident
399        }
400    ) => {
401        $(#[$outer])*
402        pub struct $name<'a, K, V, const PREFIX_LEN: usize = DEFAULT_PREFIX_LEN, A: Allocator = Global> {
403            inner: RawIterator<K, V, PREFIX_LEN>,
404            _tree: $tree_ty,
405        }
406
407        impl<'a, K: AsBytes, V, const PREFIX_LEN: usize, A: Allocator> $name<'a, K, V, PREFIX_LEN, A> {
408            /// Create a new range iterator over the given tree, starting and ending
409            /// according to the given bounds.
410            ///
411            /// # Panics
412            ///
413            /// This function will panic if `start_bound` is greater than `end_bound`.
414            pub(crate) fn new(
415                tree: $tree_ty,
416                start_bound: Bound<&[u8]>,
417                end_bound: Bound<&[u8]>,
418            ) -> Self {
419                let Some(tree_state) = &tree.state else {
420                    return Self {
421                        _tree: tree,
422                        inner: RawIterator::empty(),
423                    };
424                };
425
426                // Validation happens after the empty check so we can avoid panicking for invalid range
427                // when the tree is empty. I believe this matches BTreeMap behavior.
428                validate_range_bounds(&start_bound, &end_bound);
429
430                // SAFETY: Since we have a (shared or mutable) reference to the original TreeMap, we know
431                // there will be no concurrent mutation
432                let possible_start =
433                    unsafe { find_leaf_pointer_for_bound(tree_state, start_bound, true) };
434                let Some(start) = possible_start else {
435                    return Self {
436                        _tree: tree,
437                        inner: RawIterator::empty(),
438                    };
439                };
440
441                // SAFETY: Since we have a (shared or mutable) reference to the original TreeMap, we know
442                // there will be no concurrent mutation
443                let possible_end =
444                    unsafe { find_leaf_pointer_for_bound(tree_state, end_bound, false) };
445                let Some(end) = possible_end else {
446                    return Self {
447                        _tree: tree,
448                        inner: RawIterator::empty(),
449                    };
450                };
451
452                // SAFETY: Since we have a (shared or mutable) reference to the original TreeMap, we know
453                // there will be no concurrent mutation. Also, the reference lifetimes created
454                // are bounded to this `unsafe` block, and don't overlap with any mutation.
455                unsafe {
456                    let start_leaf_bytes = start.as_key_ref().as_bytes();
457                    let end_leaf_bytes = end.as_key_ref().as_bytes();
458
459                    if start_leaf_bytes > end_leaf_bytes {
460                        // Resolved start leaf is not less than or equal to resolved end leaf for
461                        // iteration order
462                        return Self {
463                            _tree: tree,
464                            inner: RawIterator::empty(),
465                        };
466                    }
467                }
468
469                Self {
470                    _tree: tree,
471                    // SAFETY: `start` is guaranteed to be less than or equal to `end` in the iteration
472                    // order because of the check we do on the bytes of the resolved leaf pointers, just
473                    // above this line
474                    inner: unsafe { RawIterator::new(start, end) },
475                }
476            }
477        }
478
479        impl<'a, K, V, const PREFIX_LEN: usize, A: Allocator> Iterator for $name<'a, K, V, PREFIX_LEN, A> {
480            type Item = $item_ty;
481
482            fn next(&mut self) -> Option<Self::Item> {
483                // SAFETY: This iterator has a reference (either shared or mutable) to the
484                // original `TreeMap` it is iterating over, preventing any other modification.
485                let leaf_ptr = unsafe { self.inner.next()? };
486
487                // SAFETY: THe lifetimes returned from this function are returned as bounded by
488                // lifetime 'a, meaning that they cannot outlive this iterator's reference
489                // (shared or mutable) to the original TreeMap.
490                Some(unsafe { leaf_ptr.$leaf_accessor_func() })
491            }
492        }
493
494        impl<'a, K, V, const PREFIX_LEN: usize, A: Allocator> DoubleEndedIterator
495            for $name<'a, K, V, PREFIX_LEN, A>
496        {
497            fn next_back(&mut self) -> Option<Self::Item> {
498                // SAFETY: This iterator has a reference (either shared or mutable) to the
499                // original `TreeMap` it is iterating over, preventing any other modification.
500                let leaf_ptr = unsafe { self.inner.next_back()? };
501
502                // SAFETY: THe lifetimes returned from this function are returned as bounded by
503                // lifetime 'a, meaning that they cannot outlive this iterator's reference
504                // (shared or mutable) to the original TreeMap.
505                Some(unsafe { leaf_ptr.$leaf_accessor_func() })
506            }
507        }
508
509        impl<'a, K, V, const PREFIX_LEN: usize, A: Allocator> FusedIterator for $name<'a, K, V, PREFIX_LEN, A> {}
510    };
511}
512
513implement_range_iter!(
514    /// An iterator over a sub-range of entries in a [`TreeMap`].
515    ///
516    /// This struct is created by the [`range`][TreeMap::range] method on `TreeMap`.
517    /// See its documentation for more details.
518    struct Range {
519        tree: &'a TreeMap<K, V, PREFIX_LEN, A>,
520        item: (&'a K, &'a V),
521        as_key_value_ref
522    }
523);
524
525// SAFETY: This iterator holds a shared reference to the underlying `TreeMap`
526// and thus can be moved across threads if the `TreeMap<K, V>: Sync`.
527unsafe impl<K, V, A, const PREFIX_LEN: usize> Send for Range<'_, K, V, PREFIX_LEN, A>
528where
529    K: Sync,
530    V: Sync,
531    A: Sync + Allocator,
532{
533}
534
535// SAFETY: This iterator has no interior mutability and can be shared across
536// thread so long as the reference `TreeMap<K, V>` can as well.
537unsafe impl<K, V, A, const PREFIX_LEN: usize> Sync for Range<'_, K, V, PREFIX_LEN, A>
538where
539    K: Sync,
540    V: Sync,
541    A: Sync + Allocator,
542{
543}
544
545implement_range_iter!(
546    /// A mutable iterator over a sub-range of entries in a [`TreeMap`].
547    ///
548    /// This struct is created by the [`range_mut`][TreeMap::range_mut] method on `TreeMap`.
549    /// See its documentation for more details.
550    struct RangeMut {
551        tree: &'a mut TreeMap<K, V, PREFIX_LEN, A>,
552        item: (&'a K, &'a mut V),
553        as_key_ref_value_mut
554    }
555);
556
557// SAFETY: This iterator has a mutable reference to the underlying `TreeMap` and
558// can be moved across threads if `&mut TreeMap<K, V>` is `Send`, which requires
559// `TreeMap<K, V>` to be `Send` as well.
560unsafe impl<K, V, A, const PREFIX_LEN: usize> Send for RangeMut<'_, K, V, PREFIX_LEN, A>
561where
562    K: Send,
563    V: Send,
564    A: Send + Allocator,
565{
566}
567
568// SAFETY: This iterator uses no interior mutability and can be shared across
569// threads so long as `TreeMap<K, V>: Sync`.
570unsafe impl<K, V, A, const PREFIX_LEN: usize> Sync for RangeMut<'_, K, V, PREFIX_LEN, A>
571where
572    K: Sync,
573    V: Sync,
574    A: Sync + Allocator,
575{
576}
577
578#[cfg(test)]
579mod tests {
580    use alloc::{boxed::Box, vec::Vec};
581
582    use super::*;
583    use crate::testing::{generate_key_with_prefix, swap, PrefixExpansion};
584
585    #[test]
586    fn iterators_are_send_sync() {
587        fn is_send<T: Send>() {}
588        fn is_sync<T: Sync>() {}
589
590        fn range_is_send<'a, K: Sync + 'a, V: Sync + 'a, A: Sync + Allocator + 'a>() {
591            is_send::<Range<'a, K, V, DEFAULT_PREFIX_LEN, A>>();
592        }
593
594        fn range_is_sync<'a, K: Sync + 'a, V: Sync + 'a, A: Sync + Allocator + 'a>() {
595            is_sync::<Range<'a, K, V, DEFAULT_PREFIX_LEN, A>>();
596        }
597
598        range_is_send::<[u8; 3], usize, Global>();
599        range_is_sync::<[u8; 3], usize, Global>();
600
601        fn range_mut_is_send<'a, K: Send + 'a, V: Send + 'a, A: Send + Allocator + 'a>() {
602            is_send::<RangeMut<'a, K, V, DEFAULT_PREFIX_LEN, A>>();
603        }
604
605        fn range_mut_is_sync<'a, K: Sync + 'a, V: Sync + 'a, A: Sync + Allocator + 'a>() {
606            is_sync::<RangeMut<'a, K, V, DEFAULT_PREFIX_LEN, A>>();
607        }
608
609        range_mut_is_send::<[u8; 3], usize, Global>();
610        range_mut_is_sync::<[u8; 3], usize, Global>();
611    }
612
613    fn fixture_tree() -> TreeMap<[u8; 3], usize> {
614        [
615            [0, 0, 0],
616            [0, 0, u8::MAX],
617            [0, u8::MAX, 0],
618            [0, u8::MAX, u8::MAX],
619            [127, 127, 0],
620            [127, 127, 127],
621            [127, 127, u8::MAX],
622            [u8::MAX, 0, 0],
623            [u8::MAX, 0, u8::MAX],
624            [u8::MAX, u8::MAX, 0],
625            [u8::MAX, u8::MAX, u8::MAX],
626        ]
627        .into_iter()
628        .enumerate()
629        .map(swap)
630        .collect()
631    }
632
633    #[test]
634    fn range_iteration_normal_tree() {
635        let tree = fixture_tree();
636
637        // Included on end of key range
638        let mut it = Range::new(
639            &tree,
640            Bound::Included([u8::MAX, u8::MAX, u8::MAX].as_slice()),
641            Bound::Unbounded,
642        )
643        .map(|(k, _)| k);
644        assert_eq!(it.next().unwrap(), &[u8::MAX, u8::MAX, u8::MAX]);
645        assert_eq!(it.next(), None);
646
647        // Excluded on end of key range
648        let mut it = Range::new(
649            &tree,
650            Bound::Excluded([u8::MAX, u8::MAX, u8::MAX].as_slice()),
651            Bound::Unbounded,
652        )
653        .map(|(k, _)| k);
654        assert_eq!(it.next(), None);
655
656        // Included on start of key range
657        let mut it = Range::new(
658            &tree,
659            Bound::Unbounded,
660            Bound::Included([0, 0, 0].as_slice()),
661        )
662        .map(|(k, _)| k);
663        assert_eq!(it.next().unwrap(), &[0, 0, 0]);
664        assert_eq!(it.next(), None);
665
666        // Excluded on start of key range
667        let mut it = Range::new(
668            &tree,
669            Bound::Unbounded,
670            Bound::Excluded([0, 0, 0].as_slice()),
671        )
672        .map(|(k, _)| k);
673        assert_eq!(it.next(), None);
674    }
675
676    #[test]
677    fn range_iteration_on_key_prefix() {
678        let tree = fixture_tree();
679
680        let mut it = Range::new(
681            &tree,
682            Bound::Included([0].as_slice()),
683            Bound::Excluded([1].as_slice()),
684        )
685        .map(|(k, _)| k);
686
687        assert_eq!(it.next().unwrap(), &[0, 0, 0]);
688        assert_eq!(it.next().unwrap(), &[0, 0, u8::MAX]);
689        assert_eq!(it.next().unwrap(), &[0, u8::MAX, 0]);
690        assert_eq!(it.next().unwrap(), &[0, u8::MAX, u8::MAX]);
691        assert_eq!(it.next(), None);
692    }
693
694    #[test]
695    fn range_prefix_mismatch_or_insufficient_bytes_lower_bounds() {
696        let tree = fixture_tree();
697
698        let mut it = Range::new(
699            &tree,
700            Bound::Included([127, 126].as_slice()),
701            Bound::Excluded([128].as_slice()),
702        )
703        .map(|(k, _)| k);
704
705        // This should produce the 3 keys because the start key [127, 126] is ordered
706        // before the key [127, 127, 0]
707        assert!([127, 126].as_slice() < [127, 127, 0].as_slice());
708        assert_eq!(it.next().unwrap(), &[127, 127, 0]);
709        assert_eq!(it.next().unwrap(), &[127, 127, 127]);
710        assert_eq!(it.next().unwrap(), &[127, 127, u8::MAX]);
711        assert_eq!(it.next(), None);
712
713        let mut it = Range::new(
714            &tree,
715            Bound::Included([127, 128].as_slice()),
716            Bound::Excluded([128].as_slice()),
717        )
718        .map(|(k, _)| k);
719
720        // This should produce no keys because the start key [127, 128] is ordered after
721        // the key [127, 127, u8::MAX]
722        assert!([127, 128].as_slice() > [127, 127, u8::MAX].as_slice());
723        assert_eq!(it.next(), None);
724
725        let mut it = Range::new(
726            &tree,
727            Bound::Included([127].as_slice()),
728            Bound::Excluded([128].as_slice()),
729        )
730        .map(|(k, _)| k);
731
732        // This should produce the 3 keys because the start key [127] is ordered
733        // before the key [127, 127, 0]
734        assert!([127].as_slice() < [127, 127, 0].as_slice());
735        assert_eq!(it.next().unwrap(), &[127, 127, 0]);
736        assert_eq!(it.next().unwrap(), &[127, 127, 127]);
737        assert_eq!(it.next().unwrap(), &[127, 127, u8::MAX]);
738        assert_eq!(it.next(), None);
739
740        let mut it = Range::new(
741            &tree,
742            Bound::Included([127, 127].as_slice()),
743            Bound::Excluded([128].as_slice()),
744        )
745        .map(|(k, _)| k);
746
747        // This should produce the 3 keys because the start key [127, 127] is ordered
748        // before the key [127, 127, 0]
749        assert!([127, 127].as_slice() < [127, 127, 0].as_slice());
750        assert_eq!(it.next().unwrap(), &[127, 127, 0]);
751        assert_eq!(it.next().unwrap(), &[127, 127, 127]);
752        assert_eq!(it.next().unwrap(), &[127, 127, u8::MAX]);
753        assert_eq!(it.next(), None);
754    }
755
756    #[test]
757    fn range_prefix_mismatch_or_insufficient_bytes_upper_bounds() {
758        let tree = fixture_tree();
759
760        let mut it = Range::new(
761            &tree,
762            Bound::Excluded([126].as_slice()),
763            Bound::Excluded([128].as_slice()),
764        )
765        .map(|(k, _)| k);
766        assert_eq!(it.next().unwrap(), &[127, 127, 0]);
767        assert_eq!(it.next().unwrap(), &[127, 127, 127]);
768        assert_eq!(it.next().unwrap(), &[127, 127, u8::MAX]);
769        assert_eq!(it.next(), None);
770
771        let mut it = Range::new(
772            &tree,
773            Bound::Excluded([126].as_slice()),
774            Bound::Included([127, 127, u8::MAX].as_slice()),
775        )
776        .map(|(k, _)| k);
777        assert_eq!(it.next().unwrap(), &[127, 127, 0]);
778        assert_eq!(it.next().unwrap(), &[127, 127, 127]);
779        assert_eq!(it.next().unwrap(), &[127, 127, u8::MAX]);
780        assert_eq!(it.next(), None);
781
782        let mut it = Range::new(
783            &tree,
784            Bound::Excluded([126].as_slice()),
785            Bound::Included([127, 127, 0].as_slice()),
786        )
787        .map(|(k, _)| k);
788        assert_eq!(it.next().unwrap(), &[127, 127, 0]);
789        assert_eq!(it.next(), None);
790    }
791
792    #[test]
793    fn empty_tree_empty_iterator() {
794        let tree = TreeMap::<[u8; 3], usize>::new();
795
796        let it = Range::new(
797            &tree,
798            Bound::Excluded([1, 1, 1].as_slice()),
799            Bound::Excluded([1, 1, 1].as_slice()),
800        );
801
802        assert_eq!(it.count(), 0);
803    }
804
805    #[test]
806    #[should_panic(expected = "range start and end are equal and excluded: ([1, 1, 1])")]
807    fn equal_excluded_bounds_should_panic() {
808        let tree = fixture_tree();
809
810        let _it = Range::new(
811            &tree,
812            Bound::Excluded([1, 1, 1].as_slice()),
813            Bound::Excluded([1, 1, 1].as_slice()),
814        );
815    }
816
817    #[test]
818    #[should_panic(expected = "range start ([1, 1, 1]) is greater than range end ([0, 0, 0])")]
819    fn excluded_excluded_start_greater_than_end_should_panic() {
820        let tree = fixture_tree();
821
822        let _it = Range::new(
823            &tree,
824            Bound::Excluded([1, 1, 1].as_slice()),
825            Bound::Excluded([0, 0, 0].as_slice()),
826        );
827    }
828
829    #[test]
830    #[should_panic(expected = "range start ([1, 1, 1]) is greater than range end ([0, 0, 0])")]
831    fn included_included_start_greater_than_end_should_panic() {
832        let tree = fixture_tree();
833
834        let _it = Range::new(
835            &tree,
836            Bound::Included([1, 1, 1].as_slice()),
837            Bound::Included([0, 0, 0].as_slice()),
838        );
839    }
840
841    #[test]
842    fn excluded_excluded_empty_range_should_be_empty() {
843        let tree = fixture_tree();
844
845        let it = Range::new(
846            &tree,
847            Bound::Excluded([127, 127, 127].as_slice()),
848            Bound::Excluded([127, 127, 128].as_slice()),
849        );
850
851        assert_eq!(it.count(), 0);
852
853        let it = Range::new(
854            &tree,
855            Bound::Excluded([127, 127, 126].as_slice()),
856            Bound::Excluded([127, 127, 127].as_slice()),
857        );
858
859        assert_eq!(it.count(), 0);
860    }
861
862    #[test]
863    fn included_included_range_on_middle() {
864        let tree = fixture_tree();
865
866        let mut it = Range::new(
867            &tree,
868            Bound::Included([126, 0, 0].as_slice()),
869            Bound::Included([128, 0, 0].as_slice()),
870        )
871        .map(|(k, _)| k);
872
873        assert_eq!(it.next().unwrap(), &[127, 127, 0]);
874        assert_eq!(it.next().unwrap(), &[127, 127, 127]);
875        assert_eq!(it.next().unwrap(), &[127, 127, u8::MAX]);
876        assert_eq!(it.next(), None);
877    }
878
879    #[test]
880    fn range_mut_mutate_some_keys() {
881        let mut tree = fixture_tree();
882
883        tree.values_mut().for_each(|value| *value = 0);
884
885        tree.range_mut([126, 0, 0]..=[128u8, 0, 0])
886            .for_each(|(_, value)| *value = 1024);
887
888        assert_eq!(
889            tree.into_iter().collect::<Vec<_>>(),
890            [
891                ([0, 0, 0], 0),
892                ([0, 0, 255], 0),
893                ([0, 255, 0], 0),
894                ([0, 255, 255], 0),
895                ([127, 127, 0], 1024),
896                ([127, 127, 127], 1024),
897                ([127, 127, 255], 1024),
898                ([255, 0, 0], 0),
899                ([255, 0, 255], 0),
900                ([255, 255, 0], 0),
901                ([255, 255, 255], 0)
902            ]
903        );
904    }
905
906    #[test]
907    fn lookup_on_tree_with_implicit_prefix_bytes() {
908        let mut tree = TreeMap::<_, _, 0>::with_prefix_len();
909
910        for (key, value) in generate_key_with_prefix(
911            [3, 3, 3],
912            [PrefixExpansion {
913                base_index: 0,
914                expanded_length: 4,
915            }],
916        )
917        .enumerate()
918        .map(swap)
919        {
920            let _ = tree.try_insert(key, value).unwrap();
921        }
922
923        assert_eq!(
924            tree.range(Box::from([0u8, 0, 0, 0, 0, 0])..Box::from([0u8, 0, 0, 0, 0, 4]))
925                .collect::<Vec<_>>(),
926            &[
927                (&[0, 0, 0, 0, 0, 0].into(), &0),
928                (&[0, 0, 0, 0, 0, 1].into(), &1),
929                (&[0, 0, 0, 0, 0, 2].into(), &2),
930                (&[0, 0, 0, 0, 0, 3].into(), &3)
931            ]
932        );
933
934        assert_eq!(
935            tree.range(Box::from([0u8, 0])..Box::from([0u8, 0, 0, 0, 0, 4]))
936                .collect::<Vec<_>>(),
937            &[
938                (&[0, 0, 0, 0, 0, 0].into(), &0),
939                (&[0, 0, 0, 0, 0, 1].into(), &1),
940                (&[0, 0, 0, 0, 0, 2].into(), &2),
941                (&[0, 0, 0, 0, 0, 3].into(), &3)
942            ]
943        );
944    }
945}