use jiff::SignedDuration;
use crate::intervals::ops::precision::relative::bound::{
precise_rel_end_bound,
precise_rel_end_bound_with_base_offset,
precise_rel_start_bound,
precise_rel_start_bound_with_base_offset,
};
use crate::intervals::relative::{
EmptiableRelBoundPair,
EmptiableRelInterval,
HasEmptiableRelBoundPair,
HasRelBoundPair,
RelBoundPair,
RelInterval,
};
use crate::intervals::special::EmptyInterval;
use crate::ops::{Precision, PrecisionOutOfRangeError};
pub trait PreciseRelInterval {
type PrecisedIntervalOutput;
#[must_use]
fn precise_different_precisions(
&self,
precision_start: Precision,
precision_end: Precision,
) -> Self::PrecisedIntervalOutput;
#[must_use]
fn precise(&self, precision: Precision) -> Self::PrecisedIntervalOutput {
self.precise_different_precisions(precision, precision)
}
#[must_use]
fn precise_different_precisions_with_base_offset(
&self,
precision_start: Precision,
base_start: SignedDuration,
precision_end: Precision,
base_end: SignedDuration,
) -> Self::PrecisedIntervalOutput;
#[must_use]
fn precise_with_base_offset(&self, precision: Precision, base: SignedDuration) -> Self::PrecisedIntervalOutput {
self.precise_different_precisions_with_base_offset(precision, base, precision, base)
}
}
impl PreciseRelInterval for RelBoundPair {
type PrecisedIntervalOutput = Result<Self, PrecisionOutOfRangeError>;
fn precise_different_precisions(
&self,
precision_start: Precision,
precision_end: Precision,
) -> Self::PrecisedIntervalOutput {
precise_rel_bound_pair(self, precision_start, precision_end)
}
fn precise_different_precisions_with_base_offset(
&self,
precision_start: Precision,
base_start: SignedDuration,
precision_end: Precision,
base_end: SignedDuration,
) -> Self::PrecisedIntervalOutput {
precise_rel_bound_pair_with_base_offset(self, precision_start, base_start, precision_end, base_end)
}
}
impl PreciseRelInterval for EmptiableRelBoundPair {
type PrecisedIntervalOutput = Result<Self, PrecisionOutOfRangeError>;
fn precise_different_precisions(
&self,
precision_start: Precision,
precision_end: Precision,
) -> Self::PrecisedIntervalOutput {
if let Self::Bound(rel_bound_pair) = self {
Ok(precise_rel_bound_pair(rel_bound_pair, precision_start, precision_end)?.to_emptiable())
} else {
Ok(Self::Empty)
}
}
fn precise_different_precisions_with_base_offset(
&self,
precision_start: Precision,
base_start: SignedDuration,
precision_end: Precision,
base_end: SignedDuration,
) -> Self::PrecisedIntervalOutput {
if let Self::Bound(rel_bound_pair) = self {
Ok(precise_rel_bound_pair_with_base_offset(
rel_bound_pair,
precision_start,
base_start,
precision_end,
base_end,
)?
.to_emptiable())
} else {
Ok(Self::Empty)
}
}
}
impl PreciseRelInterval for RelInterval {
type PrecisedIntervalOutput = Result<Self, PrecisionOutOfRangeError>;
fn precise_different_precisions(
&self,
precision_start: Precision,
precision_end: Precision,
) -> Self::PrecisedIntervalOutput {
Ok(precise_rel_bound_pair(&self.rel_bound_pair(), precision_start, precision_end)?.to_interval())
}
fn precise_different_precisions_with_base_offset(
&self,
precision_start: Precision,
base_start: SignedDuration,
precision_end: Precision,
base_end: SignedDuration,
) -> Self::PrecisedIntervalOutput {
Ok(precise_rel_bound_pair_with_base_offset(
&self.rel_bound_pair(),
precision_start,
base_start,
precision_end,
base_end,
)?
.to_interval())
}
}
impl PreciseRelInterval for EmptiableRelInterval {
type PrecisedIntervalOutput = Result<Self, PrecisionOutOfRangeError>;
fn precise_different_precisions(
&self,
precision_start: Precision,
precision_end: Precision,
) -> Self::PrecisedIntervalOutput {
if let EmptiableRelBoundPair::Bound(ref rel_bound_pair) = self.emptiable_rel_bound_pair() {
Ok(precise_rel_bound_pair(rel_bound_pair, precision_start, precision_end)?.to_emptiable_interval())
} else {
Ok(Self::Empty(EmptyInterval))
}
}
fn precise_different_precisions_with_base_offset(
&self,
precision_start: Precision,
base_start: SignedDuration,
precision_end: Precision,
base_end: SignedDuration,
) -> Self::PrecisedIntervalOutput {
if let EmptiableRelBoundPair::Bound(ref rel_bound_pair) = self.emptiable_rel_bound_pair() {
Ok(precise_rel_bound_pair_with_base_offset(
rel_bound_pair,
precision_start,
base_start,
precision_end,
base_end,
)?
.to_emptiable_interval())
} else {
Ok(Self::Empty(EmptyInterval))
}
}
}
pub fn precise_rel_bound_pair(
bound_pair: &RelBoundPair,
precision_start: Precision,
precision_end: Precision,
) -> Result<RelBoundPair, PrecisionOutOfRangeError> {
Ok(RelBoundPair::new(
precise_rel_start_bound(&bound_pair.start(), precision_start)?,
precise_rel_end_bound(&bound_pair.end(), precision_end)?,
))
}
pub fn precise_rel_bound_pair_with_base_offset(
bound_pair: &RelBoundPair,
precision_start: Precision,
base_start: SignedDuration,
precision_end: Precision,
base_end: SignedDuration,
) -> Result<RelBoundPair, PrecisionOutOfRangeError> {
Ok(RelBoundPair::new(
precise_rel_start_bound_with_base_offset(&bound_pair.start(), precision_start, base_start)?,
precise_rel_end_bound_with_base_offset(&bound_pair.end(), precision_end, base_end)?,
))
}