1use std::cmp::Ordering::*;
51use std::ops::Range;
52
53pub trait RangeExt<T> {
57 fn compare(&self, other: &Range<T>) -> RangeCmpResult<T>;
59}
60
61impl<T> RangeExt<T> for Range<T>
63where
64 T: Ord + Eq + Copy,
65{
66 fn compare(&self, other: &Range<T>) -> RangeCmpResult<T> {
68 if self.is_empty() || other.is_empty() {
69 return RangeCmpResult::RangeEmpty;
70 }
71
72 match (
73 self.start.cmp(&other.start),
74 self.end.cmp(&other.end),
75 self.start.cmp(&other.end),
76 self.end.cmp(&other.start),
77 ) {
78 (Equal, Equal, _, _) => RangeCmpResult::CompletelyTheSame,
79 (_, _, Greater | Equal, _) => RangeCmpResult::NotIncludedAbove,
81 (_, _, _, Less | Equal) => RangeCmpResult::NotIncludedBelow,
82 (Less, Less, _, _) => RangeCmpResult::EndIncluded {
83 other_after: self.end..other.end,
84 original_part_which_is_not_included: self.start..other.start,
85 overlapping_part: other.start..self.end,
86 },
87 (Greater, Greater, _, _) => RangeCmpResult::StartIncluded {
88 other_before: other.start..self.start,
89 original_part_which_is_not_included: other.end..self.end,
90 overlapping_part: self.start..other.end,
91 },
92 (Less, Greater, _, _) => RangeCmpResult::MiddleIncluded {
93 overlapping_part: other.start..other.end,
94 original_before_not_included: self.start..other.start,
95 original_after_not_included: other.end..self.end,
96 },
97 (Greater, Less, _, _) => RangeCmpResult::CompletelyIncluded {
98 other_before: other.start..self.start,
99 other_after: self.end..other.end,
100 overlapping_part: self.start..self.end,
101 },
102 (Equal, Less, _, _) => RangeCmpResult::SameStartOriginalShorter {
103 overlapping_part: self.start..self.end,
104 other_after_not_included: self.end..other.end,
105 },
106 (Equal, Greater, _, _) => RangeCmpResult::SameStartOtherShorter {
107 overlapping_part: other.start..other.end,
108 original_after_not_included: other.end..self.end,
109 },
110 (Less, Equal, _, _) => RangeCmpResult::SameEndOtherShorter {
111 overlapping_part: other.start..other.end,
112 original_before_not_included: self.start..other.start,
113 },
114 (Greater, Equal, _, _) => RangeCmpResult::SameEndOriginalShorter {
115 overlapping_part: self.start..self.end,
116 other_before_not_included: other.start..self.start,
117 },
118 }
119 }
120}
121
122#[derive(Debug, Clone, PartialEq, Eq)]
126pub enum RangeCmpResult<T> {
127 CompletelyTheSame,
141
142 NotIncludedBelow,
156
157 NotIncludedAbove,
171
172 RangeEmpty,
186
187 CompletelyIncluded {
208 other_before: Range<T>,
209 other_after: Range<T>,
210 overlapping_part: Range<T>,
211 },
212
213 EndIncluded {
234 other_after: Range<T>,
236 original_part_which_is_not_included: Range<T>,
237 overlapping_part: Range<T>,
238 },
239
240 StartIncluded {
260 other_before: Range<T>,
261 original_part_which_is_not_included: Range<T>,
262 overlapping_part: Range<T>,
263 },
264
265 MiddleIncluded {
286 overlapping_part: Range<T>,
287 original_before_not_included: Range<T>,
288 original_after_not_included: Range<T>,
289 },
290
291 SameStartOriginalShorter {
310 overlapping_part: Range<T>,
311 other_after_not_included: Range<T>,
312 },
313
314 SameStartOtherShorter {
334 overlapping_part: Range<T>,
335 original_after_not_included: Range<T>,
336 },
337
338 SameEndOriginalShorter {
357 overlapping_part: Range<T>,
358 other_before_not_included: Range<T>,
359 },
360
361 SameEndOtherShorter {
380 overlapping_part: Range<T>,
381 original_before_not_included: Range<T>,
382 },
383}
384
385impl<T> RangeCmpResult<T> {
386 pub fn get_matching_part(&self) -> Option<&Range<T>> {
390 match self {
391 RangeCmpResult::RangeEmpty => None,
392 RangeCmpResult::CompletelyTheSame => None,
393 RangeCmpResult::NotIncludedBelow => None,
394 RangeCmpResult::NotIncludedAbove => None,
395 RangeCmpResult::CompletelyIncluded {
396 other_before: _,
397 other_after: _,
398 overlapping_part: original_included_part,
399 } => Some(original_included_part),
400 RangeCmpResult::EndIncluded {
401 other_after: _,
403 original_part_which_is_not_included: _,
404 overlapping_part: original_included_part,
405 } => Some(original_included_part),
406 RangeCmpResult::StartIncluded {
407 other_before: _,
408 original_part_which_is_not_included: _,
409 overlapping_part: original_included_part,
410 } => Some(original_included_part),
411 RangeCmpResult::MiddleIncluded {
412 overlapping_part: original_included_part,
413 original_before_not_included: _,
414 original_after_not_included: _,
415 } => Some(original_included_part),
416 RangeCmpResult::SameStartOriginalShorter {
417 overlapping_part: original_included_part,
418 other_after_not_included: _,
419 } => Some(original_included_part),
420 RangeCmpResult::SameStartOtherShorter {
421 overlapping_part: original_included_part,
422 original_after_not_included: _,
423 } => Some(original_included_part),
424 RangeCmpResult::SameEndOriginalShorter {
425 overlapping_part: original_included_part,
426 other_before_not_included: _,
427 } => Some(original_included_part),
428 RangeCmpResult::SameEndOtherShorter {
429 overlapping_part: original_included_part,
430 original_before_not_included: _,
431 } => Some(original_included_part),
432 }
433 }
434
435 pub fn get_original_not_matching_parts(&self) -> [Option<&Range<T>>; 2] {
437 match self {
438 RangeCmpResult::CompletelyTheSame => [None, None],
439 RangeCmpResult::NotIncludedBelow => [None, None],
440 RangeCmpResult::RangeEmpty => [None, None],
441 RangeCmpResult::NotIncludedAbove => [None, None],
442 RangeCmpResult::CompletelyIncluded {
444 other_before: _,
445 other_after: _,
446 overlapping_part: _,
447 } => [None, None],
448 RangeCmpResult::EndIncluded {
449 other_after: _,
451 original_part_which_is_not_included,
452 overlapping_part: _,
453 } => [Some(original_part_which_is_not_included), None],
454 RangeCmpResult::StartIncluded {
455 other_before: _,
456 original_part_which_is_not_included,
457 overlapping_part: _,
458 } => [Some(original_part_which_is_not_included), None],
459 RangeCmpResult::MiddleIncluded {
460 overlapping_part: _,
461 original_before_not_included,
462 original_after_not_included,
463 } => [
464 Some(original_before_not_included),
465 Some(original_after_not_included),
466 ],
467 RangeCmpResult::SameStartOriginalShorter {
468 overlapping_part: _,
469 other_after_not_included: _,
470 } => [None, None],
471 RangeCmpResult::SameStartOtherShorter {
472 overlapping_part: _,
473 original_after_not_included,
474 } => [Some(original_after_not_included), None],
475 RangeCmpResult::SameEndOriginalShorter {
476 overlapping_part: _,
477 other_before_not_included: _,
478 } => [None, None],
479 RangeCmpResult::SameEndOtherShorter {
480 overlapping_part: _,
481 original_before_not_included,
482 } => [Some(original_before_not_included), None],
483 }
484 }
485}
486
487#[cfg(test)]
488mod tests {
489 use super::*;
490
491 #[test]
493 fn test_i32() {
494 let range1 = 2i32..10;
495 let range2 = 5i32..15;
496 let result = range1.compare(&range2);
497 assert_eq!(
498 result,
499 RangeCmpResult::EndIncluded {
500 other_after: 10..15,
501 original_part_which_is_not_included: 2..5,
502 overlapping_part: 5..10,
503 }
504 );
505 }
506
507 #[test]
508 fn test_u8() {
509 let range1 = 2u8..10;
510 let range2 = 5u8..15;
511 let result = range1.compare(&range2);
512 assert_eq!(
513 result,
514 RangeCmpResult::EndIncluded {
515 other_after: 10..15,
516 original_part_which_is_not_included: 2..5,
517 overlapping_part: 5..10,
518 }
519 );
520 }
521
522 #[test]
523 fn test_i8() {
524 let range1 = 2i8..10;
525 let range2 = 5i8..15;
526 let result = range1.compare(&range2);
527 assert_eq!(
528 result,
529 RangeCmpResult::EndIncluded {
530 other_after: 10..15,
531 original_part_which_is_not_included: 2..5,
532 overlapping_part: 5..10,
533 }
534 );
535 }
536
537 #[test]
538 fn test_u16() {
539 let range1 = 2u16..10;
540 let range2 = 5u16..15;
541 let result = range1.compare(&range2);
542 assert_eq!(
543 result,
544 RangeCmpResult::EndIncluded {
545 other_after: 10..15,
546 original_part_which_is_not_included: 2..5,
547 overlapping_part: 5..10,
548 }
549 );
550 }
551
552 #[test]
553 fn test_i16() {
554 let range1 = 2i16..10;
555 let range2 = 5i16..15;
556 let result = range1.compare(&range2);
557 assert_eq!(
558 result,
559 RangeCmpResult::EndIncluded {
560 other_after: 10..15,
561 original_part_which_is_not_included: 2..5,
562 overlapping_part: 5..10,
563 }
564 );
565 }
566
567 #[test]
568 fn test_u32() {
569 let range1 = 2u32..10;
570 let range2 = 5u32..15;
571 let result = range1.compare(&range2);
572 assert_eq!(
573 result,
574 RangeCmpResult::EndIncluded {
575 other_after: 10..15,
576 original_part_which_is_not_included: 2..5,
577 overlapping_part: 5..10,
578 }
579 );
580 }
581
582 #[test]
583 fn test_u64() {
584 let range1 = 2u64..10;
585 let range2 = 5u64..15;
586 let result = range1.compare(&range2);
587 assert_eq!(
588 result,
589 RangeCmpResult::EndIncluded {
590 other_after: 10..15,
591 original_part_which_is_not_included: 2..5,
592 overlapping_part: 5..10,
593 }
594 );
595 }
596
597 #[test]
598 fn test_i64() {
599 let range1 = 2i64..10;
600 let range2 = 5i64..15;
601 let result = range1.compare(&range2);
602 assert_eq!(
603 result,
604 RangeCmpResult::EndIncluded {
605 other_after: 10..15,
606 original_part_which_is_not_included: 2..5,
607 overlapping_part: 5..10,
608 }
609 );
610 }
611
612 #[test]
613 fn test_u128() {
614 let range1 = 2u128..10;
615 let range2 = 5u128..15;
616 let result = range1.compare(&range2);
617 assert_eq!(
618 result,
619 RangeCmpResult::EndIncluded {
620 other_after: 10..15,
621 original_part_which_is_not_included: 2..5,
622 overlapping_part: 5..10,
623 }
624 );
625 }
626
627 #[test]
628 fn test_i126() {
629 let range1 = 2i128..10;
630 let range2 = 5i128..15;
631 let result = range1.compare(&range2);
632 assert_eq!(
633 result,
634 RangeCmpResult::EndIncluded {
635 other_after: 10..15,
636 original_part_which_is_not_included: 2..5,
637 overlapping_part: 5..10,
638 }
639 );
640 }
641
642 #[test]
645 fn test_range_empty() {
646 let range1 = 2..2;
647 let range2 = 5..15;
648 let result = range1.compare(&range2);
649 assert_eq!(result, RangeCmpResult::RangeEmpty);
650 }
651
652 #[test]
653 fn test_range_empty2() {
654 let range1 = 5..2;
655 let range2 = 5..15;
656 let result = range1.compare(&range2);
657 assert_eq!(result, RangeCmpResult::RangeEmpty);
658 }
659
660 #[test]
661 fn test_range_empty3() {
662 let range1 = 5..20;
663 let range2 = 25..15;
664 let result = range1.compare(&range2);
665 assert_eq!(result, RangeCmpResult::RangeEmpty);
666 }
667
668 #[test]
669 fn test_completely_the_same() {
670 let range1 = 2..10;
671 let range2 = 2..10;
672 let result = range1.compare(&range2);
673 assert_eq!(result, RangeCmpResult::CompletelyTheSame);
674 }
675
676 #[test]
677 fn test_not_included() {
678 let range1 = 2..10;
679 let range2 = 11..15;
680 let result = range1.compare(&range2);
681 assert_eq!(result, RangeCmpResult::NotIncludedBelow);
682 }
683
684 #[test]
685 fn test_not_included_above() {
686 let range1 = 11..15;
687 let range2 = 2..10;
688 let result = range1.compare(&range2);
689 assert_eq!(result, RangeCmpResult::NotIncludedAbove);
690 }
691
692 #[test]
693 fn test_completely_included() {
694 let range1 = 2..10;
695 let range2 = 1..11;
696 let result = range1.compare(&range2);
697 assert_eq!(
698 result,
699 RangeCmpResult::CompletelyIncluded {
700 other_before: 1..2,
701 other_after: 10..11,
702 overlapping_part: 2..10,
703 }
704 );
705 }
706
707 #[test]
708 fn test_end_included() {
709 let range1 = 1..9;
710 let range2 = 2..10;
711 let result = range1.compare(&range2);
712 assert_eq!(
713 result,
714 RangeCmpResult::EndIncluded {
715 other_after: 9..10,
716 original_part_which_is_not_included: 1..2,
717 overlapping_part: 2..9,
718 }
719 );
720 }
721
722 #[test]
723 fn test_start_included() {
724 let range1 = 2..15;
725 let range2 = 1..9;
726 let result = range1.compare(&range2);
727 assert_eq!(
728 result,
729 RangeCmpResult::StartIncluded {
730 other_before: 1..2,
731 original_part_which_is_not_included: 9..15,
732 overlapping_part: 2..9,
733 }
734 );
735 }
736
737 #[test]
738 fn test_middle_included() {
739 let range1 = 1..20;
740 let range2 = 4..15;
741 let result = range1.compare(&range2);
742 assert_eq!(
743 result,
744 RangeCmpResult::MiddleIncluded {
745 overlapping_part: 4..15,
746 original_before_not_included: 1..4,
747 original_after_not_included: 15..20,
748 }
749 );
750 }
751
752 #[test]
753 fn test_same_start_original_shorter() {
754 let range1 = 1..10;
755 let range2 = 1..15;
756 let result = range1.compare(&range2);
757 assert_eq!(
758 result,
759 RangeCmpResult::SameStartOriginalShorter {
760 overlapping_part: 1..10,
761 other_after_not_included: 10..15,
762 }
763 );
764 }
765
766 #[test]
767 fn test_same_start_other_shorter() {
768 let range1 = 1..15;
769 let range2 = 1..10;
770 let result = range1.compare(&range2);
771 assert_eq!(
772 result,
773 RangeCmpResult::SameStartOtherShorter {
774 overlapping_part: 1..10,
775 original_after_not_included: 10..15,
776 }
777 );
778 }
779
780 #[test]
781 fn test_same_end_original_shorter() {
782 let range1 = 5..15;
783 let range2 = 1..15;
784 let result = range1.compare(&range2);
785 assert_eq!(
786 result,
787 RangeCmpResult::SameEndOriginalShorter {
788 overlapping_part: 5..15,
789 other_before_not_included: 1..5,
790 }
791 );
792 }
793
794 #[test]
795 fn test_same_end_other_shorter() {
796 let range1 = 1..15;
797 let range2 = 5..15;
798 let result = range1.compare(&range2);
799 assert_eq!(
800 result,
801 RangeCmpResult::SameEndOtherShorter {
802 overlapping_part: 5..15,
803 original_before_not_included: 1..5,
804 }
805 );
806 }
807
808 #[test]
809 fn test_get_matching_part() {
810 let range1 = 29..40;
811 let range2 = 35..70;
812 let result = range1.compare(&range2);
813 let matching_part = result.get_matching_part();
814 assert_eq!(matching_part, Some(35..40).as_ref());
815 }
816}