@@ -81,14 +81,44 @@ impl<I: Interval> IntervalSet<I> {
81
81
82
82
/// Add a new interval to this set.
83
83
pub fn push ( & mut self , interval : I ) {
84
- // TODO: This could be faster. e.g., Push the interval such that
85
- // it preserves canonicalization.
86
- self . ranges . push ( interval) ;
87
- self . canonicalize ( ) ;
88
84
// We don't know whether the new interval added here is considered
89
85
// case folded, so we conservatively assume that the entire set is
90
86
// no longer case folded if it was previously.
91
87
self . folded = false ;
88
+
89
+ if self . ranges . is_empty ( ) {
90
+ self . ranges . push ( interval) ;
91
+ return ;
92
+ }
93
+
94
+ // Find the first range that is not greater than the new interval.
95
+ // This is the first range that could possibly be unioned with the
96
+ // new interval.
97
+ let mut drain_end = self . ranges . len ( ) ;
98
+ while drain_end > 0
99
+ && self . ranges [ drain_end - 1 ] . lower ( ) > interval. upper ( )
100
+ {
101
+ drain_end -= 1 ;
102
+ }
103
+
104
+ // Try to union the new interval with old intervals backwards.
105
+ if drain_end > 0 && self . ranges [ drain_end - 1 ] . is_contiguous ( & interval)
106
+ {
107
+ self . ranges [ drain_end - 1 ] =
108
+ self . ranges [ drain_end - 1 ] . union ( & interval) . unwrap ( ) ;
109
+ for i in 0 ..drain_end - 1 {
110
+ if let Some ( union) =
111
+ self . ranges [ drain_end - 1 ] . union ( & self . ranges [ i] )
112
+ {
113
+ self . ranges [ drain_end - 1 ] = union;
114
+ } else {
115
+ self . ranges . drain ( i + 1 ..drain_end - 1 ) ;
116
+ break ;
117
+ }
118
+ }
119
+ } else {
120
+ self . ranges . insert ( drain_end, interval) ;
121
+ }
92
122
}
93
123
94
124
/// Return an iterator over all intervals in this set.
0 commit comments