use core::ops::BitAnd;
use crate::{Arrangement, Domain, GenericRange, OperationResult};
impl<T: Domain> GenericRange<T> {
pub fn intersect(self, other: Self) -> OperationResult<T> {
match self.arrangement(&other) {
Arrangement::Disjoint { .. } | Arrangement::Touching { .. } => OperationResult::Empty,
Arrangement::Overlapping { self_less, .. } => {
let (less, greater) = if self_less { (self, other) } else { (other, self) };
OperationResult::Single(Self {
start: greater.start,
end: less.end,
})
}
Arrangement::Containing { self_shorter }
| Arrangement::Starting { self_shorter, .. }
| Arrangement::Ending { self_shorter, .. } => {
let short = if self_shorter { self } else { other };
OperationResult::Single(short)
}
Arrangement::Equal => OperationResult::Single(self),
Arrangement::Empty { .. } => {
OperationResult::Empty
}
}
}
}
impl<T, I> BitAnd<I> for GenericRange<T>
where
I: Into<GenericRange<T>>,
T: Domain,
{
type Output = OperationResult<T>;
#[must_use]
fn bitand(self, rhs: I) -> Self::Output {
self.intersect(rhs.into())
}
}
#[cfg(test)]
mod tests {
use crate::{GenericRange, OperationResult};
#[test]
fn disjoint() {
let range = GenericRange::new_less_than(5);
let range2 = GenericRange::new_at_least(10);
assert_eq!(range.intersect(range2), OperationResult::Empty);
assert_eq!(range2.intersect(range), OperationResult::Empty);
assert_eq!(range & range2, OperationResult::Empty);
assert_eq!(range2 & range, OperationResult::Empty);
}
#[test]
fn touching() {
let range = GenericRange::from(0..10);
let range2 = GenericRange::from(10..=20);
assert_eq!(range.intersect(range2), OperationResult::Empty);
assert_eq!(range2.intersect(range), OperationResult::Empty);
assert_eq!(range & range2, OperationResult::Empty);
assert_eq!(range2 & range, OperationResult::Empty);
}
#[test]
fn overlapping() {
let range = GenericRange::from(0..10);
let range2 = GenericRange::from(5..=15);
assert_eq!(
range.intersect(range2),
OperationResult::Single(GenericRange::from(5..10))
);
assert_eq!(
range2.intersect(range),
OperationResult::Single(GenericRange::from(5..10))
);
assert_eq!(range & range2, OperationResult::Single(GenericRange::from(5..10)));
assert_eq!(range2 & range, OperationResult::Single(GenericRange::from(5..10)));
}
#[test]
fn containing() {
let range = GenericRange::from(0..10);
let range2 = GenericRange::from(5..=8);
assert_eq!(range.intersect(range2), OperationResult::Single(range2));
assert_eq!(range2.intersect(range), OperationResult::Single(range2));
assert_eq!(range & range2, OperationResult::Single(range2));
assert_eq!(range2 & range, OperationResult::Single(range2));
}
#[test]
fn starting() {
let range = GenericRange::from(0..10);
let range2 = GenericRange::from(0..=8);
assert_eq!(range.intersect(range2), OperationResult::Single(range2));
assert_eq!(range2.intersect(range), OperationResult::Single(range2));
assert_eq!(range & range2, OperationResult::Single(range2));
assert_eq!(range2 & range, OperationResult::Single(range2));
}
#[test]
fn ending() {
let range = GenericRange::from(3..=10);
let range2 = GenericRange::from(5..=10);
assert_eq!(range.intersect(range2), OperationResult::Single(range2));
assert_eq!(range2.intersect(range), OperationResult::Single(range2));
assert_eq!(range & range2, OperationResult::Single(range2));
assert_eq!(range2 & range, OperationResult::Single(range2));
}
#[test]
fn equal() {
let range = GenericRange::from(5..=10);
let range2 = range;
assert_eq!(range.intersect(range2), OperationResult::Single(range));
assert_eq!(range2.intersect(range), OperationResult::Single(range));
assert_eq!(range & range2, OperationResult::Single(range));
assert_eq!(range2 & range, OperationResult::Single(range));
}
}