use std::error::Error;
use std::fmt::Display;
use super::grow::{GrowableEndBound, GrowableStartBound};
use super::overlap::{CanPositionOverlap, DisambiguatedOverlapPosition, OverlapRuleSet};
use crate::intervals::absolute::{
AbsBoundPair,
AbsEndBound,
AbsFiniteBoundPos,
AbsInterval,
AbsStartBound,
BoundedAbsInterval,
EmptiableAbsBoundPair,
EmptiableAbsInterval,
HalfBoundedAbsInterval,
HasAbsBoundPair,
HasEmptiableAbsBoundPair,
};
use crate::intervals::meta::{HasBoundInclusivity, Interval};
use crate::intervals::relative::{
BoundedRelInterval,
EmptiableRelBoundPair,
EmptiableRelInterval,
HalfBoundedRelInterval,
HasEmptiableRelBoundPair,
HasRelBoundPair,
RelBoundPair,
RelEndBound,
RelFiniteBoundPos,
RelInterval,
RelStartBound,
};
use crate::intervals::special::EmptyInterval;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct GapFillOverlapFoundError;
impl Display for GapFillOverlapFoundError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "The two given intervals were overlapping")
}
}
impl Error for GapFillOverlapFoundError {}
pub trait GapFillable<Rhs = Self> {
type Output;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError>;
}
impl<Rhs> GapFillable<Rhs> for AbsBoundPair
where
Rhs: HasEmptiableAbsBoundPair,
{
type Output = Self;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError> {
fill_gap_abs_bound_pair_with_emptiable_abs_bound_pair(self, &rhs.emptiable_abs_bound_pair())
}
}
impl<Rhs> GapFillable<Rhs> for EmptiableAbsBoundPair
where
Rhs: HasEmptiableAbsBoundPair,
{
type Output = Self;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError> {
fill_gap_emptiable_abs_bound_pair(self, &rhs.emptiable_abs_bound_pair())
}
}
impl<Rhs> GapFillable<Rhs> for AbsInterval
where
Rhs: HasEmptiableAbsBoundPair,
{
type Output = Self;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError> {
fill_gap_abs_bound_pair_with_emptiable_abs_bound_pair(&self.abs_bound_pair(), &rhs.emptiable_abs_bound_pair())
.map(Self::Output::from)
}
}
impl<Rhs> GapFillable<Rhs> for EmptiableAbsInterval
where
Rhs: HasEmptiableAbsBoundPair,
{
type Output = Self;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError> {
fill_gap_emptiable_abs_bound_pair(&self.emptiable_abs_bound_pair(), &rhs.emptiable_abs_bound_pair())
.map(Self::Output::from)
}
}
impl<Rhs> GapFillable<Rhs> for BoundedAbsInterval
where
Rhs: HasEmptiableAbsBoundPair,
{
type Output = AbsInterval;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError> {
fill_gap_abs_bound_pair_with_emptiable_abs_bound_pair(&self.abs_bound_pair(), &rhs.emptiable_abs_bound_pair())
.map(Self::Output::from)
}
}
impl<Rhs> GapFillable<Rhs> for HalfBoundedAbsInterval
where
Rhs: HasEmptiableAbsBoundPair,
{
type Output = AbsInterval;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError> {
fill_gap_abs_bound_pair_with_emptiable_abs_bound_pair(&self.abs_bound_pair(), &rhs.emptiable_abs_bound_pair())
.map(Self::Output::from)
}
}
impl<Rhs> GapFillable<Rhs> for RelBoundPair
where
Rhs: HasEmptiableRelBoundPair,
{
type Output = Self;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError> {
fill_gap_rel_bound_pair_with_emptiable_rel_bound_pair(self, &rhs.emptiable_rel_bound_pair())
}
}
impl<Rhs> GapFillable<Rhs> for EmptiableRelBoundPair
where
Rhs: HasEmptiableRelBoundPair,
{
type Output = Self;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError> {
fill_gap_emptiable_rel_bound_pair(self, &rhs.emptiable_rel_bound_pair())
}
}
impl<Rhs> GapFillable<Rhs> for RelInterval
where
Rhs: HasEmptiableRelBoundPair,
{
type Output = Self;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError> {
fill_gap_rel_bound_pair_with_emptiable_rel_bound_pair(&self.rel_bound_pair(), &rhs.emptiable_rel_bound_pair())
.map(Self::Output::from)
}
}
impl<Rhs> GapFillable<Rhs> for EmptiableRelInterval
where
Rhs: HasEmptiableRelBoundPair,
{
type Output = Self;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError> {
fill_gap_emptiable_rel_bound_pair(&self.emptiable_rel_bound_pair(), &rhs.emptiable_rel_bound_pair())
.map(Self::Output::from)
}
}
impl<Rhs> GapFillable<Rhs> for BoundedRelInterval
where
Rhs: HasEmptiableRelBoundPair,
{
type Output = RelInterval;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError> {
fill_gap_rel_bound_pair_with_emptiable_rel_bound_pair(&self.rel_bound_pair(), &rhs.emptiable_rel_bound_pair())
.map(Self::Output::from)
}
}
impl<Rhs> GapFillable<Rhs> for HalfBoundedRelInterval
where
Rhs: HasEmptiableRelBoundPair,
{
type Output = RelInterval;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError> {
fill_gap_rel_bound_pair_with_emptiable_rel_bound_pair(&self.rel_bound_pair(), &rhs.emptiable_rel_bound_pair())
.map(Self::Output::from)
}
}
impl<Rhs> GapFillable<Rhs> for EmptyInterval
where
Rhs: Interval + Clone,
{
type Output = Rhs;
fn fill_gap(&self, rhs: &Rhs) -> Result<Self::Output, GapFillOverlapFoundError> {
Ok(rhs.clone())
}
}
pub fn fill_gap_abs_bound_pair(a: &AbsBoundPair, b: &AbsBoundPair) -> Result<AbsBoundPair, GapFillOverlapFoundError> {
type Dop = DisambiguatedOverlapPosition;
let Ok(overlap_position) = a.disambiguated_overlap_position(b, OverlapRuleSet::Strict);
match overlap_position {
Dop::Outside => unreachable!("Only empty intervals can produce `OverlapPosition::Outside`"),
Dop::OutsideBefore => {
let AbsStartBound::Finite(finite_bound_position) = b.abs_start() else {
unreachable!(
"If the start of the compared bounds is `InfinitePast`, then it is impossible that the overlap \
was `OutsideBefore`"
);
};
let new_end_bound = AbsFiniteBoundPos::new_with_incl(
finite_bound_position.pos().time(),
finite_bound_position.pos().inclusivity().opposite(), )
.to_end_bound();
Ok(a.grow_end(new_end_bound))
},
Dop::OutsideAfter => {
let AbsEndBound::Finite(finite_bound_position) = b.abs_end() else {
unreachable!(
"If the end of the compared bounds is `InfiniteFuture`, then it is impossible that the overlap \
was `OutsideAfter`"
);
};
let new_start_bound = AbsFiniteBoundPos::new_with_incl(
finite_bound_position.pos().time(),
finite_bound_position.pos().inclusivity().opposite(), )
.to_start_bound();
Ok(a.grow_start(new_start_bound))
},
_ => Err(GapFillOverlapFoundError),
}
}
pub fn fill_gap_abs_bound_pair_with_emptiable_abs_bound_pair(
a: &AbsBoundPair,
b: &EmptiableAbsBoundPair,
) -> Result<AbsBoundPair, GapFillOverlapFoundError> {
let EmptiableAbsBoundPair::Bound(b_abs_bound_pair) = b else {
return Ok(a.clone());
};
fill_gap_abs_bound_pair(a, b_abs_bound_pair)
}
pub fn fill_gap_emptiable_abs_bound_pair(
a: &EmptiableAbsBoundPair,
b: &EmptiableAbsBoundPair,
) -> Result<EmptiableAbsBoundPair, GapFillOverlapFoundError> {
let EmptiableAbsBoundPair::Bound(a_abs_bound_pair) = a else {
return Ok(b.clone());
};
fill_gap_abs_bound_pair_with_emptiable_abs_bound_pair(a_abs_bound_pair, b).map(EmptiableAbsBoundPair::from)
}
pub fn fill_gap_rel_bound_pair(a: &RelBoundPair, b: &RelBoundPair) -> Result<RelBoundPair, GapFillOverlapFoundError> {
type Dop = DisambiguatedOverlapPosition;
let Ok(overlap_position) = a.disambiguated_overlap_position(b, OverlapRuleSet::Strict);
match overlap_position {
Dop::Outside => unreachable!("Only empty intervals can produce `OverlapPosition::Outside`"),
Dop::OutsideBefore => {
let RelStartBound::Finite(finite_bound_position) = b.rel_start() else {
unreachable!(
"If the start of the compared bounds is `InfinitePast`, then it is impossible that the overlap \
was `OutsideBefore`"
);
};
let new_end_bound = RelFiniteBoundPos::new_with_incl(
finite_bound_position.pos().offset(),
finite_bound_position.pos().inclusivity().opposite(), )
.to_end_bound();
Ok(a.grow_end(new_end_bound))
},
Dop::OutsideAfter => {
let RelEndBound::Finite(finite_bound_position) = b.rel_end() else {
unreachable!(
"If the end of the compared bounds is `InfiniteFuture`, then it is impossible that the overlap \
was `OutsideAfter`"
);
};
let new_start_bound = RelFiniteBoundPos::new_with_incl(
finite_bound_position.pos().offset(),
finite_bound_position.pos().inclusivity().opposite(), )
.to_start_bound();
Ok(a.grow_start(new_start_bound))
},
_ => Err(GapFillOverlapFoundError),
}
}
pub fn fill_gap_rel_bound_pair_with_emptiable_rel_bound_pair(
a: &RelBoundPair,
b: &EmptiableRelBoundPair,
) -> Result<RelBoundPair, GapFillOverlapFoundError> {
let EmptiableRelBoundPair::Bound(b_rel_bound_pair) = b else {
return Ok(a.clone());
};
fill_gap_rel_bound_pair(a, b_rel_bound_pair)
}
pub fn fill_gap_emptiable_rel_bound_pair(
a: &EmptiableRelBoundPair,
b: &EmptiableRelBoundPair,
) -> Result<EmptiableRelBoundPair, GapFillOverlapFoundError> {
let EmptiableRelBoundPair::Bound(a_rel_bound_pair) = a else {
return Ok(b.clone());
};
fill_gap_rel_bound_pair_with_emptiable_rel_bound_pair(a_rel_bound_pair, b).map(EmptiableRelBoundPair::from)
}