Skip to main content

indexmap/
util.rs

1use core::ops::{Bound, Range, RangeBounds};
2
3pub(crate) fn third<A, B, C>(t: (A, B, C)) -> C {
4    t.2
5}
6
7#[inline]
8#[track_caller]
9pub(crate) fn assert_index_lt(index: usize, len: usize) {
10    assert!(
11        index < len,
12        "index out of bounds: the len is {len} but the index is {index}",
13    );
14}
15
16#[inline]
17#[track_caller]
18pub(crate) fn assert_index_le(index: usize, len: usize) {
19    assert!(
20        index <= len,
21        "index out of bounds: the len is {len} but the index is {index}. Expected index <= len"
22    );
23}
24
25#[track_caller]
26pub(crate) fn simplify_range<R>(range: R, len: usize) -> Range<usize>
27where
28    R: RangeBounds<usize>,
29{
30    let start = match range.start_bound() {
31        Bound::Unbounded => 0,
32        Bound::Included(&i) if i <= len => i,
33        Bound::Excluded(&i) if i < len => i + 1,
34        Bound::Included(i) | Bound::Excluded(i) => {
35            panic!("range start index {i} out of range for slice of length {len}")
36        }
37    };
38    let end = match range.end_bound() {
39        Bound::Unbounded => len,
40        Bound::Excluded(&i) if i <= len => i,
41        Bound::Included(&i) if i < len => i + 1,
42        Bound::Included(i) | Bound::Excluded(i) => {
43            panic!("range end index {i} out of range for slice of length {len}")
44        }
45    };
46    if start > end {
47        panic!(
48            "range start index {:?} should be <= range end index {:?}",
49            range.start_bound(),
50            range.end_bound()
51        );
52    }
53    start..end
54}
55
56pub(crate) fn try_simplify_range<R>(range: R, len: usize) -> Option<Range<usize>>
57where
58    R: RangeBounds<usize>,
59{
60    let start = match range.start_bound() {
61        Bound::Unbounded => 0,
62        Bound::Included(&i) if i <= len => i,
63        Bound::Excluded(&i) if i < len => i + 1,
64        _ => return None,
65    };
66    let end = match range.end_bound() {
67        Bound::Unbounded => len,
68        Bound::Excluded(&i) if i <= len => i,
69        Bound::Included(&i) if i < len => i + 1,
70        _ => return None,
71    };
72    if start > end {
73        return None;
74    }
75    Some(start..end)
76}
77
78// Generic slice equality -- copied from the standard library but adding a custom comparator,
79// allowing for our `Bucket` wrapper on either or both sides.
80pub(crate) fn slice_eq<T, U>(left: &[T], right: &[U], eq: impl Fn(&T, &U) -> bool) -> bool {
81    if left.len() != right.len() {
82        return false;
83    }
84
85    // Implemented as explicit indexing rather
86    // than zipped iterators for performance reasons.
87    // See PR https://github.com/rust-lang/rust/pull/116846
88    for i in 0..left.len() {
89        // bound checks are optimized away
90        if !eq(&left[i], &right[i]) {
91            return false;
92        }
93    }
94
95    true
96}