int_range_ext/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use core::fmt::Debug;
4use core::ops::{Add, Bound, RangeBounds, RangeInclusive, Sub};
5
6pub trait Integer
7where
8    Self: Copy + PartialOrd + Ord + Add<Output = Self> + Sub<Output = Self>,
9{
10    const ZERO: Self;
11    const ONE: Self;
12    const MAX: Self;
13    const MIN: Self;
14}
15
16macro_rules! impl_integers {
17    ($($ident: ident),*) => {
18        $(
19            impl Integer for $ident {
20                const ZERO: Self = 0;
21                const ONE: Self = 1;
22                const MAX: Self = $ident::MAX;
23                const MIN: Self = $ident::MIN;
24            }
25        )*
26    };
27}
28
29impl_integers!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
30
31#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
32pub enum Error {
33    EmptyRange,
34    SelfDoNotContainOtherRange,
35}
36
37impl core::fmt::Display for Error {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        let s = match self {
40            Error::EmptyRange => "empty range",
41            Error::SelfDoNotContainOtherRange => "self do not contain the other range",
42        };
43        f.write_str(s)
44    }
45}
46
47impl core::error::Error for Error {}
48
49#[allow(unused)]
50pub trait IntRangeExt<T: Integer>
51where
52    Self: RangeBounds<T>,
53{
54    /// Check if the range is empty
55    ///
56    /// ```
57    /// assert_eq!((0..0).is_empty(), true);
58    /// assert_eq!((0..1).is_empty(), false);
59    /// ```
60    fn is_empty(&self) -> bool;
61
62    /// `self` must not be empty
63    ///
64    /// ```
65    /// use int_range_ext::IntRangeExt;
66    ///
67    /// assert_eq!((0..10).to_inclusive(), Ok(0..=9));
68    /// assert!((0..0).to_inclusive().is_err());
69    /// ```
70    fn to_inclusive(&self) -> Result<RangeInclusive<T>, Error>;
71
72    /// Both `self` and `other` must not be empty
73    ///
74    /// ```
75    /// use int_range_ext::IntRangeExt;
76    ///
77    /// assert_eq!((0..10).contains_subrange(&(1..8)), Ok(true));
78    /// assert_eq!((0..10).contains_subrange(&(1..11)), Ok(false));
79    /// assert!((0..10).contains_subrange(&(11..11)).is_err());
80    /// ```
81    fn contains_subrange<Other: RangeBounds<T>>(&self, other: &Other) -> Result<bool, Error>;
82
83    /// ```
84    /// use int_range_ext::IntRangeExt;
85    ///
86    /// assert!((0..10).equal(&(0..=9)));
87    /// ```
88    fn equal<Other: RangeBounds<T>>(&self, other: &Other) -> bool;
89
90    /// `self` must contains_subrange `other`
91    ///
92    /// ```
93    /// use int_range_ext::IntRangeExt;
94    ///
95    /// assert_eq!((0..10).substract(&(4..=7)), Ok((Some(0..=3), Some(8..=9))));
96    /// assert_eq!((0..10).substract(&(0..=7)), Ok((None, Some(8..=9))));
97    /// assert!((0..10).substract(&(4..=11)).is_err());
98    /// ```
99    #[allow(clippy::type_complexity)]
100    fn substract<Other: RangeBounds<T>>(
101        &self,
102        other: &Other,
103    ) -> Result<(Option<RangeInclusive<T>>, Option<RangeInclusive<T>>), Error>;
104
105    /// Both `self` and `other` must not be empty
106    ///
107    /// ```
108    /// use int_range_ext::IntRangeExt;
109    ///
110    /// assert_eq!((0..10).intersect(&(0..=7)), Ok(true));
111    /// assert_eq!((0..10).intersect(&(4..=11)), Ok(true));
112    /// assert_eq!((0..10).intersect(&(10..20)), Ok(false));
113    /// assert!((0..10).intersect(&(10..10)).is_err());
114    /// ```
115    fn intersect<Other: RangeBounds<T>>(&self, other: &Other) -> Result<bool, Error>;
116}
117
118impl<T: Integer, U: RangeBounds<T>> IntRangeExt<T> for U {
119    fn is_empty(&self) -> bool {
120        match self.start_bound() {
121            Bound::Included(s) => {
122                match self.end_bound() {
123                    Bound::Included(e) => {
124                        // [s, e]
125                        s > e
126                    }
127                    Bound::Excluded(e) => {
128                        // [s, e)
129                        s >= e
130                    }
131                    Bound::Unbounded => {
132                        // [s..
133                        false
134                    }
135                }
136            }
137            Bound::Excluded(s) => {
138                match self.end_bound() {
139                    Bound::Included(e) => {
140                        // (s, e]
141                        s >= e
142                    }
143                    Bound::Excluded(e) => {
144                        // (s, e)
145                        !(s < e && *s + T::ONE < *e)
146                    }
147                    Bound::Unbounded => {
148                        // (s..
149                        *s >= T::MAX
150                    }
151                }
152            }
153            Bound::Unbounded => {
154                match self.end_bound() {
155                    Bound::Included(e) => {
156                        // ..=e
157                        T::MIN > *e
158                    }
159                    Bound::Excluded(e) => {
160                        // ..e
161                        T::MIN >= *e
162                    }
163                    Bound::Unbounded => {
164                        // ..
165                        false
166                    }
167                }
168            }
169        }
170    }
171
172    fn to_inclusive(&self) -> Result<RangeInclusive<T>, Error> {
173        if self.is_empty() {
174            return Err(Error::EmptyRange);
175        }
176
177        let s = match self.start_bound() {
178            Bound::Included(n) => *n,
179            Bound::Excluded(n) => *n + T::ONE,
180            Bound::Unbounded => T::MIN,
181        };
182
183        let e = match self.end_bound() {
184            Bound::Included(n) => *n,
185            Bound::Excluded(n) => *n - T::ONE,
186            Bound::Unbounded => T::MAX,
187        };
188
189        Ok(s..=e)
190    }
191
192    fn contains_subrange<Other: RangeBounds<T>>(&self, other: &Other) -> Result<bool, Error> {
193        if self.is_empty() || other.is_empty() {
194            return Err(Error::EmptyRange);
195        }
196
197        match other.start_bound() {
198            Bound::Included(n) => {
199                // [n..
200                if !self.contains(n) {
201                    return Ok(false);
202                }
203            }
204            Bound::Excluded(n) => {
205                // (n..
206                match self.start_bound() {
207                    Bound::Included(x) => {
208                        // (n..
209                        // [x..
210                        if x > n && *x > *n + T::ONE {
211                            return Ok(false);
212                        }
213                    }
214                    Bound::Excluded(x) => {
215                        // (n..
216                        // (x..
217                        if x > n {
218                            return Ok(false);
219                        }
220                    }
221                    Bound::Unbounded => {
222                        // (n..
223                        // ..
224                    }
225                }
226            }
227            Bound::Unbounded => match self.start_bound() {
228                Bound::Included(n) => {
229                    if *n != T::MIN {
230                        return Ok(false);
231                    }
232                }
233                Bound::Excluded(_) => {
234                    return Ok(false);
235                }
236                Bound::Unbounded => {}
237            },
238        }
239        match other.end_bound() {
240            Bound::Included(n) => {
241                // ..=n
242                if !self.contains(n) {
243                    return Ok(false);
244                }
245            }
246            Bound::Excluded(n) => {
247                // ..n
248                match self.end_bound() {
249                    Bound::Included(x) => {
250                        // ..n
251                        // ..=x
252                        if x < n && *x + T::ONE < *n {
253                            return Ok(false);
254                        }
255                    }
256                    Bound::Excluded(x) => {
257                        // ..n
258                        // ..x
259                        if x < n {
260                            return Ok(false);
261                        }
262                    }
263                    Bound::Unbounded => {}
264                }
265            }
266            Bound::Unbounded => {
267                // ..
268                match self.end_bound() {
269                    Bound::Included(n) => {
270                        if *n != T::MAX {
271                            return Ok(false);
272                        }
273                    }
274                    Bound::Excluded(_) => {
275                        return Ok(false);
276                    }
277                    Bound::Unbounded => {}
278                }
279            }
280        }
281
282        Ok(true)
283    }
284
285    fn equal<Other: RangeBounds<T>>(&self, other: &Other) -> bool {
286        self.contains_subrange(other).unwrap_or(false)
287            && other.contains_subrange(self).unwrap_or(false)
288    }
289
290    fn substract<Other: RangeBounds<T>>(
291        &self,
292        other: &Other,
293    ) -> Result<(Option<RangeInclusive<T>>, Option<RangeInclusive<T>>), Error> {
294        if !self.contains_subrange(other).unwrap_or(false) {
295            return Err(Error::SelfDoNotContainOtherRange);
296        }
297
298        // self.start .. other.start - 1
299        let r1 = match self.start_bound() {
300            Bound::Included(s) => {
301                match other.start_bound() {
302                    Bound::Included(e) => {
303                        if s < e {
304                            *s..=*e - T::ONE
305                        } else {
306                            T::ONE..=T::ZERO
307                        }
308                    }
309                    Bound::Excluded(e) => {
310                        // [s..
311                        // (e..
312                        *s..=*e
313                    }
314                    Bound::Unbounded => T::ONE..=T::ZERO,
315                }
316            }
317            Bound::Excluded(s) => {
318                // (s..
319                match other.start_bound() {
320                    Bound::Included(e) => {
321                        // (s..
322                        // [e..
323                        *s + T::ONE..=*e - T::ONE
324                    }
325                    Bound::Excluded(e) => {
326                        // (s..
327                        // (e..
328                        *s + T::ONE..=*e
329                    }
330                    Bound::Unbounded => T::ONE..=T::ZERO,
331                }
332            }
333            Bound::Unbounded => match other.start_bound() {
334                Bound::Included(e) => {
335                    if T::MIN < *e {
336                        T::MIN..=*e - T::ONE
337                    } else {
338                        T::ONE..=T::ZERO
339                    }
340                }
341                Bound::Excluded(e) => T::MIN..=*e,
342                Bound::Unbounded => T::ONE..=T::ZERO,
343            },
344        };
345
346        // other.end .. self.end
347        let r2 = match other.end_bound() {
348            Bound::Included(s) => {
349                if *s == T::MAX {
350                    T::ONE..=T::ZERO
351                } else {
352                    match self.end_bound() {
353                        Bound::Included(e) => *s + T::ONE..=*e,
354                        Bound::Excluded(e) => *s + T::ONE..=*e - T::ONE,
355                        Bound::Unbounded => *s + T::ONE..=T::MAX,
356                    }
357                }
358            }
359            Bound::Excluded(s) => match self.end_bound() {
360                Bound::Included(e) => *s..=*e,
361                Bound::Excluded(e) => *s..=*e - T::ONE,
362                Bound::Unbounded => *s..=T::MAX,
363            },
364            Bound::Unbounded => T::ONE..=T::ZERO,
365        };
366
367        let r1 = if r1.is_empty() { None } else { Some(r1) };
368
369        let r2 = if r2.is_empty() { None } else { Some(r2) };
370
371        Ok((r1, r2))
372    }
373
374    fn intersect<Other: RangeBounds<T>>(&self, other: &Other) -> Result<bool, Error> {
375        if self.is_empty() || other.is_empty() {
376            return Err(Error::EmptyRange);
377        }
378        if self.contains_subrange(other).unwrap_or(false)
379            || other.contains_subrange(self).unwrap_or(false)
380        {
381            return Ok(true);
382        }
383
384        //   -----
385        //      -----
386        let s = match self.start_bound() {
387            Bound::Included(n) => *n,
388            Bound::Excluded(n) => *n + T::ONE,
389            Bound::Unbounded => T::MIN,
390        };
391        let e = match self.end_bound() {
392            Bound::Included(n) => *n,
393            Bound::Excluded(n) => *n - T::ONE,
394            Bound::Unbounded => T::MAX,
395        };
396
397        Ok(other.contains(&s) || other.contains(&e))
398    }
399}
400
401// #[derive(Debug)]
402// pub struct RangeSubtracter<T> {
403//     vec: Vec<RangeInclusive<T>>,
404// }
405
406// impl<T: Integer> RangeSubtracter<T> {
407//     /// `range` must not be empty
408//     pub fn new(range: impl RangeBounds<T>) -> Result<Self, Error> {
409//         let r = range.to_inclusive()?;
410//         Ok(Self { vec: vec![r] })
411//     }
412
413//     pub fn is_empty(&self) -> bool {
414//         self.vec.is_empty()
415//     }
416
417//     pub fn substract(&mut self, other: &impl RangeBounds<T>) -> Result<(), ()> {
418//         let mut ret = Err(());
419
420//         let mut new_vec = Vec::new();
421//         for r in self.vec.iter() {
422//             match r.substract(other) {
423//                 Ok(ok) => {
424//                     match ok {
425//                         (Some(r1), Some(r2)) => {
426//                             new_vec.push(r1);
427//                             new_vec.push(r2);
428//                         }
429//                         (Some(r1), None) => {
430//                             new_vec.push(r1);
431//                         }
432//                         (None, Some(r2)) => {
433//                             new_vec.push(r2);
434//                         }
435//                         (None, None) => {}
436//                     }
437//                     ret = Ok(());
438//                 }
439//                 Err(_) => {
440//                     new_vec.push(r.clone());
441//                 }
442//             }
443//         }
444
445//         self.vec = new_vec;
446//         ret
447//     }
448// }
449
450#[cfg(test)]
451mod tests {
452    use super::*;
453
454    #[test]
455    fn empty() {
456        let r = 0..0;
457        assert_eq!(r.is_empty(), true);
458
459        let r = 0..=0;
460        assert_eq!(r.is_empty(), false);
461
462        let r = u8::MAX..u8::MAX;
463        assert_eq!(r.is_empty(), true);
464
465        let r = u8::MIN..u8::MIN;
466        assert_eq!(r.is_empty(), true);
467
468        let r = u8::MAX..u8::MIN;
469        assert_eq!(r.is_empty(), true);
470
471        let r = u8::MIN..u8::MAX;
472        assert_eq!(r.is_empty(), false);
473
474        assert_eq!((1..0).is_empty(), true);
475        assert_eq!((1..=0).is_empty(), true);
476
477        assert_eq!((..u8::MIN).is_empty(), true);
478        assert_eq!((u8::MAX..).is_empty(), false);
479    }
480
481    #[test]
482    fn to_inclusive() {
483        assert_eq!((..).to_inclusive(), Ok(u8::MIN..=u8::MAX));
484        assert_eq!((u8::MIN..).to_inclusive(), Ok(u8::MIN..=u8::MAX));
485        assert_eq!((..u8::MAX).to_inclusive(), Ok(u8::MIN..=u8::MAX - 1));
486        assert_eq!((..=u8::MAX).to_inclusive(), Ok(u8::MIN..=u8::MAX));
487        assert_eq!((10..20).to_inclusive(), Ok(10..=19));
488        assert_eq!((0..0).to_inclusive(), Err(Error::EmptyRange));
489    }
490
491    #[test]
492    fn contains_subrange() {
493        assert_eq!(
494            (u8::MIN..=u8::MAX).contains_subrange(&(..=u8::MAX)),
495            Ok(true)
496        );
497        assert_eq!(
498            (..=u8::MAX).contains_subrange(&(u8::MIN..=u8::MAX)),
499            Ok(true)
500        );
501        assert_eq!((u8::MIN..=u8::MAX).contains_subrange(&(..)), Ok(true));
502        assert_eq!((..).contains_subrange(&(u8::MIN..u8::MAX)), Ok(true));
503        assert_eq!((..).contains_subrange(&(u8::MIN..=u8::MAX)), Ok(true));
504
505        assert_eq!((..).contains_subrange(&(0..)), Ok(true));
506        assert_eq!((..).contains_subrange(&(..42)), Ok(true));
507        assert_eq!((..).contains_subrange(&(0..42)), Ok(true));
508        assert_eq!((..).contains_subrange(&(0..=42)), Ok(true));
509
510        assert_eq!((2..42).contains_subrange(&(2..42)), Ok(true));
511        assert_eq!((2..42).contains_subrange(&(3..42)), Ok(true));
512        assert_eq!((2..42).contains_subrange(&(3..41)), Ok(true));
513
514        assert_eq!((2..42).contains_subrange(&(2..=42)), Ok(false));
515        assert_eq!((2..42).contains_subrange(&(2..43)), Ok(false));
516        assert_eq!((2..42).contains_subrange(&(1..42)), Ok(false));
517        assert_eq!((2..42).contains_subrange(&(1..44)), Ok(false));
518
519        assert_eq!((2..u8::MAX).contains_subrange(&(2..u8::MAX)), Ok(true));
520        assert_eq!((2..u8::MAX).contains_subrange(&(2..=u8::MAX)), Ok(false));
521        assert_eq!((2..u8::MAX).contains_subrange(&(3..u8::MAX)), Ok(true));
522
523        assert_eq!((2..u8::MAX).contains_subrange(&(1..u8::MAX)), Ok(false));
524        assert_eq!((2..u8::MAX).contains_subrange(&(2..u8::MAX - 1)), Ok(true));
525        assert_eq!((2..u8::MAX).contains_subrange(&(2..=u8::MAX - 1)), Ok(true));
526
527        assert_eq!((2..=u8::MAX).contains_subrange(&(2..u8::MAX)), Ok(true));
528        assert_eq!((2..=u8::MAX).contains_subrange(&(2..=u8::MAX)), Ok(true));
529
530        assert_eq!((2..=u8::MAX - 1).contains_subrange(&(2..u8::MAX)), Ok(true));
531        assert_eq!(
532            (2..=u8::MAX - 1).contains_subrange(&(2..=u8::MAX)),
533            Ok(false)
534        );
535
536        assert_eq!((0..10).contains_subrange(&(0..0)), Err(Error::EmptyRange));
537        assert_eq!((0..0).contains_subrange(&(0..10)), Err(Error::EmptyRange));
538        assert_eq!((0..0).contains_subrange(&(0..0)), Err(Error::EmptyRange));
539    }
540
541    #[test]
542    fn equal() {
543        assert_eq!((0..100).equal(&(0..=99)), true);
544        assert_eq!((0u8..).equal(&(0..=u8::MAX)), true);
545        assert_eq!((..).equal(&(0..=u8::MAX)), true);
546        assert_eq!((..).equal(&(u8::MIN..=u8::MAX)), true);
547        assert_eq!((..).equal(&(u8::MIN..u8::MAX)), false);
548        assert_eq!((0..=u8::MAX).equal(&(..)), true);
549    }
550
551    #[test]
552    fn sub() {
553        assert_eq!((..).substract(&(u8::MIN..=u8::MAX)), Ok((None, None)));
554        assert_eq!((u8::MIN..=u8::MAX).substract(&(..)), Ok((None, None)));
555        assert_eq!(
556            (..).substract(&(u8::MIN..u8::MAX)),
557            Ok((None, Some(255..=255u8)))
558        );
559        assert_eq!(
560            (..=u8::MAX).substract(&(u8::MIN..u8::MAX)),
561            Ok((None, Some(255..=255u8)))
562        );
563        assert_eq!(
564            (..=u8::MAX).substract(&(..u8::MAX)),
565            Ok((None, Some(255..=255u8)))
566        );
567        assert_eq!(
568            (..=u8::MAX).substract(&(1..u8::MAX)),
569            Ok((Some(0..=0), Some(255..=255u8)))
570        );
571
572        assert_eq!(
573            (0..100).substract(&(30..50)),
574            Ok((Some(0..=29), Some(50..=99)))
575        );
576        assert_eq!((0..100).substract(&(30..100)), Ok((Some(0..=29), None)));
577        assert_eq!((0..100).substract(&(0..50)), Ok((None, Some(50..=99))));
578
579        assert_eq!(
580            (20..40).substract(&(30..50)),
581            Err(Error::SelfDoNotContainOtherRange)
582        );
583    }
584
585    #[test]
586    fn intersect() {
587        assert_eq!((0..50).intersect(&(50..100)), Ok(false));
588        assert_eq!((0..=50).intersect(&(50..100)), Ok(true));
589    }
590
591    // #[test]
592    // fn range_sub() {
593    //     let mut r = RangeSubtracter::new(0..100).unwrap();
594    //     r.substract(&(3..5)).unwrap();
595    //     assert_eq!(r.vec, vec![0..=2, 5..=99]);
596    //     r.substract(&(10..20)).unwrap();
597    //     assert_eq!(r.vec, vec![0..=2, 5..=9, 20..=99]);
598    //     r.substract(&(0..2)).unwrap();
599    //     assert_eq!(r.vec, vec![2..=2, 5..=9, 20..=99]);
600
601    //     let mut r = RangeSubtracter::new(..100u8).unwrap();
602    //     r.substract(&(..5)).unwrap();
603    //     assert_eq!(r.vec, vec![5..=99]);
604
605    //     let mut r = RangeSubtracter::new(..100u8).unwrap();
606    //     r.substract(&(u8::MIN..5)).unwrap();
607    //     assert_eq!(r.vec, vec![5..=99]);
608
609    //     let mut r = RangeSubtracter::new(..).unwrap();
610    //     r.substract(&(u8::MIN..5)).unwrap();
611    //     assert_eq!(r.vec, vec![5..=u8::MAX]);
612
613    //     let mut r = RangeSubtracter::new(..).unwrap();
614    //     r.substract(&(u8::MIN..=255)).unwrap();
615    //     assert_eq!(r.vec, vec![]);
616    // }
617}