@@ -364,6 +364,14 @@ impl<T: Ord+Normalizable> Range<T> {
364
364
}
365
365
}
366
366
367
+ fn order < T : Ord > ( a : T , b : T ) -> ( T , T ) {
368
+ if a < b {
369
+ ( a, b)
370
+ } else {
371
+ ( b, a)
372
+ }
373
+ }
374
+
367
375
impl < T : Ord +Normalizable +Clone > Range < T > {
368
376
/// Returns the intersection of this range with another
369
377
pub fn intersect ( & self , other : & Range < T > ) -> Range < T > {
@@ -378,6 +386,37 @@ impl<T: Ord+Normalizable+Clone> Range<T> {
378
386
379
387
Range :: new ( lower. map ( |v| v. clone ( ) ) , upper. map ( |v| v. clone ( ) ) )
380
388
}
389
+
390
+ /// Returns the union of this range with another if it is contiguous
391
+ pub fn union ( & self , other : & Range < T > ) -> Option < Range < T > > {
392
+ if self . is_empty ( ) {
393
+ return Some ( other. clone ( ) ) ;
394
+ }
395
+
396
+ if other. is_empty ( ) {
397
+ return Some ( self . clone ( ) ) ;
398
+ }
399
+
400
+ let ( OptBound ( l_lower) , OptBound ( u_lower) ) =
401
+ order ( OptBound ( self . lower ( ) ) , OptBound ( other. lower ( ) ) ) ;
402
+ let ( OptBound ( l_upper) , OptBound ( u_upper) ) =
403
+ order ( OptBound ( self . upper ( ) ) , OptBound ( other. upper ( ) ) ) ;
404
+
405
+ let discontiguous = match ( u_lower, l_upper) {
406
+ ( Some ( & RangeBound { value : ref l, type_ : Exclusive } ) ,
407
+ Some ( & RangeBound { value : ref u, type_ : Exclusive } ) ) => l >= u,
408
+ ( Some ( & RangeBound { value : ref l, .. } ) ,
409
+ Some ( & RangeBound { value : ref u, .. } ) ) => l > u,
410
+ _ => false
411
+ } ;
412
+
413
+ if discontiguous {
414
+ None
415
+ } else {
416
+ Some ( Range :: new ( l_lower. map ( |v| v. clone ( ) ) ,
417
+ u_upper. map ( |v| v. clone ( ) ) ) )
418
+ }
419
+ }
381
420
}
382
421
383
422
#[ cfg( test) ]
@@ -544,6 +583,42 @@ mod test {
544
583
assert_eq ! ( r2, r2. intersect( & r1) ) ;
545
584
}
546
585
586
+ #[ test]
587
+ fn test_union ( ) {
588
+ let r1 = range ! ( '[' 10i32 , 15i32 ')' ) ;
589
+ let r2 = range ! ( '(' 20i32 , 25i32 ']' ) ;
590
+ assert_eq ! ( None , r1. union ( & r2) ) ;
591
+ assert_eq ! ( None , r2. union ( & r1) ) ;
592
+
593
+ let r2 = range ! ( '(' , ')' ) ;
594
+ assert_eq ! ( Some ( r2) , r1. union ( & r2) ) ;
595
+ assert_eq ! ( Some ( r2) , r2. union ( & r1) ) ;
596
+
597
+ let r2 = range ! ( '[' 13i32 , 50i32 ')' ) ;
598
+ assert_eq ! ( Some ( range!( '[' 10i32 , 50i32 ')' ) ) , r1. union ( & r2) ) ;
599
+ assert_eq ! ( Some ( range!( '[' 10i32 , 50i32 ')' ) ) , r2. union ( & r1) ) ;
600
+
601
+ let r2 = range ! ( '[' 3i32 , 50i32 ')' ) ;
602
+ assert_eq ! ( Some ( range!( '[' 3i32 , 50i32 ')' ) ) , r1. union ( & r2) ) ;
603
+ assert_eq ! ( Some ( range!( '[' 3i32 , 50i32 ')' ) ) , r2. union ( & r1) ) ;
604
+
605
+ let r2 = range ! ( '(' , 11i32 ')' ) ;
606
+ assert_eq ! ( Some ( range!( '(' , 15i32 ')' ) ) , r1. union ( & r2) ) ;
607
+ assert_eq ! ( Some ( range!( '(' , 15i32 ')' ) ) , r2. union ( & r1) ) ;
608
+
609
+ let r2 = range ! ( '(' 11i32 , ')' ) ;
610
+ assert_eq ! ( Some ( range!( '[' 10i32 , ')' ) ) , r1. union ( & r2) ) ;
611
+ assert_eq ! ( Some ( range!( '[' 10i32 , ')' ) ) , r2. union ( & r1) ) ;
612
+
613
+ let r2 = range ! ( '(' 15i32 , 20i32 ')' ) ;
614
+ assert_eq ! ( None , r1. union ( & r2) ) ;
615
+ assert_eq ! ( None , r2. union ( & r1) ) ;
616
+
617
+ let r2 = range ! ( '[' 15i32 , 20i32 ']' ) ;
618
+ assert_eq ! ( Some ( range!( '[' 10i32 , 20i32 ']' ) ) , r1. union ( & r2) ) ;
619
+ assert_eq ! ( Some ( range!( '[' 10i32 , 20i32 ']' ) ) , r2. union ( & r1) ) ;
620
+ }
621
+
547
622
#[ test]
548
623
fn test_contains_range ( ) {
549
624
assert ! ( Range :: <i32 >:: empty( ) . contains_range( & Range :: empty( ) ) ) ;
0 commit comments