willow_data_model/grouping/
range.rs1use core::cmp;
2use core::cmp::Ordering;
3
4#[cfg(feature = "dev")]
5use arbitrary::{Arbitrary, Error as ArbitraryError};
6
7use crate::path::Path;
8
9#[derive(Debug, PartialEq, Eq)]
10pub enum RangeEnd<T: Ord> {
12 Closed(T),
14 Open,
16}
17
18impl<T: Ord> RangeEnd<T> {
19 pub fn gt_val(&self, val: &T) -> bool {
21 match self {
22 RangeEnd::Open => true,
23 RangeEnd::Closed(end_val) => end_val > val,
24 }
25 }
26}
27
28impl From<&RangeEnd<u64>> for u64 {
29 fn from(value: &RangeEnd<u64>) -> Self {
30 match value {
31 RangeEnd::Closed(val) => *val,
32 RangeEnd::Open => u64::MAX,
33 }
34 }
35}
36
37impl<T: Ord> Ord for RangeEnd<T> {
38 fn cmp(&self, other: &Self) -> Ordering {
39 match self {
40 RangeEnd::Closed(end_value) => match other {
41 RangeEnd::Closed(other_end_value) => end_value.cmp(other_end_value),
42 RangeEnd::Open => Ordering::Less,
43 },
44 RangeEnd::Open => match other {
45 RangeEnd::Closed(_) => Ordering::Greater,
46 RangeEnd::Open => Ordering::Equal,
47 },
48 }
49 }
50}
51
52impl<T: Ord> PartialOrd for RangeEnd<T> {
53 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
54 Some(self.cmp(other))
55 }
56}
57
58impl<T> PartialEq<T> for RangeEnd<T>
59where
60 T: Eq + Ord,
61{
62 fn eq(&self, other: &T) -> bool {
63 match self {
64 RangeEnd::Closed(val) => val.eq(other),
65 RangeEnd::Open => false,
66 }
67 }
68}
69
70impl<T> PartialOrd<T> for RangeEnd<T>
71where
72 T: Ord,
73{
74 fn partial_cmp(&self, other: &T) -> Option<Ordering> {
75 match self {
76 RangeEnd::Closed(val) => val.partial_cmp(other),
77 RangeEnd::Open => Some(Ordering::Greater),
78 }
79 }
80}
81
82impl PartialEq<RangeEnd<u64>> for u64 {
83 fn eq(&self, other: &RangeEnd<u64>) -> bool {
84 match other {
85 RangeEnd::Closed(other_val) => self.eq(other_val),
86 RangeEnd::Open => false,
87 }
88 }
89}
90
91impl PartialOrd<RangeEnd<u64>> for u64 {
92 fn partial_cmp(&self, other: &RangeEnd<u64>) -> Option<Ordering> {
93 match other {
94 RangeEnd::Closed(other_val) => self.partial_cmp(other_val),
95 RangeEnd::Open => Some(Ordering::Less),
96 }
97 }
98}
99
100impl<const MCL: usize, const MCC: usize, const MPL: usize> PartialEq<RangeEnd<Path<MCL, MCC, MPL>>>
101 for Path<MCL, MCC, MPL>
102{
103 fn eq(&self, other: &RangeEnd<Path<MCL, MCC, MPL>>) -> bool {
104 match other {
105 RangeEnd::Closed(other_path) => self.eq(other_path),
106 RangeEnd::Open => false,
107 }
108 }
109}
110
111impl<const MCL: usize, const MCC: usize, const MPL: usize> PartialOrd<RangeEnd<Path<MCL, MCC, MPL>>>
112 for Path<MCL, MCC, MPL>
113{
114 fn partial_cmp(&self, other: &RangeEnd<Path<MCL, MCC, MPL>>) -> Option<Ordering> {
115 match other {
116 RangeEnd::Closed(other_path) => self.partial_cmp(other_path),
117 RangeEnd::Open => Some(Ordering::Less),
118 }
119 }
120}
121
122impl<T> Clone for RangeEnd<T>
123where
124 T: Ord + Clone,
125{
126 fn clone(&self) -> Self {
127 match self {
128 RangeEnd::Closed(val) => RangeEnd::Closed(val.clone()),
129 RangeEnd::Open => RangeEnd::Open,
130 }
131 }
132}
133
134#[cfg(feature = "dev")]
135impl<'a, T> Arbitrary<'a> for RangeEnd<T>
136where
137 T: Arbitrary<'a> + Ord,
138{
139 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
140 let is_open: bool = Arbitrary::arbitrary(u)?;
141
142 if !is_open {
143 let value: T = Arbitrary::arbitrary(u)?;
144
145 return Ok(Self::Closed(value));
146 }
147
148 Ok(Self::Open)
149 }
150}
151
152#[derive(Debug, PartialEq, Eq)]
156pub struct Range<T: Ord> {
157 pub start: T,
159 pub end: RangeEnd<T>,
161}
162
163impl<T> Range<T>
164where
165 T: Ord + Clone,
166{
167 pub fn new_open(start: T) -> Self {
169 Self {
170 start,
171 end: RangeEnd::Open,
172 }
173 }
174
175 pub fn new_closed(start: T, end: T) -> Option<Self> {
177 if start < end {
178 return Some(Self {
179 start,
180 end: RangeEnd::Closed(end),
181 });
182 }
183
184 None
185 }
186
187 pub fn includes(&self, value: &T) -> bool {
189 &self.start <= value && self.end.gt_val(value)
190 }
191
192 pub fn includes_range(&self, other: &Range<T>) -> bool {
194 self.start <= other.start && self.end >= other.end
195 }
196
197 pub fn intersection(&self, other: &Self) -> Option<Self> {
199 let start = cmp::max(&self.start, &other.start);
200 let end = match (&self.end, &other.end) {
201 (RangeEnd::Open, RangeEnd::Closed(b)) => RangeEnd::Closed(b),
202 (RangeEnd::Closed(a), RangeEnd::Closed(b)) => RangeEnd::Closed(a.min(b)),
203 (RangeEnd::Closed(a), RangeEnd::Open) => RangeEnd::Closed(a),
204 (RangeEnd::Open, RangeEnd::Open) => RangeEnd::Open,
205 };
206 match end {
207 RangeEnd::Open => Some(Self::new_open(start.clone())),
208 RangeEnd::Closed(t) if t >= start => {
209 Some(Self::new_closed(start.clone(), t.clone()).unwrap())
210 }
211 RangeEnd::Closed(_) => None,
212 }
213 }
214}
215
216impl<T: Default> Range<T>
217where
218 T: Ord + Clone,
219{
220 pub fn full() -> Self {
222 Self::new_open(T::default())
223 }
224}
225
226impl<T: Default> Default for Range<T>
227where
228 T: Ord + Clone,
229{
230 fn default() -> Self {
231 Self::full()
232 }
233}
234
235impl<T: Ord> Ord for Range<T> {
236 fn cmp(&self, other: &Self) -> Ordering {
237 match self.start.cmp(&other.start) {
238 Ordering::Less => Ordering::Less,
239 Ordering::Equal => Ordering::Equal,
240 Ordering::Greater => self.end.cmp(&other.end),
241 }
242 }
243}
244
245impl<T: Ord> PartialOrd for Range<T> {
246 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
247 Some(self.cmp(other))
248 }
249}
250
251impl<T> Clone for Range<T>
252where
253 T: Ord + Clone,
254{
255 fn clone(&self) -> Self {
256 Self {
257 start: self.start.clone(),
258 end: self.end.clone(),
259 }
260 }
261}
262
263#[cfg(feature = "dev")]
264impl<'a, T> Arbitrary<'a> for Range<T>
265where
266 T: Arbitrary<'a> + Ord,
267{
268 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
269 let start: T = Arbitrary::arbitrary(u)?;
270 let end: RangeEnd<T> = Arbitrary::arbitrary(u)?;
271
272 if !end.gt_val(&start) {
273 return Err(ArbitraryError::IncorrectFormat);
274 }
275
276 Ok(Self { start, end })
277 }
278}
279
280#[cfg(test)]
281mod tests {
282 use super::*;
283
284 #[test]
287 fn range_end_ord() {
288 assert!(RangeEnd::Closed(0) == RangeEnd::Closed(0));
289 assert!(RangeEnd::Closed(1) < RangeEnd::Closed(2));
290 assert!(RangeEnd::Closed(100) < RangeEnd::Open);
291 assert!(RangeEnd::<usize>::Open == RangeEnd::Open);
292 }
293
294 #[test]
297 fn range_new_closed() {
298 assert!(Range::new_closed(0, 0).is_none());
299 assert!(Range::new_closed(2, 1).is_none());
300 assert!(Range::new_closed(5, 10).is_some());
301 }
302
303 #[test]
304 fn range_includes() {
305 let open_range = Range::new_open(20);
306
307 assert!(open_range.includes(&20));
308 assert!(open_range.includes(&30));
309 assert!(!open_range.includes(&10));
310
311 let closed_range = Range::new_closed(5, 10).unwrap();
312
313 assert!(closed_range.includes(&5));
314 assert!(closed_range.includes(&8));
315 assert!(!closed_range.includes(&1));
316 }
317
318 #[test]
319 fn range_includes_range() {
320 let open_range = Range::new_open(0);
321 let open_range_2 = Range::new_open(2);
322
323 assert!(open_range.includes_range(&open_range_2));
324 assert!(!open_range_2.includes_range(&open_range));
325
326 let closed_range = Range::new_closed(0, 10).unwrap();
327 let closed_range_2 = Range::new_closed(5, 10).unwrap();
328 let closed_range_3 = Range::new_closed(5, 15).unwrap();
329
330 assert!(closed_range.includes_range(&closed_range_2));
331 assert!(!closed_range_2.includes_range(&closed_range));
332 assert!(!closed_range.includes_range(&closed_range_3));
333
334 assert!(open_range.includes_range(&closed_range));
335 assert!(!closed_range.includes_range(&open_range_2));
336 }
337
338 #[test]
339 fn range_intersection() {
340 let closed_1 = Range::new_closed(0, 10).unwrap();
341 let closed_2 = Range::new_closed(5, 15).unwrap();
342
343 let intersection_1 = closed_1.intersection(&closed_2);
344
345 assert!(intersection_1.is_some());
346 assert_eq!(intersection_1.unwrap(), Range::new_closed(5, 10).unwrap());
347
348 let open_1 = Range::new_open(5);
349
350 let intersection_2 = open_1.intersection(&closed_1);
351
352 assert!(intersection_2.is_some());
353 assert_eq!(intersection_2.unwrap(), Range::new_closed(5, 10).unwrap());
354
355 let closed_3 = Range::new_closed(20, 25).unwrap();
356
357 let intersection_3 = closed_3.intersection(&closed_1);
358
359 assert!(intersection_3.is_none());
360
361 let open_2 = Range::new_open(50);
362
363 let intersection_4 = closed_3.intersection(&open_2);
364
365 assert!(intersection_4.is_none())
366 }
367}