use crate::intervals::absolute::{
AbsBoundPair,
AbsEndBound,
AbsInterval,
AbsStartBound,
BoundedAbsInterval,
EmptiableAbsBoundPair,
EmptiableAbsInterval,
HalfBoundedAbsInterval,
HasAbsBoundPair,
HasEmptiableAbsBoundPair,
};
use crate::intervals::meta::{HasOpeningDirection, OpeningDirection};
use crate::intervals::relative::{
BoundedRelInterval,
EmptiableRelBoundPair,
EmptiableRelInterval,
HalfBoundedRelInterval,
HasEmptiableRelBoundPair,
HasRelBoundPair,
RelBoundPair,
RelEndBound,
RelInterval,
RelStartBound,
};
use crate::intervals::special::{EmptyInterval, UnboundedInterval};
use crate::ops::ComplementResult;
pub trait Complementable {
type Output;
#[must_use]
fn complement(&self) -> ComplementResult<Self::Output>;
}
impl Complementable for AbsBoundPair {
type Output = EmptiableAbsBoundPair;
fn complement(&self) -> ComplementResult<Self::Output> {
complement_abs_bound_pair(self)
}
}
impl Complementable for EmptiableAbsBoundPair {
type Output = Self;
fn complement(&self) -> ComplementResult<Self::Output> {
complement_emptiable_abs_bound_pair(self)
}
}
impl Complementable for AbsInterval {
type Output = EmptiableAbsInterval;
fn complement(&self) -> ComplementResult<Self::Output> {
complement_abs_bound_pair(&self.abs_bound_pair()).map(Self::Output::from)
}
}
impl Complementable for EmptiableAbsInterval {
type Output = Self;
fn complement(&self) -> ComplementResult<Self::Output> {
complement_emptiable_abs_bound_pair(&self.emptiable_abs_bound_pair()).map(Self::Output::from)
}
}
impl Complementable for BoundedAbsInterval {
type Output = HalfBoundedAbsInterval;
fn complement(&self) -> ComplementResult<Self::Output> {
complement_bounded_abs_interval(self)
}
}
impl Complementable for HalfBoundedAbsInterval {
type Output = HalfBoundedAbsInterval;
fn complement(&self) -> ComplementResult<Self::Output> {
complement_half_bounded_abs_interval(self)
}
}
impl Complementable for RelBoundPair {
type Output = EmptiableRelBoundPair;
fn complement(&self) -> ComplementResult<Self::Output> {
complement_rel_bound_pair(self)
}
}
impl Complementable for EmptiableRelBoundPair {
type Output = Self;
fn complement(&self) -> ComplementResult<Self::Output> {
complement_emptiable_rel_bound_pair(self)
}
}
impl Complementable for RelInterval {
type Output = EmptiableRelInterval;
fn complement(&self) -> ComplementResult<Self::Output> {
complement_rel_bound_pair(&self.rel_bound_pair()).map(Self::Output::from)
}
}
impl Complementable for EmptiableRelInterval {
type Output = Self;
fn complement(&self) -> ComplementResult<Self::Output> {
complement_emptiable_rel_bound_pair(&self.emptiable_rel_bound_pair()).map(Self::Output::from)
}
}
impl Complementable for BoundedRelInterval {
type Output = HalfBoundedRelInterval;
fn complement(&self) -> ComplementResult<Self::Output> {
complement_bounded_rel_interval(self)
}
}
impl Complementable for HalfBoundedRelInterval {
type Output = HalfBoundedRelInterval;
fn complement(&self) -> ComplementResult<Self::Output> {
complement_half_bounded_rel_interval(self)
}
}
impl Complementable for UnboundedInterval {
type Output = EmptyInterval;
fn complement(&self) -> ComplementResult<Self::Output> {
ComplementResult::Single(EmptyInterval)
}
}
impl Complementable for EmptyInterval {
type Output = UnboundedInterval;
fn complement(&self) -> ComplementResult<Self::Output> {
ComplementResult::Single(UnboundedInterval)
}
}
#[must_use]
pub fn complement_abs_bound_pair(bounds: &AbsBoundPair) -> ComplementResult<EmptiableAbsBoundPair> {
type Sb = AbsStartBound;
type Eb = AbsEndBound;
match (bounds.abs_start(), bounds.abs_end()) {
(Sb::InfinitePast, Eb::InfiniteFuture) => ComplementResult::Single(EmptyInterval.emptiable_abs_bound_pair()),
(Sb::InfinitePast, Eb::Finite(finite_end)) => ComplementResult::Single(
AbsBoundPair::new(finite_end.opposite().to_start_bound(), AbsEndBound::InfiniteFuture).to_emptiable(),
),
(Sb::Finite(finite_start), Eb::InfiniteFuture) => ComplementResult::Single(
AbsBoundPair::new(AbsStartBound::InfinitePast, finite_start.opposite().to_end_bound()).to_emptiable(),
),
(Sb::Finite(finite_start), Eb::Finite(finite_end)) => ComplementResult::Split(
AbsBoundPair::new(AbsStartBound::InfinitePast, finite_start.opposite().to_end_bound()).to_emptiable(),
AbsBoundPair::new(finite_end.opposite().to_start_bound(), AbsEndBound::InfiniteFuture).to_emptiable(),
),
}
}
#[must_use]
pub fn complement_emptiable_abs_bound_pair(
emptiable_bounds: &EmptiableAbsBoundPair,
) -> ComplementResult<EmptiableAbsBoundPair> {
let EmptiableAbsBoundPair::Bound(bounds) = emptiable_bounds else {
return ComplementResult::Single(UnboundedInterval.emptiable_abs_bound_pair());
};
complement_abs_bound_pair(bounds)
}
#[must_use]
pub fn complement_bounded_abs_interval(interval: &BoundedAbsInterval) -> ComplementResult<HalfBoundedAbsInterval> {
let until_start = HalfBoundedAbsInterval::from_time_incl(
interval.start_time(),
interval.start_inclusivity().opposite(),
OpeningDirection::ToPast,
);
let since_end = HalfBoundedAbsInterval::from_time_incl(
interval.end_time(),
interval.end_inclusivity().opposite(),
OpeningDirection::ToFuture,
);
ComplementResult::Split(until_start, since_end)
}
#[must_use]
pub fn complement_half_bounded_abs_interval(
interval: &HalfBoundedAbsInterval,
) -> ComplementResult<HalfBoundedAbsInterval> {
ComplementResult::Single(HalfBoundedAbsInterval::from_time_incl(
interval.reference_time(),
interval.reference_inclusivity().opposite(),
interval.opening_direction().opposite(),
))
}
#[must_use]
pub fn complement_rel_bound_pair(bounds: &RelBoundPair) -> ComplementResult<EmptiableRelBoundPair> {
type Sb = RelStartBound;
type Eb = RelEndBound;
match (bounds.rel_start(), bounds.rel_end()) {
(Sb::InfinitePast, Eb::InfiniteFuture) => ComplementResult::Single(EmptyInterval.emptiable_rel_bound_pair()),
(Sb::InfinitePast, Eb::Finite(finite_end)) => ComplementResult::Single(
RelBoundPair::new(finite_end.opposite().to_start_bound(), RelEndBound::InfiniteFuture).to_emptiable(),
),
(Sb::Finite(finite_start), Eb::InfiniteFuture) => ComplementResult::Single(
RelBoundPair::new(RelStartBound::InfinitePast, finite_start.opposite().to_end_bound()).to_emptiable(),
),
(Sb::Finite(finite_start), Eb::Finite(finite_end)) => ComplementResult::Split(
RelBoundPair::new(RelStartBound::InfinitePast, finite_start.opposite().to_end_bound()).to_emptiable(),
RelBoundPair::new(finite_end.opposite().to_start_bound(), RelEndBound::InfiniteFuture).to_emptiable(),
),
}
}
#[must_use]
pub fn complement_emptiable_rel_bound_pair(
emptiable_bounds: &EmptiableRelBoundPair,
) -> ComplementResult<EmptiableRelBoundPair> {
let EmptiableRelBoundPair::Bound(bounds) = emptiable_bounds else {
return ComplementResult::Single(UnboundedInterval.emptiable_rel_bound_pair());
};
complement_rel_bound_pair(bounds)
}
#[must_use]
pub fn complement_bounded_rel_interval(interval: &BoundedRelInterval) -> ComplementResult<HalfBoundedRelInterval> {
let until_start = HalfBoundedRelInterval::from_offset_incl(
interval.start_offset(),
interval.start_inclusivity().opposite(),
OpeningDirection::ToPast,
);
let since_end = HalfBoundedRelInterval::from_offset_incl(
interval.end_offset(),
interval.end_inclusivity().opposite(),
OpeningDirection::ToFuture,
);
ComplementResult::Split(until_start, since_end)
}
#[must_use]
pub fn complement_half_bounded_rel_interval(
interval: &HalfBoundedRelInterval,
) -> ComplementResult<HalfBoundedRelInterval> {
ComplementResult::Single(HalfBoundedRelInterval::from_offset_incl(
interval.reference_offset(),
interval.reference_inclusivity().opposite(),
interval.opening_direction().opposite(),
))
}