pgm_extra/util/
range.rs

1use core::ops::{Bound, RangeBounds};
2
3/// Convert a start bound to an index using lower_bound/upper_bound.
4#[inline]
5pub fn start_bound_to_idx<K, F, G>(
6    bound: Bound<&K>,
7    len: usize,
8    lower_bound: F,
9    upper_bound: G,
10) -> usize
11where
12    F: Fn(&K) -> usize,
13    G: Fn(&K) -> usize,
14{
15    match bound {
16        Bound::Included(key) => lower_bound(key).min(len),
17        Bound::Excluded(key) => upper_bound(key).min(len),
18        Bound::Unbounded => 0,
19    }
20}
21
22/// Convert an end bound to an index using lower_bound/upper_bound.
23#[inline]
24pub fn end_bound_to_idx<K, F, G>(
25    bound: Bound<&K>,
26    len: usize,
27    lower_bound: F,
28    upper_bound: G,
29) -> usize
30where
31    F: Fn(&K) -> usize,
32    G: Fn(&K) -> usize,
33{
34    match bound {
35        Bound::Included(key) => upper_bound(key).min(len),
36        Bound::Excluded(key) => lower_bound(key).min(len),
37        Bound::Unbounded => len,
38    }
39}
40
41/// Compute the (start, end) indices for a range.
42#[inline]
43pub fn range_to_indices<K, R, F, G>(
44    range: R,
45    len: usize,
46    lower_bound: F,
47    upper_bound: G,
48) -> (usize, usize)
49where
50    R: RangeBounds<K>,
51    F: Fn(&K) -> usize + Copy,
52    G: Fn(&K) -> usize + Copy,
53{
54    let start = start_bound_to_idx(range.start_bound(), len, lower_bound, upper_bound);
55    let end = end_bound_to_idx(range.end_bound(), len, lower_bound, upper_bound);
56    (start, end.max(start))
57}