Skip to main content

tree_table/utils/
consecutive_ranges.rs

1/// Iterator of tuples (usize, usize) from an iterable of sorted positive usize.
2/// Each yielded tuple is a (start_inclusive, end_inclusive) of a consecutive range.
3pub struct ConsecutiveRangesBorrowed<'a, I>
4where
5    I: Iterator<Item = &'a usize>,
6{
7    iter: I,
8    start: Option<usize>,
9    prev: Option<usize>,
10}
11
12impl<'a, I> Iterator for ConsecutiveRangesBorrowed<'a, I>
13where
14    I: Iterator<Item = &'a usize>,
15{
16    type Item = (usize, usize); // (start, end_inclusive)
17
18    fn next(&mut self) -> Option<Self::Item> {
19        let (current_start, mut current_prev) = match (self.start, self.prev) {
20            (Some(start), Some(prev)) => (start, prev),
21            (None, None) => {
22                if let Some(&first) = self.iter.next() {
23                    self.start = Some(first);
24                    self.prev = Some(first);
25                    (first, first)
26                } else {
27                    return None;
28                }
29            }
30            _ => unreachable!("start and prev should both be Some or both be None"),
31        };
32
33        loop {
34            match self.iter.next() {
35                Some(&curr) => {
36                    if curr > current_prev + 1 {
37                        // Gap found → return inclusive range
38                        let range = (current_start, current_prev);
39                        self.start = Some(curr);
40                        self.prev = Some(curr);
41                        return Some(range);
42                    } else {
43                        current_prev = curr;
44                        self.prev = Some(curr);
45                    }
46                }
47                None => {
48                    // End of iterator → return final inclusive range
49                    let range = (current_start, current_prev);
50                    self.start = None;
51                    self.prev = None;
52                    return Some(range);
53                }
54            }
55        }
56    }
57}
58
59pub fn consecutive_ranges_borrowed<'a, I>(iter: I) -> ConsecutiveRangesBorrowed<'a, I>
60where
61    I: Iterator<Item = &'a usize>,
62{
63    ConsecutiveRangesBorrowed {
64        iter,
65        start: None,
66        prev: None,
67    }
68}
69
70/// Iterator of tuples (usize, usize) from an iterable of sorted positive usize.
71/// Each yielded tuple is a (start_inclusive, end_inclusive) of a consecutive range.
72pub struct ConsecutiveRangesOwned<I>
73where
74    I: Iterator<Item = usize>,
75{
76    iter: I,
77    start: Option<usize>,
78    prev: Option<usize>,
79}
80
81impl<I> Iterator for ConsecutiveRangesOwned<I>
82where
83    I: Iterator<Item = usize>,
84{
85    type Item = (usize, usize); // (start, end_inclusive)
86
87    fn next(&mut self) -> Option<Self::Item> {
88        let (current_start, mut current_prev) = match (self.start, self.prev) {
89            (Some(start), Some(prev)) => (start, prev),
90            (None, None) => {
91                if let Some(first) = self.iter.next() {
92                    self.start = Some(first);
93                    self.prev = Some(first);
94                    (first, first)
95                } else {
96                    return None;
97                }
98            }
99            _ => unreachable!("start and prev should both be Some or both be None"),
100        };
101
102        loop {
103            match self.iter.next() {
104                Some(curr) => {
105                    if curr > current_prev + 1 {
106                        let range = (current_start, current_prev); // inclusive
107                        self.start = Some(curr);
108                        self.prev = Some(curr);
109                        return Some(range);
110                    } else {
111                        current_prev = curr;
112                        self.prev = Some(curr);
113                    }
114                }
115                None => {
116                    let range = (current_start, current_prev); // inclusive
117                    self.start = None;
118                    self.prev = None;
119                    return Some(range);
120                }
121            }
122        }
123    }
124}
125
126pub fn consecutive_ranges_owned<I>(iter: I) -> ConsecutiveRangesOwned<I>
127where
128    I: Iterator<Item = usize>,
129{
130    ConsecutiveRangesOwned {
131        iter,
132        start: None,
133        prev: None,
134    }
135}