@@ -11,6 +11,10 @@ use smallvec::SmallVec;
11
11
mod tests;
12
12
13
13
/// 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.
14
18
#[ derive( Debug , Clone ) ]
15
19
pub struct IntervalSet < I > {
16
20
// Start, end
@@ -84,7 +88,7 @@ impl<I: Idx> IntervalSet<I> {
84
88
// continue to the next range. We're looking here for the first
85
89
// range which starts *non-adjacently* to our end.
86
90
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 ) {
88
92
let ( prev_start, prev_end) = self . map [ right] ;
89
93
if prev_end + 1 >= start {
90
94
// If the start for the inserted range is adjacent to the
@@ -99,25 +103,25 @@ impl<I: Idx> IntervalSet<I> {
99
103
if left != right {
100
104
self . map . drain ( left..right) ;
101
105
}
102
- return true ;
106
+ true
103
107
} else {
104
108
// We overlap with the previous range, increase it to
105
109
// include us.
106
110
//
107
111
// Make sure we're actually going to *increase* it though --
108
112
// it may be that end is just inside the previously existing
109
113
// set.
110
- return if end > prev_end {
114
+ if end > prev_end {
111
115
self . map [ right] . 1 = end;
112
116
true
113
117
} else {
114
118
false
115
- } ;
119
+ }
116
120
}
117
121
} else {
118
122
// Otherwise, we don't overlap, so just insert
119
123
self . map . insert ( right + 1 , ( start, end) ) ;
120
- return true ;
124
+ true
121
125
}
122
126
} else {
123
127
if self . map . is_empty ( ) {
@@ -127,8 +131,16 @@ impl<I: Idx> IntervalSet<I> {
127
131
} else {
128
132
self . map . insert ( next, ( start, end) ) ;
129
133
}
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
132
144
}
133
145
134
146
pub fn contains ( & self , needle : I ) -> bool {
@@ -192,6 +204,7 @@ impl<I: Idx> IntervalSet<I> {
192
204
pub fn insert_all ( & mut self ) {
193
205
self . clear ( ) ;
194
206
self . map . push ( ( 0 , self . domain . try_into ( ) . unwrap ( ) ) ) ;
207
+ debug_assert ! ( self . check_invariants( ) ) ;
195
208
}
196
209
197
210
pub fn union ( & mut self , other : & IntervalSet < I > ) -> bool
@@ -203,8 +216,21 @@ impl<I: Idx> IntervalSet<I> {
203
216
for range in other. iter_intervals ( ) {
204
217
did_insert |= self . insert_range ( range) ;
205
218
}
219
+ debug_assert ! ( self . check_invariants( ) ) ;
206
220
did_insert
207
221
}
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
+ }
208
234
}
209
235
210
236
/// This data structure optimizes for cases where the stored bits in each row
0 commit comments