use std::cmp::Ordering;
use std::ops::RangeBounds;
#[cfg(feature = "arbitrary")]
use arbitrary::Arbitrary;
use jiff::Timestamp;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::intervals::absolute::{
AbsBoundPair,
AbsEndBound,
AbsInterval,
AbsStartBound,
BoundedAbsInterval,
EmptiableAbsBoundPair,
HalfBoundedAbsInterval,
HalfBoundedToFutureAbsInterval,
HalfBoundedToPastAbsInterval,
HasAbsBoundPair,
HasEmptiableAbsBoundPair,
};
use crate::intervals::meta::{
Duration as IntervalDuration,
HasDuration,
HasIntervalTypeWithRel,
HasOpenness,
HasRelativity,
Interval,
IntervalTypeWithRel,
IsEmpty,
Openness,
Relativity,
};
use crate::intervals::special::{EmptyInterval, UnboundedInterval};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub enum EmptiableAbsInterval {
Bound(AbsInterval),
Empty(EmptyInterval),
}
impl EmptiableAbsInterval {
#[must_use]
pub fn from_range<R>(range: R) -> Self
where
R: RangeBounds<Timestamp>,
{
AbsInterval::from_range(range).to_emptiable()
}
#[must_use]
pub fn bound(self) -> Option<AbsInterval> {
match self {
Self::Bound(interval) => Some(interval),
Self::Empty(_) => None,
}
}
#[must_use]
pub fn ord_by_start_and_inv_length(&self, other: &Self) -> Ordering {
self.emptiable_abs_bound_pair()
.ord_by_start_and_inv_length(&other.emptiable_abs_bound_pair())
}
}
impl Interval for EmptiableAbsInterval {}
impl HasDuration for EmptiableAbsInterval {
fn duration(&self) -> IntervalDuration {
match self {
Self::Bound(interval) => interval.duration(),
Self::Empty(empty) => empty.duration(),
}
}
}
impl HasRelativity for EmptiableAbsInterval {
fn relativity(&self) -> Relativity {
match self {
Self::Bound(interval) => interval.relativity(),
Self::Empty(empty) => empty.relativity(),
}
}
}
impl HasOpenness for EmptiableAbsInterval {
fn openness(&self) -> Openness {
match self {
Self::Bound(interval) => interval.openness(),
Self::Empty(empty) => empty.openness(),
}
}
}
impl HasEmptiableAbsBoundPair for EmptiableAbsInterval {
fn emptiable_abs_bound_pair(&self) -> EmptiableAbsBoundPair {
match self {
Self::Bound(interval) => EmptiableAbsBoundPair::from(interval.abs_bound_pair()),
Self::Empty(interval) => interval.emptiable_abs_bound_pair(),
}
}
fn partial_abs_start(&self) -> Option<AbsStartBound> {
match self {
Self::Bound(interval) => interval.partial_abs_start(),
Self::Empty(interval) => interval.partial_abs_start(),
}
}
fn partial_abs_end(&self) -> Option<AbsEndBound> {
match self {
Self::Bound(interval) => interval.partial_abs_end(),
Self::Empty(interval) => interval.partial_abs_end(),
}
}
}
impl IsEmpty for EmptiableAbsInterval {
fn is_empty(&self) -> bool {
matches!(self, Self::Empty(_))
}
}
impl HasIntervalTypeWithRel for EmptiableAbsInterval {
fn interval_type_with_rel(&self) -> IntervalTypeWithRel {
match self {
Self::Empty(_) => IntervalTypeWithRel::Empty,
Self::Bound(interval) => interval.interval_type_with_rel(),
}
}
}
impl PartialOrd for EmptiableAbsInterval {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for EmptiableAbsInterval {
fn cmp(&self, other: &Self) -> Ordering {
self.emptiable_abs_bound_pair().cmp(&other.emptiable_abs_bound_pair())
}
}
impl From<BoundedAbsInterval> for EmptiableAbsInterval {
fn from(value: BoundedAbsInterval) -> Self {
EmptiableAbsInterval::Bound(value.to_interval())
}
}
impl From<HalfBoundedToFutureAbsInterval> for EmptiableAbsInterval {
fn from(value: HalfBoundedToFutureAbsInterval) -> Self {
EmptiableAbsInterval::Bound(value.to_interval())
}
}
impl From<HalfBoundedToPastAbsInterval> for EmptiableAbsInterval {
fn from(value: HalfBoundedToPastAbsInterval) -> Self {
EmptiableAbsInterval::Bound(value.to_interval())
}
}
impl From<HalfBoundedAbsInterval> for EmptiableAbsInterval {
fn from(value: HalfBoundedAbsInterval) -> Self {
EmptiableAbsInterval::Bound(value.to_interval())
}
}
impl From<UnboundedInterval> for EmptiableAbsInterval {
fn from(value: UnboundedInterval) -> Self {
EmptiableAbsInterval::Bound(AbsInterval::Unbounded(value))
}
}
impl From<EmptyInterval> for EmptiableAbsInterval {
fn from(value: EmptyInterval) -> Self {
EmptiableAbsInterval::Empty(value)
}
}
impl From<AbsBoundPair> for EmptiableAbsInterval {
fn from(value: AbsBoundPair) -> Self {
EmptiableAbsInterval::Bound(AbsInterval::from(value))
}
}
impl From<EmptiableAbsBoundPair> for EmptiableAbsInterval {
fn from(value: EmptiableAbsBoundPair) -> Self {
match value.bound() {
Some(abs_bound_pair) => Self::from(abs_bound_pair),
None => Self::Empty(EmptyInterval),
}
}
}
impl From<AbsInterval> for EmptiableAbsInterval {
fn from(value: AbsInterval) -> Self {
Self::Bound(value)
}
}
impl From<()> for EmptiableAbsInterval {
fn from(_value: ()) -> Self {
EmptiableAbsInterval::Empty(EmptyInterval)
}
}