| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use std::{ |
| io::{Read, Seek}, |
| ops::Range, |
| }; |
| |
| pub trait ReadAndSeek: Read + Seek {} |
| impl<T> ReadAndSeek for T where T: Read + Seek {} |
| |
| pub trait RangeOps<T> { |
| /// Returns `true` if a slice of self is contained in the |other|. |
| fn overlaps(&self, other: &Self) -> bool; |
| |
| /// Returns `true` if `start` of one equals `end` of the other. |
| /// ``` |
| /// let a: Range<u64> = 1..10; |
| /// let b. Range<u64> = 10..14; |
| /// assert!(a.is_adjacent(&b)); |
| /// ``` |
| fn is_adjacent(&self, other: &Self) -> bool; |
| |
| /// Returns `true` if all of `other` is contained within `self`. |
| /// ``` |
| /// let a: Range<u64> = 1..10; |
| /// let b. Range<u64> = 2..4; |
| /// assert!(a.contains_range(&b)); |
| /// assert!(!b.contains_range(&a)); |
| /// ``` |
| fn contains_range(&self, other: &Self) -> bool; |
| fn is_valid(&self) -> bool; |
| fn length(&self) -> T; |
| } |
| |
| impl<T: Copy + std::cmp::Ord + std::ops::Sub<Output = T>> RangeOps<T> for Range<T> { |
| fn overlaps(&self, other: &Self) -> bool { |
| std::cmp::max(self.start, other.start) < std::cmp::min(self.end, other.end) |
| } |
| |
| fn is_adjacent(&self, other: &Self) -> bool { |
| let min_end = std::cmp::min(self.end, other.end); |
| let max_start = std::cmp::max(self.start, other.start); |
| min_end == max_start |
| } |
| |
| fn contains_range(&self, other: &Self) -> bool { |
| if self.start >= self.end || other.start >= other.end { |
| return false; |
| } |
| self.start <= other.start && self.end >= other.end |
| } |
| |
| fn is_valid(&self) -> bool { |
| self.start < self.end |
| } |
| |
| fn length(&self) -> T { |
| assert!(self.start < self.end); |
| self.end - self.start |
| } |
| } |
| |
| #[cfg(test)] |
| pub(crate) fn get_overlapping_ranges() -> (Range<u64>, Range<u64>) { |
| (1..5, 4..8) |
| } |
| |
| #[cfg(test)] |
| pub(crate) fn get_containing_ranges() -> (Range<u64>, Range<u64>) { |
| (1..5, 2..4) |
| } |
| |
| #[cfg(test)] |
| pub(crate) fn get_adjacent_ranges() -> (Range<u64>, Range<u64>) { |
| (1..5, 5..8) |
| } |
| |
| #[cfg(test)] |
| pub(crate) fn get_non_overlapping_ranges() -> (Range<u64>, Range<u64>) { |
| (1..5, 6..8) |
| } |
| |
| #[cfg(test)] |
| mod test { |
| use super::*; |
| |
| #[test] |
| fn test_range_overlaps() { |
| let (r1, r2) = get_overlapping_ranges(); |
| assert!(r1.overlaps(&r2)); |
| assert!(r2.overlaps(&r1)); |
| |
| // Overlaps with itself. |
| assert!(r1.overlaps(&r1)); |
| |
| // Range completely contains the other. |
| let (r3, r4) = get_containing_ranges(); |
| assert!(r4.overlaps(&r3)); |
| assert!(r3.overlaps(&r4)); |
| } |
| |
| #[test] |
| fn test_range_do_not_overlaps() { |
| // Adjacent ranges |
| let (r1, r2) = get_adjacent_ranges(); |
| assert!(!r1.overlaps(&r2)); |
| assert!(!r2.overlaps(&r1)); |
| |
| // Non-overlapping |
| let (r3, r4) = get_non_overlapping_ranges(); |
| assert!(!r4.overlaps(&r3)); |
| assert!(!r3.overlaps(&r4)); |
| } |
| |
| #[test] |
| fn test_range_is_adjacent() { |
| // Adjacent ranges |
| let (r1, r2) = get_adjacent_ranges(); |
| assert!(r1.is_adjacent(&r2)); |
| assert!(r2.is_adjacent(&r1)); |
| |
| // Non-overlapping |
| let (r3, r4) = get_non_overlapping_ranges(); |
| assert!(!r4.is_adjacent(&r3)); |
| assert!(!r3.is_adjacent(&r4)); |
| |
| // Overlapping |
| let (r5, r6) = get_overlapping_ranges(); |
| assert!(!r5.is_adjacent(&r6)); |
| assert!(!r6.is_adjacent(&r5)); |
| assert!(!r5.is_adjacent(&r5)); |
| |
| // Range completely contains the other. |
| let (r7, r8) = get_containing_ranges(); |
| assert!(!r7.is_adjacent(&r8)); |
| assert!(!r8.is_adjacent(&r7)); |
| } |
| |
| #[test] |
| fn test_range_contains_range() { |
| // r1 has r2 |
| let (r1, r2) = get_containing_ranges(); |
| |
| // One doesn't contains itself. |
| assert!(r1.contains_range(&r1)); |
| |
| assert!(r1.contains_range(&r2)); |
| // But doesn't have r1. |
| assert!(!r2.contains_range(&r1)); |
| |
| // Overlapping |
| let (r3, r4) = get_overlapping_ranges(); |
| assert!(!r3.contains_range(&r4)); |
| assert!(!r4.contains_range(&r3)); |
| |
| // Non-overlapping |
| let (r5, r6) = get_non_overlapping_ranges(); |
| assert!(!r5.contains_range(&r6)); |
| assert!(!r6.contains_range(&r5)); |
| |
| // Adjacent ranges |
| let (r7, r8) = get_adjacent_ranges(); |
| assert!(!r7.contains_range(&r8)); |
| assert!(!r8.contains_range(&r7)); |
| } |
| |
| #[test] |
| fn test_range_is_valid() { |
| let r1: Range<u64> = 1..8; |
| assert!(r1.is_valid()); |
| |
| let r2: Range<u64> = 1..2; |
| assert!(r2.is_valid()); |
| |
| let r3: Range<u64> = 0..0; |
| assert!(!r3.is_valid()); |
| |
| let r4: Range<u64> = 1..1; |
| assert!(!r4.is_valid()); |
| |
| let r5: Range<u64> = 5..2; |
| assert!(!r5.is_valid()); |
| } |
| |
| #[test] |
| fn test_range_length() { |
| let r1: Range<u64> = 1..8; |
| assert_eq!(r1.length(), 7); |
| |
| let r2: Range<u64> = 1..2; |
| assert_eq!(r2.length(), 1); |
| } |
| |
| #[should_panic] |
| #[test] |
| fn test_invalid_range_length() { |
| // Invalid range length |
| let r1: Range<u64> = 8..1; |
| r1.length(); |
| } |
| } |