exocore_core/utils/
range.rs1use std::ops::Range;
2
3pub fn are_continuous<'a, I, T: 'a + Ord + Copy + Eq>(iter: I) -> bool
4where
5 I: Iterator<Item = &'a Range<T>>,
6{
7 get_gaps(iter).is_empty()
8}
9
10pub fn get_gaps<'a, I, T: 'a + Ord + Copy + Eq>(iter: I) -> Vec<Range<T>>
11where
12 I: Iterator<Item = &'a Range<T>>,
13{
14 let mut sorted: Vec<&Range<T>> = iter.collect();
15 sorted.sort_by(|a, b| a.start.partial_cmp(&b.start).unwrap());
16
17 let mut gaps = Vec::new();
18 for i in 1..sorted.len() {
19 let left = &sorted[i - 1];
20 let right = &sorted[i];
21 if left.end != right.start {
22 gaps.push(Range {
23 start: left.end,
24 end: right.start,
25 });
26 }
27 }
28
29 gaps
30}
31
32#[cfg(test)]
33mod test {
34 use super::*;
35
36 #[test]
37 fn test_find_gaps() {
38 let r1 = 10..20;
39 let r2 = 30..40;
40 let r3 = 40..50;
41 let r4 = 80..100;
42
43 let ranges = [r2, r1, r4, r3];
44 let gaps = get_gaps(ranges.iter());
45 assert_eq!(gaps, vec![20..30, 50..80]);
46 assert!(!are_continuous(ranges.iter()));
47
48 let r5 = 30..40;
49 let r6 = 40..50;
50 let ranges = [r5, r6];
51 assert!(are_continuous(ranges.iter()));
52 }
53}