use std::ops::Neg;
use crate::*;
use crate::iter::TimeUnion;
pub type TimeSpans = TimeSet<TimeValue>;
pub type TimeSlots = TimeSet<Timestamp>;
#[derive(Clone, Eq, Hash)]
pub struct TimeSet<T:TimePoint>(pub(crate) Vec<TimeInterval<T>>);
impl<T:TimePoint> TimeSet<T>
{
#[inline]
pub fn all() -> Self { Self(vec![TimeInterval::all()]) }
#[inline]
pub fn convex(lower: T, upper: T) -> Self
{
let tw = TimeInterval::new(lower, upper);
if tw.is_empty() { Self::empty() } else { Self(vec![tw]) }
}
#[inline]
pub fn singleton(t: T) -> Self {
Self(vec![TimeInterval::singleton(t)])
}
#[inline]
pub fn empty() -> Self { Self(vec![]) }
#[inline]
pub fn shrink_to_fit(&mut self) { self.0.shrink_to_fit() }
}
impl<T:TimePoint> TimeBounds for TimeSet<T>
{
type TimePoint = T;
#[inline]
fn is_empty(&self) -> bool { self.0.is_empty() }
#[inline]
fn is_singleton(&self) -> bool {
(self.0.len() == 1) && unsafe { self.0.get_unchecked(0).is_singleton() }
}
#[inline]
fn is_bounded(&self) -> bool {
self.is_low_bounded() && self.is_up_bounded()
}
#[inline]
fn is_low_bounded(&self) -> bool {
self.0.first().map(|s| s.is_low_bounded()).unwrap_or(false)
}
#[inline]
fn is_up_bounded(&self) -> bool {
self.0.last().map(|s| s.is_up_bounded()).unwrap_or(false)
}
#[inline]
fn lower_bound(&self) -> Self::TimePoint {
self.0.first()
.map(|i| i.lower_bound())
.unwrap_or(Self::TimePoint::INFINITE)
}
#[inline]
fn upper_bound(&self) -> Self::TimePoint {
self.0.last()
.map(|i| i.upper_bound())
.unwrap_or(-Self::TimePoint::INFINITE)
}
}
impl<T:TimePoint> TimeWindow for TimeSet<T>
{
#[inline]
fn convex_count(&self) -> usize { self.0.len() }
type ConvexIter = crate::iter::intoiter::IntoConvexIter<T,std::vec::IntoIter<TimeInterval<T>>>;
fn iter(&self) -> Self::ConvexIter {
crate::iter::intoiter::IntoConvexIter(self.0.clone().into_iter())
}
}
impl<T:TimePoint> Neg for TimeSet<T>
{
type Output = Self;
#[inline] fn neg(self) -> Self {
Self(self.0.iter().rev().map(|&t| -t).collect())
}
}
impl<T:TimePoint> FromIterator<TimeInterval<T>> for TimeSet<T>
{
fn from_iter<I: IntoIterator<Item=TimeInterval<T>>>(iter: I) -> Self
{
let mut iter = iter.into_iter()
.filter(|i| !i.is_empty());
match iter.next() {
None => Self::empty(),
Some(i) => {
iter.fold(i.into(), |mut r,i| {
if i.lower_bound() > r.upper_bound().just_after() {
r.0.push(i); r
} else {
r.into_iter().union(i).collect()
}
})
}
}
}
}
impl<T:TimePoint> FromIterator<TimeSet<T>> for TimeSet<T>
{
fn from_iter<I: IntoIterator<Item=TimeSet<T>>>(iter: I) -> Self
{
iter.into_iter()
.reduce(|r,s| r|s)
.unwrap_or(TimeSet::empty())
}
}
impl<T,TW> From<TW> for TimeSet<T>
where
T:TimePoint,
TW:TimeConvex<TimePoint=T>
{
#[inline] fn from(tw: TW) -> Self
{
if tw.is_empty() {
TimeSet::empty()
} else {
Self(vec![TimeInterval { lower: tw.lower_bound(), upper: tw.upper_bound()}])
}
}
}