@@ -56,33 +56,72 @@ impl Range {
5656 Ok ( Self :: new ( self . start . max ( other. start ) , self . end . min ( other. end ) ) . unwrap ( ) )
5757 }
5858
59+ /// Calculates the difference between two ranges.
60+ ///
61+ /// This method returns a vector of ranges representing the parts of `self`
62+ /// that are not present in `other`.
63+ ///
64+ /// # Cases:
65+ /// - If `other` completely contains `self`, the result is an empty vector.
66+ /// - If `self` completely contains `other`, the result is a vector with two ranges.
67+ /// - If they partially overlap, the result is a vector with one range.
68+ /// - If they do not overlap, the result is a vector containing `self`.
69+ ///
70+ /// # Example
71+ ///
72+ /// ```
73+ /// use crate::utils::range::Range;
74+ ///
75+ /// let range = Range::new(3, 8).unwrap();
76+ ///
77+ /// // Case where `other` is inside `self`
78+ /// let other1 = Range::new(5, 6).unwrap();
79+ /// assert_eq!(
80+ /// vec![Range::new(3, 4).unwrap(), Range::new(7, 8).unwrap()],
81+ /// range.diff(&other1)
82+ /// );
83+ ///
84+ /// // Case where `other` overlaps on the right
85+ /// let other2 = Range::new(7, 10).unwrap();
86+ /// assert_eq!(
87+ /// vec![Range::new(3, 6).unwrap()],
88+ /// range.diff(&other2)
89+ /// );
90+ ///
91+ /// // Case where `other` does not overlap
92+ /// let other3 = Range::new(10, 12).unwrap();
93+ /// assert_eq!(
94+ /// vec![range],
95+ /// range.diff(&other3)
96+ /// );
97+ ///
98+ /// // Case where `other` completely contains `self`
99+ /// let other4 = Range::new(1, 10).unwrap();
100+ /// assert_eq!(
101+ /// Vec::<Range>::new(),
102+ /// range.diff(&other4)
103+ /// );
104+ /// ```
59105 pub fn diff ( & self , other : & Self ) -> Vec < Self > {
60- // other is outside self
61- if other. start <= self . start && other. end >= self . end {
62- return vec ! [ ] ;
63- }
106+ let mut result = Vec :: new ( ) ;
64107
65- // other is inside self
66- if other . start > self . start && other. end < self . end {
67- return vec ! [
68- Self :: new ( self . start, other . start - 1 ) . unwrap ( ) ,
69- Self :: new( other . end + 1 , self . end) . unwrap( ) ,
70- ] ;
108+ // Part of self before other starts
109+ if self . start < other. start {
110+ let end = self . end . min ( other . start - 1 ) ;
111+ if self . start <= end {
112+ result . push ( Self :: new ( self . start , end) . unwrap ( ) ) ;
113+ }
71114 }
72115
73- let start: isize ;
74- let end: isize ;
75-
76- // collide on side
77- if self . start < other. start {
78- start = self . start . min ( other. start ) ;
79- end = self . start . max ( other. start ) - 1 ;
80- } else {
81- start = self . end . min ( other. end ) + 1 ;
82- end = self . end . max ( other. end ) ;
116+ // Part of self after other ends
117+ if self . end > other. end {
118+ let start = self . start . max ( other. end + 1 ) ;
119+ if start <= self . end {
120+ result. push ( Self :: new ( start, self . end ) . unwrap ( ) ) ;
121+ }
83122 }
84123
85- vec ! [ Self :: new ( start , end ) . unwrap ( ) ]
124+ result
86125 }
87126
88127 pub fn iter ( & self ) -> impl Iterator < Item = isize > {
@@ -192,14 +231,26 @@ mod tests {
192231 ) ;
193232
194233 assert_eq ! (
195- vec![ Range :: new( 3 , 3 ) . unwrap( ) , Range :: new( 6 , 6 ) . unwrap( ) , ] ,
234+ vec![ Range :: new( 3 , 3 ) . unwrap( ) , Range :: new( 6 , 6 ) . unwrap( ) ] ,
196235 range. diff( & Range :: new( 4 , 5 ) . unwrap( ) )
197236 ) ;
198237
199- // @fixme - why it doesnt work for that case?
200- // assert_eq!(
201- // Vec::<Range>::new(),
202- // range.diff(&Range::new(10, 14).unwrap())
203- // );
238+ // Case where other does not overlap and is after self
239+ assert_eq ! ( vec![ range] , range. diff( & Range :: new( 10 , 14 ) . unwrap( ) ) ) ;
240+
241+ // Case where other does not overlap and is before self
242+ assert_eq ! ( vec![ range] , range. diff( & Range :: new( 0 , 1 ) . unwrap( ) ) ) ;
243+
244+ // Case where other completely contains self
245+ assert_eq ! ( Vec :: <Range >:: new( ) , range. diff( & Range :: new( 2 , 7 ) . unwrap( ) ) ) ;
246+
247+ // Case where self and other are identical
248+ assert_eq ! ( Vec :: <Range >:: new( ) , range. diff( & Range :: new( 3 , 6 ) . unwrap( ) ) ) ;
249+
250+ // Case where other overlaps on the left
251+ assert_eq ! (
252+ vec![ Range :: new( 5 , 6 ) . unwrap( ) ] ,
253+ range. diff( & Range :: new( 1 , 4 ) . unwrap( ) )
254+ ) ;
204255 }
205256}
0 commit comments