1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
use std::ops::{
    Bound::*, Range, RangeBounds, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
};

/// Into inclusive start and exclusive end indices.
/// 
/// Used for range query and range update in [`SegTree`](crate::SegTree) and [`LazySegTree`](crate::LazySegTree).
pub trait IntoIndex {
    /// Computes index from [`RangeBounds`]. The parameter `size` is the size of the full range.
    fn into_index(self, size: usize) -> (usize, usize);
}

macro_rules! into_index_impl {
    ($($range:ty)*) => {
        $(
            impl IntoIndex for $range {
                fn into_index(self, size: usize) -> (usize, usize) {
                    into_index(self, size)
                }
            }
        )*
    };
}

into_index_impl! { Range<usize> RangeFrom<usize> RangeInclusive<usize> RangeToInclusive<usize>
RangeTo<usize> RangeFull }

impl IntoIndex for usize {
    fn into_index(self, _: usize) -> (usize, usize) {
        (self, self + 1)
    }
}

// TODO(yujingaya) Be defensive with some assertion
pub fn into_index<R: RangeBounds<usize>>(range: R, size: usize) -> (usize, usize) {
    (
        match range.start_bound() {
            Included(&start) => start,
            Excluded(&start) => start + 1,
            Unbounded => 0,
        },
        match range.end_bound() {
            Included(&end) => end + 1,
            Excluded(&end) => end,
            Unbounded => size,
        },
    )
}