@@ -826,6 +826,84 @@ impl<V: Ord + Clone> Ranges<V> {
826826 }
827827}
828828
829+ impl < V : Ord > FromIterator < ( Bound < V > , Bound < V > ) > for Ranges < V > {
830+ /// Constructor from arbitrary, unsorted and potentially overlapping ranges.
831+ fn from_iter < T : IntoIterator < Item = ( Bound < V > , Bound < V > ) > > ( iter : T ) -> Self {
832+ // We have three constraints we need to fulfil:
833+ // 1. The segments are sorted, from lowest to highest (through `Ord`): By sorting.
834+ // 2. Each segment contains at least one version (start < end): By `union`.
835+ // 3. There is at least one version between two segments: By `union`.
836+ let mut segments: SmallVec < [ Interval < V > ; 1 ] > = SmallVec :: new ( ) ;
837+
838+ for segment in iter {
839+ if !valid_segment ( & segment. start_bound ( ) , & segment. end_bound ( ) ) {
840+ continue ;
841+ }
842+ // Find where to insert the new segment
843+ let insertion_point = segments. partition_point ( |elem : & Interval < V > | {
844+ cmp_bounds_start ( elem. start_bound ( ) , segment. end_bound ( ) )
845+ . unwrap ( )
846+ . is_lt ( )
847+ } ) ;
848+ // Is it overlapping with the previous segment?
849+ let previous_overlapping = insertion_point > 0
850+ && !end_before_start_with_gap (
851+ & segments[ insertion_point - 1 ] . end_bound ( ) ,
852+ & segment. start_bound ( ) ,
853+ ) ;
854+
855+ // Is it overlapping with the following segment?
856+ let next_overlapping = insertion_point < segments. len ( )
857+ && !end_before_start_with_gap (
858+ & segment. end_bound ( ) ,
859+ & segments[ insertion_point] . start_bound ( ) ,
860+ ) ;
861+
862+ match ( previous_overlapping, next_overlapping) {
863+ ( true , true ) => {
864+ // previous: |-------|
865+ // segment: |-------|
866+ // following: |-----|
867+ //
868+ // final: |--------------------|
869+ // We merge all three segments into one, which is effectively removing one of
870+ // two previously inserted and changing the bounds on the other.
871+ let following = segments. remove ( insertion_point) ;
872+ segments[ insertion_point - 1 ] . 1 = following. 1 ;
873+ }
874+ ( true , false ) => {
875+ // previous: |-----|
876+ // segment: |-----|
877+ // following: |-----|
878+ //
879+ // final: |---------| |-----|
880+ // We can reuse the existing element by extending it.
881+ segments[ insertion_point - 1 ] . 1 = segment. 1 ;
882+ }
883+ ( false , true ) => {
884+ // previous: |-----|
885+ // segment: |-----|
886+ // following: |-----|
887+ //
888+ // final: |-----| |---------|
889+ // We can reuse the existing element by extending it.
890+ segments[ insertion_point] . 0 = segment. 0 ;
891+ }
892+ ( false , false ) => {
893+ // previous: |-----|
894+ // segment: |-----|
895+ // following: |-----|
896+ //
897+ // final: |-----| |-----| |-----|
898+ segments. insert ( insertion_point, segment) ;
899+ }
900+ }
901+ }
902+
903+ Self { segments } . check_invariants ( )
904+ }
905+ }
906+
829907// REPORT ######################################################################
830908
831909impl < V : Display + Eq > Display for Ranges < V > {
@@ -1130,6 +1208,11 @@ pub mod tests {
11301208 }
11311209 assert!( simp. segments. len( ) <= range. segments. len( ) )
11321210 }
1211+
1212+ #[ test]
1213+ fn from_iter_valid( segments in proptest:: collection:: vec( any:: <( Bound <u32 >, Bound <u32 >) >( ) , ..30 ) ) {
1214+ Ranges :: from_iter( segments. clone( ) ) . check_invariants( ) ;
1215+ }
11331216 }
11341217
11351218 #[ test]
0 commit comments