@@ -11,6 +11,10 @@ use smallvec::SmallVec;
1111mod tests;
1212
1313/// Stores a set of intervals on the indices.
14+ ///
15+ /// The elements in `map` are sorted and non-adjacent, which means
16+ /// the second value of the previous element is *greater* than the
17+ /// first value of the following element.
1418#[ derive( Debug , Clone ) ]
1519pub struct IntervalSet < I > {
1620 // Start, end
@@ -84,7 +88,7 @@ impl<I: Idx> IntervalSet<I> {
8488 // continue to the next range. We're looking here for the first
8589 // range which starts *non-adjacently* to our end.
8690 let next = self . map . partition_point ( |r| r. 0 <= end + 1 ) ;
87- if let Some ( right) = next. checked_sub ( 1 ) {
91+ let result = if let Some ( right) = next. checked_sub ( 1 ) {
8892 let ( prev_start, prev_end) = self . map [ right] ;
8993 if prev_end + 1 >= start {
9094 // If the start for the inserted range is adjacent to the
@@ -99,25 +103,25 @@ impl<I: Idx> IntervalSet<I> {
99103 if left != right {
100104 self . map . drain ( left..right) ;
101105 }
102- return true ;
106+ true
103107 } else {
104108 // We overlap with the previous range, increase it to
105109 // include us.
106110 //
107111 // Make sure we're actually going to *increase* it though --
108112 // it may be that end is just inside the previously existing
109113 // set.
110- return if end > prev_end {
114+ if end > prev_end {
111115 self . map [ right] . 1 = end;
112116 true
113117 } else {
114118 false
115- } ;
119+ }
116120 }
117121 } else {
118122 // Otherwise, we don't overlap, so just insert
119123 self . map . insert ( right + 1 , ( start, end) ) ;
120- return true ;
124+ true
121125 }
122126 } else {
123127 if self . map . is_empty ( ) {
@@ -127,8 +131,16 @@ impl<I: Idx> IntervalSet<I> {
127131 } else {
128132 self . map . insert ( next, ( start, end) ) ;
129133 }
130- return true ;
131- }
134+ true
135+ } ;
136+ debug_assert ! (
137+ self . check_invariants( ) ,
138+ "wrong intervals after insert {:?}..={:?} to {:?}" ,
139+ start,
140+ end,
141+ self
142+ ) ;
143+ result
132144 }
133145
134146 pub fn contains ( & self , needle : I ) -> bool {
@@ -192,6 +204,7 @@ impl<I: Idx> IntervalSet<I> {
192204 pub fn insert_all ( & mut self ) {
193205 self . clear ( ) ;
194206 self . map . push ( ( 0 , self . domain . try_into ( ) . unwrap ( ) ) ) ;
207+ debug_assert ! ( self . check_invariants( ) ) ;
195208 }
196209
197210 pub fn union ( & mut self , other : & IntervalSet < I > ) -> bool
@@ -203,8 +216,21 @@ impl<I: Idx> IntervalSet<I> {
203216 for range in other. iter_intervals ( ) {
204217 did_insert |= self . insert_range ( range) ;
205218 }
219+ debug_assert ! ( self . check_invariants( ) ) ;
206220 did_insert
207221 }
222+
223+ // Check the intervals are valid, sorted and non-adjacent
224+ fn check_invariants ( & self ) -> bool {
225+ let mut current: Option < u32 > = None ;
226+ for ( start, end) in & self . map {
227+ if start > end || current. map_or ( false , |x| x + 1 >= * start) {
228+ return false ;
229+ }
230+ current = Some ( * end) ;
231+ }
232+ current. map_or ( true , |x| x < self . domain as u32 )
233+ }
208234}
209235
210236/// This data structure optimizes for cases where the stored bits in each row
0 commit comments