//! The module for the TimeType
//!
use chrono::NaiveDateTime;
use std::ops::Add;
use std::ops::Sub;
use result::Result;
/// A Type of Time, currently based on chrono::NaiveDateTime
#[derive(Debug)]
pub enum TimeType {
Seconds(usize),
Minutes(usize),
Hours(usize),
Days(usize),
Weeks(usize),
Months(usize),
Years(usize),
Moment(NaiveDateTime),
Addition(Box<TimeType>, Box<TimeType>),
Subtraction(Box<TimeType>, Box<TimeType>),
}
impl Add for TimeType {
type Output = TimeType;
fn add(self, rhs: TimeType) -> Self::Output {
TimeType::Addition(Box::new(self), Box::new(rhs))
}
}
impl Sub for TimeType {
type Output = TimeType;
fn sub(self, rhs: TimeType) -> Self::Output {
TimeType::Subtraction(Box::new(self), Box::new(rhs))
}
}
impl TimeType {
fn calculate(self) -> Result<TimeType> {
use timetype::TimeType as TT;
match self {
TT::Addition(a, b) => add(a, b),
TT::Subtraction(a, b) => sub(a, b),
x => Ok(x)
}
}
}
fn add(a: Box<TimeType>, b: Box<TimeType>) -> Result<TimeType> {
use timetype::TimeType as TT;
match (*a, *b) {
(TT::Seconds(a), TT::Seconds(b)) => Ok(TT::Seconds(a + b)),
(TT::Minutes(a), TT::Minutes(b)) => unimplemented!(),
(TT::Hours(a), TT::Hours(b)) => unimplemented!(),
(TT::Days(a), TT::Days(b)) => unimplemented!(),
(TT::Weeks(a), TT::Weeks(b)) => unimplemented!(),
(TT::Months(a), TT::Months(b)) => unimplemented!(),
(TT::Years(a), TT::Years(b)) => unimplemented!(),
(TT::Addition(a, b), other) => add(a, b)
.map(Box::new)
.and_then(|bx| add(bx, Box::new(other))),
others => unimplemented!(),
}
}
fn sub(a: Box<TimeType>, b: Box<TimeType>) -> Result<TimeType> {
use timetype::TimeType as TT;
match (*a, *b) {
(TT::Seconds(a), TT::Seconds(b)) => Ok(TT::Seconds(a - b)),
(TT::Minutes(a), TT::Minutes(b)) => unimplemented!(),
(TT::Hours(a), TT::Hours(b)) => unimplemented!(),
(TT::Days(a), TT::Days(b)) => unimplemented!(),
(TT::Weeks(a), TT::Weeks(b)) => unimplemented!(),
(TT::Months(a), TT::Months(b)) => unimplemented!(),
(TT::Years(a), TT::Years(b)) => unimplemented!(),
(TT::Subtraction(a, b), other) => sub(a, b)
.map(Box::new)
.and_then(|bx| sub(bx, Box::new(other))),
others => unimplemented!(),
}
}
#[cfg(test)]
mod tests {
use super::TimeType as TT;
#[test]
fn test_addition_of_seconds() {
let a = TT::Seconds(0);
let b = TT::Seconds(1);
let c = a + b;
match c {
TT::Addition(a, b) => {
match (*a, *b) {
(TT::Seconds(0), TT::Seconds(1)) => assert!(true),
_ => assert!(false, "Addition failed"),
}
}
_ => assert!(false,