1use std::ops::{self, RangeBounds};
4
5#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
7pub struct Range<T = usize> {
8 pub start: T,
9 pub end: T,
10}
11
12impl<T: PartialOrd> Range<T> {
13 pub fn contains(&self, other: Self) -> bool {
14 self.start <= other.start && other.end <= self.end
15 }
16 pub fn is_empty(&self) -> bool {
17 self.end <= self.start
18 }
19}
20
21impl<T> RangeBounds<T> for Range<T> {
22 fn start_bound(&self) -> ops::Bound<&T> {
23 ops::Bound::Included(&self.start)
24 }
25
26 fn end_bound(&self) -> ops::Bound<&T> {
27 ops::Bound::Excluded(&self.end)
28 }
29}
30
31pub fn is_subset<const ALLOW_EMPTY: bool>(
40 mut super_set: impl Iterator<Item = Range>,
41 mut sub_set: impl Iterator<Item = Range>,
42) -> bool {
43 let (mut super_range, mut sub_range) = (super_set.next(), sub_set.next());
44 loop {
45 match (super_range, sub_range) {
46 (Some(ra), Some(rb))
48 if ra.end <= rb.start && (ra.start != rb.start || !ALLOW_EMPTY) =>
49 {
50 super_range = super_set.next();
51 }
52 (Some(ra), Some(rb)) => {
53 if ra.contains(rb) {
54 sub_range = sub_set.next();
55 } else {
56 return false;
57 }
58 }
59 (None, Some(_)) => {
60 return false;
62 }
63 (_, None) => {
64 return true;
66 }
67 }
68 }
69}
70
71pub fn is_exact_subset(
73 mut super_set: impl Iterator<Item = Range>,
74 mut sub_set: impl Iterator<Item = Range>,
75) -> bool {
76 let (mut super_range, mut sub_range) = (super_set.next(), sub_set.next());
77 let mut super_range_matched = true;
78 loop {
79 match (super_range, sub_range) {
80 (Some(ra), Some(rb)) if ra.end <= rb.start && ra.start < rb.start => {
82 if !super_range_matched {
83 return false;
84 }
85 super_range_matched = false;
86 super_range = super_set.next();
87 }
88 (Some(ra), Some(rb)) => {
89 if ra.contains(rb) {
90 super_range_matched = true;
91 sub_range = sub_set.next();
92 } else {
93 return false;
94 }
95 }
96 (None, Some(_)) => {
97 return false;
99 }
100 (_, None) => {
101 return super_set.next().is_none();
103 }
104 }
105 }
106}