@@ -81,14 +81,44 @@ impl<I: Interval> IntervalSet<I> {
8181
8282 /// Add a new interval to this set.
8383 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 ( ) ;
8884 // We don't know whether the new interval added here is considered
8985 // case folded, so we conservatively assume that the entire set is
9086 // no longer case folded if it was previously.
9187 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+ }
92122 }
93123
94124 /// Return an iterator over all intervals in this set.
0 commit comments