use core::ops::Not;
use crate::{Domain, Ranges};
impl<T: Domain> Ranges<T> {
/// Inverts the range set.
///
/// # Examples
/// Empty set:
/// ```
/// use ranges::Ranges;
///
/// assert_eq!(!Ranges::<usize>::new(), Ranges::full());
/// ```
/// Single entry:
/// ```
/// use ranges::{GenericRange, Ranges};
///
/// let ranges = Ranges::from(0..10);
/// assert_eq!(
/// !ranges,
/// vec![GenericRange::new_less_than(0), GenericRange::new_at_least(10)].into()
/// );
/// ```
/// Multiple entries:
/// ```
/// use ranges::{GenericRange, Ranges};
///
/// let ranges = Ranges::from(vec![GenericRange::from(0..10), (15..=20).into()]);
/// assert_eq!(
/// !ranges,
/// vec![
/// GenericRange::new_less_than(0),
/// (10..15).into(),
/// GenericRange::new_greater_than(20)
/// ].into()
/// );
/// ```
#[must_use]
pub fn invert(self) -> Self {
Self::full().difference(self)
}
}
/// This calls [`self.invert()`](#method.invert).
impl<T: Domain> Not for Ranges<T> {
type Output = Self;
#[must_use]
fn not(self) -> Self::Output {
self.invert()
}
}
#[cfg(test)]
mod tests {
use alloc::vec;
use core::cmp::Ordering;
use core::ops::RangeBounds;
use proptest::prelude::*;
use crate::{GenericRange, Ranges};
#[test]
fn empty() {
assert_eq!(!Ranges::<usize>::new(), Ranges::full());
}
#[test]
fn single_range() {
let ranges = Ranges::from(0..10);
assert_eq!(
!ranges,
Ranges {
ranges: vec![GenericRange::new_less_than(0), GenericRange::new_at_least(10)]
}
);
}
#[test]
fn two_ranges() {
let ranges = Ranges::from(vec![GenericRange::from(0..10), (15..=20).into()]);
assert_eq!(
!ranges,
Ranges {
ranges: vec![
GenericRange::new_less_than(0),
(10..15).into(),
GenericRange::new_greater_than(20)
]
}
);
}
proptest! {
#[ignore]
#[test]
fn sorted_and_disjoint(ranges in any::<Ranges<u8>>()) {
let result = ranges.invert();
let sorted_and_disjoint = result.as_slice().windows(2).all(|slice| match slice {
[left, right] => {
GenericRange::cmp_start_start(left.start_bound(), right.start_bound()) == Ordering::Less
&& GenericRange::cmp_end_start(left.end_bound(), right.start_bound()) == Ordering::Less
},
_ => false,
});
prop_assert!(sorted_and_disjoint);
}
}
}