ranges/generic_range/
union.rs1use core::ops::BitOr;
2
3use crate::{Arrangement, Domain, GenericRange, OperationResult};
4
5impl<T: Domain> GenericRange<T> {
6 pub fn union(self, other: Self) -> OperationResult<T> {
28 match self.arrangement(&other) {
31 Arrangement::Disjoint { self_less: true } => OperationResult::Double(self, other),
32 Arrangement::Disjoint { self_less: false } => OperationResult::Double(other, self),
33 Arrangement::Touching { self_less: true } | Arrangement::Overlapping { self_less: true, .. } => {
34 OperationResult::Single(Self {
35 start: self.start,
36 end: other.end,
37 })
38 }
39 Arrangement::Touching { self_less: false } | Arrangement::Overlapping { self_less: false, .. } => {
40 OperationResult::Single(Self {
41 start: other.start,
42 end: self.end,
43 })
44 }
45 Arrangement::Containing { self_shorter: false }
46 | Arrangement::Starting {
47 self_shorter: false, ..
48 }
49 | Arrangement::Ending {
50 self_shorter: false, ..
51 }
52 | Arrangement::Equal
53 | Arrangement::Empty {
54 self_empty: Some(false),
55 } => OperationResult::Single(self),
56 Arrangement::Containing { self_shorter: true }
57 | Arrangement::Starting { self_shorter: true, .. }
58 | Arrangement::Ending { self_shorter: true, .. }
59 | Arrangement::Empty { self_empty: Some(true) } => OperationResult::Single(other),
60 Arrangement::Empty { self_empty: None } => OperationResult::Empty,
61 }
62 }
63}
64
65impl<T, I> BitOr<I> for GenericRange<T>
67where
68 I: Into<GenericRange<T>>,
69 T: Domain,
70{
71 type Output = OperationResult<T>;
72
73 #[must_use]
74 fn bitor(self, rhs: I) -> Self::Output {
75 self.union(rhs.into())
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use crate::{GenericRange, OperationResult};
82
83 #[test]
84 fn disjoint() {
85 let range = GenericRange::new_less_than(5);
86 let range2 = GenericRange::new_at_least(10);
87
88 assert_eq!(range.union(range2), OperationResult::Double(range, range2));
89 assert_eq!(range2.union(range), OperationResult::Double(range, range2));
90
91 assert_eq!(range | range2, OperationResult::Double(range, range2));
92 assert_eq!(range2 | range, OperationResult::Double(range, range2));
93 }
94
95 #[test]
96 fn touching() {
97 let range = GenericRange::from(0..10);
98 let range2 = GenericRange::from(10..=20);
99
100 assert_eq!(range.union(range2), OperationResult::Single(GenericRange::from(0..=20)));
101 assert_eq!(range2.union(range), OperationResult::Single(GenericRange::from(0..=20)));
102
103 assert_eq!(range | range2, OperationResult::Single(GenericRange::from(0..=20)));
104 assert_eq!(range2 | range, OperationResult::Single(GenericRange::from(0..=20)));
105 }
106
107 #[test]
108 fn overlapping() {
109 let range = GenericRange::from(0..10);
110 let range2 = GenericRange::from(5..=15);
111
112 assert_eq!(range.union(range2), OperationResult::Single(GenericRange::from(0..=15)));
113 assert_eq!(range2.union(range), OperationResult::Single(GenericRange::from(0..=15)));
114
115 assert_eq!(range | range2, OperationResult::Single(GenericRange::from(0..=15)));
116 assert_eq!(range2 | range, OperationResult::Single(GenericRange::from(0..=15)));
117 }
118
119 #[test]
120 fn containing() {
121 let range = GenericRange::from(0..10);
122 let range2 = GenericRange::from(5..=8);
123
124 assert_eq!(range.union(range2), OperationResult::Single(range));
125 assert_eq!(range2.union(range), OperationResult::Single(range));
126
127 assert_eq!(range | range2, OperationResult::Single(range));
128 assert_eq!(range2 | range, OperationResult::Single(range));
129 }
130
131 #[test]
132 fn starting() {
133 let range = GenericRange::from(0..10);
134 let range2 = GenericRange::from(0..=8);
135
136 assert_eq!(range.union(range2), OperationResult::Single(range));
137 assert_eq!(range2.union(range), OperationResult::Single(range));
138
139 assert_eq!(range | range2, OperationResult::Single(range));
140 assert_eq!(range2 | range, OperationResult::Single(range));
141 }
142
143 #[test]
144 fn ending() {
145 let range = GenericRange::from(3..=10);
146 let range2 = GenericRange::from(5..=10);
147
148 assert_eq!(range.union(range2), OperationResult::Single(range));
149 assert_eq!(range2.union(range), OperationResult::Single(range));
150
151 assert_eq!(range | range2, OperationResult::Single(range));
152 assert_eq!(range2 | range, OperationResult::Single(range));
153 }
154
155 #[test]
156 fn equal() {
157 let range = GenericRange::from(5..=10);
158 let range2 = range;
159
160 assert_eq!(range.union(range2), OperationResult::Single(range));
161 assert_eq!(range2.union(range), OperationResult::Single(range));
162
163 assert_eq!(range | range2, OperationResult::Single(range));
164 assert_eq!(range2 | range, OperationResult::Single(range));
165 }
166}