ranges/generic_range/
difference.rs

1use core::ops::Sub;
2
3use crate::{Arrangement, Domain, GenericRange, OperationResult};
4
5impl<T: Domain> GenericRange<T> {
6    /// Returns the difference of two ranges.
7    ///
8    /// # Examples
9    ///```
10    /// use ranges::{GenericRange, OperationResult};
11    ///
12    /// let range = GenericRange::from(1..=5);
13    /// let range2 = range;
14    /// assert_eq!(range - range2, OperationResult::Empty);
15    ///```
16    ///```
17    /// use ranges::{GenericRange, OperationResult};
18    ///
19    /// let range = GenericRange::from(1..=5);
20    /// let range2 = 1..3;
21    /// assert_eq!(range - range2, OperationResult::Single((3..=5).into()));
22    ///```
23    ///```
24    /// use ranges::{GenericRange, OperationResult};
25    ///
26    /// let range = GenericRange::from(1..=10);
27    /// let range2 = 3..5;
28    /// assert_eq!(range - range2, OperationResult::Double((1..3).into(), (5..=10).into()));
29    ///```
30    pub fn difference(self, other: Self) -> OperationResult<T> {
31        match self.arrangement(&other) {
32            Arrangement::Disjoint { .. } | Arrangement::Touching { .. } => OperationResult::Single(self),
33            Arrangement::Overlapping { self_less: true, .. }
34            | Arrangement::Ending {
35                self_shorter: false, ..
36            } => OperationResult::Single(Self {
37                start: self.start,
38                end: Self::invert_border(other.start),
39            }),
40            Arrangement::Overlapping { self_less: false, .. }
41            | Arrangement::Starting {
42                self_shorter: false, ..
43            } => OperationResult::Single(Self {
44                start: Self::invert_border(other.end),
45                end: self.end,
46            }),
47            Arrangement::Containing { self_shorter: true }
48            | Arrangement::Starting { self_shorter: true, .. }
49            | Arrangement::Ending { self_shorter: true, .. }
50            | Arrangement::Equal => OperationResult::Empty,
51            Arrangement::Containing { self_shorter: false } => OperationResult::Double(
52                Self {
53                    start: self.start,
54                    end: Self::invert_border(other.start),
55                },
56                Self {
57                    start: Self::invert_border(other.end),
58                    end: self.end,
59                },
60            ),
61            Arrangement::Empty {
62                self_empty: Some(true) | None,
63            } => {
64                // ∅ \ A = ∅
65                OperationResult::Empty
66            }
67            Arrangement::Empty {
68                self_empty: Some(false),
69            } => {
70                // A \ ∅ = A
71                OperationResult::Single(self)
72            }
73        }
74    }
75}
76
77/// This calls [`self.difference(other)`](#method.difference).
78impl<T, I> Sub<I> for GenericRange<T>
79where
80    I: Into<GenericRange<T>>,
81    T: Domain,
82{
83    type Output = OperationResult<T>;
84
85    #[must_use]
86    fn sub(self, rhs: I) -> Self::Output {
87        self.difference(rhs.into())
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use crate::{GenericRange, OperationResult};
94
95    #[test]
96    fn disjoint() {
97        let range = GenericRange::new_less_than(5);
98        let range2 = GenericRange::new_at_least(10);
99
100        assert_eq!(range.difference(range2), OperationResult::Single(range));
101        assert_eq!(range2.difference(range), OperationResult::Single(range2));
102
103        assert_eq!(range - range2, OperationResult::Single(range));
104        assert_eq!(range2 - range, OperationResult::Single(range2));
105    }
106
107    #[test]
108    fn touching() {
109        let range = GenericRange::from(0..10);
110        let range2 = GenericRange::from(10..=20);
111
112        assert_eq!(range.difference(range2), OperationResult::Single(range));
113        assert_eq!(range2.difference(range), OperationResult::Single(range2));
114
115        assert_eq!(range - range2, OperationResult::Single(range));
116        assert_eq!(range2 - range, OperationResult::Single(range2));
117    }
118
119    #[test]
120    fn overlapping() {
121        let range = GenericRange::from(0..10);
122        let range2 = GenericRange::from(5..=15);
123
124        assert_eq!(
125            range.difference(range2),
126            OperationResult::Single(GenericRange::from(0..5))
127        );
128        assert_eq!(
129            range2.difference(range),
130            OperationResult::Single(GenericRange::from(10..=15))
131        );
132
133        assert_eq!(range - range2, OperationResult::Single(GenericRange::from(0..5)));
134        assert_eq!(range2 - range, OperationResult::Single(GenericRange::from(10..=15)));
135    }
136
137    #[test]
138    fn containing() {
139        let range = GenericRange::from(0..10);
140        let range2 = GenericRange::from(5..=8);
141
142        assert_eq!(
143            range.difference(range2),
144            OperationResult::Double(GenericRange::from(0..5), GenericRange::new_open(8, 10))
145        );
146        assert_eq!(range2.difference(range), OperationResult::Empty);
147
148        assert_eq!(
149            range - range2,
150            OperationResult::Double(GenericRange::from(0..5), GenericRange::new_open(8, 10))
151        );
152        assert_eq!(range2 - range, OperationResult::Empty);
153    }
154
155    #[test]
156    fn starting() {
157        let range = GenericRange::from(0..10);
158        let range2 = GenericRange::from(0..=8);
159
160        assert_eq!(
161            range.difference(range2),
162            OperationResult::Single(GenericRange::new_open(8, 10))
163        );
164        assert_eq!(range2.difference(range), OperationResult::Empty);
165
166        assert_eq!(range - range2, OperationResult::Single(GenericRange::new_open(8, 10)));
167        assert_eq!(range2 - range, OperationResult::Empty);
168    }
169
170    #[test]
171    fn ending() {
172        let range = GenericRange::from(3..=10);
173        let range2 = GenericRange::from(5..=10);
174
175        assert_eq!(
176            range.difference(range2),
177            OperationResult::Single(GenericRange::from(3..5))
178        );
179        assert_eq!(range2.difference(range), OperationResult::Empty);
180
181        assert_eq!(range - range2, OperationResult::Single(GenericRange::from(3..5)));
182        assert_eq!(range2 - range, OperationResult::Empty);
183    }
184
185    #[test]
186    fn equal() {
187        let range = GenericRange::from(5..=10);
188        let range2 = range;
189
190        assert_eq!(range.difference(range2), OperationResult::Empty);
191        assert_eq!(range2.difference(range), OperationResult::Empty);
192
193        assert_eq!(range - range2, OperationResult::Empty);
194        assert_eq!(range2 - range, OperationResult::Empty);
195    }
196}