use std;
use std::cmp::{Ordering, max, min};
use std::ops::*;
macro_rules! impl_from {
($f:ty, $t:ty) => {
impl From<$f> for $t { fn from(t: $f) -> $t { t.0 as $t } }
}
}
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct TimeDelta(i64);
impl TimeDelta {
pub fn zero() -> TimeDelta {
TimeDelta(Default::default())
}
pub fn one() -> TimeDelta {
TimeDelta(1)
}
}
impl_from!(TimeDelta, i32);
impl_from!(TimeDelta, u32);
impl_from!(TimeDelta, i64);
impl_from!(TimeDelta, u64);
impl std::iter::Sum for TimeDelta {
fn sum<I: Iterator<Item = TimeDelta>>(iter: I) -> TimeDelta {
TimeDelta(iter.map(|d| d.0).sum())
}
}
impl std::fmt::Display for TimePoint {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl std::fmt::Display for TimeDelta {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl Add for TimeDelta {
type Output = TimeDelta;
fn add(self, rhs: TimeDelta) -> TimeDelta {
TimeDelta(self.0 + rhs.0)
}
}
impl AddAssign<TimeDelta> for TimeDelta {
fn add_assign(&mut self, rhs: TimeDelta) {
self.0 += rhs.0;
}
}
impl Sub<TimeDelta> for TimeDelta {
type Output = TimeDelta;
fn sub(self, rhs: TimeDelta) -> TimeDelta {
TimeDelta(self.0 - rhs.0)
}
}
impl SubAssign<TimeDelta> for TimeDelta {
fn sub_assign(&mut self, rhs: TimeDelta) {
self.0 -= rhs.0;
}
}
impl Mul<i64> for TimeDelta {
type Output = TimeDelta;
fn mul(self, rhs: i64) -> TimeDelta {
TimeDelta(self.0 * rhs)
}
}
impl MulAssign<i64> for TimeDelta {
fn mul_assign(&mut self, rhs: i64) {
self.0 *= rhs;
}
}
impl Mul<TimeDelta> for i64 {
type Output = TimeDelta;
fn mul(self, rhs: TimeDelta) -> TimeDelta {
TimeDelta(self * rhs.0)
}
}
impl Neg for TimeDelta {
type Output = TimeDelta;
fn neg(self) -> TimeDelta {
TimeDelta(-self.0)
}
}
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct TimePoint(i64);
impl From<i64> for TimePoint {
fn from(f: i64) -> TimePoint {
TimePoint(f)
}
}
impl_from!(TimePoint, i64);
impl Sub for TimePoint {
type Output = TimeDelta;
fn sub(self, rhs: TimePoint) -> TimeDelta {
TimeDelta(self.0 - rhs.0)
}
}
impl Add<TimeDelta> for TimePoint {
type Output = TimePoint;
fn add(self, rhs: TimeDelta) -> TimePoint {
TimePoint(self.0 + rhs.0)
}
}
impl AddAssign<TimeDelta> for TimePoint {
fn add_assign(&mut self, rhs: TimeDelta) {
self.0 += rhs.0;
}
}
impl Sub<TimeDelta> for TimePoint {
type Output = TimePoint;
fn sub(self, rhs: TimeDelta) -> TimePoint {
TimePoint(self.0 - rhs.0)
}
}
impl SubAssign<TimeDelta> for TimePoint {
fn sub_assign(&mut self, rhs: TimeDelta) {
self.0 -= rhs.0;
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct TimeSpan {
start: TimePoint,
end: TimePoint,
}
impl TimeSpan {
pub fn new(start: TimePoint, end: TimePoint) -> TimeSpan {
assert!(start <= end);
TimeSpan {
start: start,
end: end,
}
}
pub fn new_safe(start: TimePoint, end: TimePoint) -> TimeSpan {
if end < start {
TimeSpan::new(end, start)
} else {
TimeSpan::new(start, end)
}
}
pub fn new_copy_with_end(self, new_end: TimePoint) -> TimeSpan {
TimeSpan::new(self.start, new_end)
}
pub fn len(self) -> TimeDelta {
self.end - self.start
}
pub fn is_empty(self) -> bool {
self.end == self.start
}
pub fn start(self) -> TimePoint {
self.start
}
pub fn end(self) -> TimePoint {
self.end
}
pub fn contains(self, other: TimeSpan) -> bool {
other.start >= self.start && other.end <= self.end
}
pub fn fast_distance_to(self, other: TimeSpan) -> TimeDelta {
if self.end < other.start {
other.start - self.end
}
else if self.start > other.end {
self.start - other.end
}
else {
TimeDelta::zero()
}
}
pub fn get_overlapping_length(self, other: TimeSpan) -> TimeDelta {
let start_max = max(self.start, other.start);
let end_min = min(self.end, other.end);
max(TimeDelta::zero(), end_min - start_max)
}
pub fn cmp_start(self, other: TimeSpan) -> Ordering {
self.start.cmp(&other.start)
}
pub fn cmp_end(self, other: TimeSpan) -> Ordering {
self.end.cmp(&other.end)
}
}
impl Add<TimeDelta> for TimeSpan {
type Output = TimeSpan;
fn add(self, rhs: TimeDelta) -> TimeSpan {
TimeSpan::new(self.start + rhs, self.end + rhs)
}
}