diff options
Diffstat (limited to 'src/parser.rs')
-rw-r--r-- | src/parser.rs | 312 |
1 files changed, 306 insertions, 6 deletions
diff --git a/src/parser.rs b/src/parser.rs index 7a2e7a1..723f4f3 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -50,6 +50,8 @@ use std::str::FromStr; use chrono::NaiveDate; use timetype; +use iter; +use error; named!(integer<i64>, alt!( map_res!( @@ -345,18 +347,92 @@ pub enum UntilSpec { } named!(iterator<Iterator>, do_parse!( - d: date >> - spec: iter_spec >> - until: opt!(until_spec) >> + opt!(sp) >> d: date >> + opt!(sp) >> spec: iter_spec >> + opt!(sp) >> until: opt!(complete!(until_spec)) >> (Iterator(d, spec, until)) )); #[derive(Debug, PartialEq, Eq)] pub struct Iterator(Date, Iterspec, Option<UntilSpec>); -impl Into<timetype::TimeType> for Iterator { - fn into(self) -> timetype::TimeType { - unimplemented!() +impl Iterator { + pub fn into_user_iterator(self) -> error::Result<UserIterator<iter::Iter>> { + use iter::Times; + use iter::Until; + + let unit_to_amount = |i, unit| match unit { + Unit::Second => timetype::TimeType::seconds(i), + Unit::Minute => timetype::TimeType::minutes(i), + Unit::Hour => timetype::TimeType::hours(i), + Unit::Day => timetype::TimeType::days(i), + Unit::Week => timetype::TimeType::weeks(i), + Unit::Month => timetype::TimeType::months(i), + Unit::Year => timetype::TimeType::years(i), + }; + + let recur = match self.1 { + Iterspec::Every(i, unit) => unit_to_amount(i, unit), + Iterspec::Secondly => unit_to_amount(1, Unit::Second), + Iterspec::Minutely => unit_to_amount(1, Unit::Minute), + Iterspec::Hourly => unit_to_amount(1, Unit::Hour), + Iterspec::Daily => unit_to_amount(1, Unit::Day), + Iterspec::Weekly => unit_to_amount(1, Unit::Week), + Iterspec::Monthly => unit_to_amount(1, Unit::Month), + Iterspec::Yearly => unit_to_amount(1, Unit::Year), + }; + + let into_ndt = |e: timetype::TimeType| try!(e.calculate()) + .get_moment() + .ok_or(error::KairosErrorKind::NotADateInsideIterator) + .map(Clone::clone); + + match self.2 { + Some(UntilSpec::Exact(e)) => { + let base = try!(into_ndt(self.0.into())); + let e = try!(into_ndt(e.into())); + + iter::Iter::build(base, recur) + .map(|it| UserIterator::UntilIterator(it.until(e))) + }, + + Some(UntilSpec::Times(i)) => { + let base = try!(into_ndt(self.0.into())); + iter::Iter::build(base, recur) + .map(|it| it.times(i)) + .map(UserIterator::TimesIter) + }, + + None => { + let base = try!(into_ndt(self.0.into())); + iter::Iter::build(base, recur) + .map(UserIterator::Iterator) + }, + } + } +} + +// names are hard +#[derive(Debug)] +pub enum UserIterator<I> + where I: ::std::iter::Iterator<Item = error::Result<timetype::TimeType>> +{ + Iterator(iter::Iter), + TimesIter(iter::TimesIter<I>), + UntilIterator(iter::UntilIter<I>) +} + +impl<I> ::std::iter::Iterator for UserIterator<I> + where I: ::std::iter::Iterator<Item = error::Result<timetype::TimeType>> +{ + type Item = error::Result<timetype::TimeType>; + + fn next(&mut self) -> Option<Self::Item> { + match *self { + UserIterator::Iterator(ref mut i) => i.next(), + UserIterator::TimesIter(ref mut i) => i.next(), + UserIterator::UntilIterator(ref mut i) => i.next(), + } } } @@ -698,5 +774,229 @@ mod tests { assert_eq!(calc_res.get_years(), 0); } + #[test] + fn test_iterator_1() { + let res = iterator(&b"2017-01-01 hourly"[..]); + assert!(res.is_done(), format!("Not done: {:?}", res)); + let (_, i) = res.unwrap(); + println!("{:#?}", i); + + let ui : Result<UserIterator<iter::Iter>, _> = i.into_user_iterator(); + assert!(ui.is_ok(), "Not okay: {:#?}", ui); + let mut ui = ui.unwrap(); + + for hour in 1..10 { // 10 is randomly chosen (fair dice roll... ) + let n = ui.next().unwrap(); + assert!(n.is_ok(), "Not ok: {:#?}", n); + let tt = n.unwrap(); + assert_eq!(tt.get_moment().unwrap().year() , 2017); + assert_eq!(tt.get_moment().unwrap().month() , 01); + assert_eq!(tt.get_moment().unwrap().day() , 01); + assert_eq!(tt.get_moment().unwrap().hour() , hour); + assert_eq!(tt.get_moment().unwrap().minute(), 00); + assert_eq!(tt.get_moment().unwrap().second(), 00); + } + } + + #[test] + fn test_iterator_2() { + let res = iterator(&b"2017-01-01 every 2mins"[..]); + assert!(res.is_done(), format!("Not done: {:?}", res)); + let (_, i) = res.unwrap(); + println!("{:#?}", i); + + let ui : Result<UserIterator<iter::Iter>, _> = i.into_user_iterator(); + assert!(ui.is_ok(), "Not okay: {:#?}", ui); + let mut ui = ui.unwrap(); + + for min in (1..60).into_iter().filter(|n| n % 2 == 0) { + let n = ui.next().unwrap(); + assert!(n.is_ok(), "Not ok: {:#?}", n); + let tt = n.unwrap(); + assert_eq!(tt.get_moment().unwrap().year() , 2017); + assert_eq!(tt.get_moment().unwrap().month() , 01); + assert_eq!(tt.get_moment().unwrap().day() , 01); + assert_eq!(tt.get_moment().unwrap().hour() , 00); + assert_eq!(tt.get_moment().unwrap().minute(), min); + assert_eq!(tt.get_moment().unwrap().second(), 00); + } + } + + #[test] + fn test_iterator_3() { + let res = iterator(&b"2017-01-01 daily"[..]); + assert!(res.is_done(), format!("Not done: {:?}", res)); + let (_, i) = res.unwrap(); + println!("{:#?}", i); + + let ui : Result<UserIterator<iter::Iter>, _> = i.into_user_iterator(); + assert!(ui.is_ok(), "Not okay: {:#?}", ui); + let mut ui = ui.unwrap(); + + for day in 2..30 { + let n = ui.next().unwrap(); + assert!(n.is_ok(), "Not ok: {:#?}", n); + let tt = n.unwrap(); + assert_eq!(tt.get_moment().unwrap().year() , 2017); + assert_eq!(tt.get_moment().unwrap().month() , 01); + assert_eq!(tt.get_moment().unwrap().day() , day); + assert_eq!(tt.get_moment().unwrap().hour() , 00); + assert_eq!(tt.get_moment().unwrap().minute(), 00); + assert_eq!(tt.get_moment().unwrap().second(), 00); + } + } + + #[test] + fn test_iterator_4() { + let res = iterator(&b"2017-01-01 weekly"[..]); + assert!(res.is_done(), format!("Not done: {:?}", res)); + let (_, i) = res.unwrap(); + println!("{:#?}", i); + + let ui : Result<UserIterator<iter::Iter>, _> = i.into_user_iterator(); + assert!(ui.is_ok(), "Not okay: {:#?}", ui); + let mut ui = ui.unwrap(); + + for week in 1..3 { + let n = ui.next().unwrap(); + assert!(n.is_ok(), "Not ok: {:#?}", n); + let tt = n.unwrap(); + assert_eq!(tt.get_moment().unwrap().year() , 2017); + assert_eq!(tt.get_moment().unwrap().month() , 01); + assert_eq!(tt.get_moment().unwrap().day() , 01 + (week * 7)); + assert_eq!(tt.get_moment().unwrap().hour() , 00); + assert_eq!(tt.get_moment().unwrap().minute(), 00); + assert_eq!(tt.get_moment().unwrap().second(), 00); + } + } + + #[test] + fn test_until_spec_1() { + let res = until_spec(&b"until 2017-01-01T05:00:00"[..]); + assert!(res.is_done(), format!("Not done: {:?}", res)); + let (_, i) = res.unwrap(); + println!("{:#?}", i); + } + + #[test] + fn test_until_iterator_1() { + let res = iterator(&b"2017-01-01 hourly until 2017-01-01T05:00:00"[..]); + assert!(res.is_done(), format!("Not done: {:?}", res)); + let (_, i) = res.unwrap(); + println!("{:#?}", i); + + let ui : Result<UserIterator<iter::Iter>, _> = i.into_user_iterator(); + assert!(ui.is_ok(), "Not okay: {:#?}", ui); + let mut ui = ui.unwrap(); + println!("Okay: {:#?}", ui); + + for hour in 1..10 { // 10 is randomly chosen (fair dice roll... ) + if hour > 5 - 1 { + let n = ui.next(); + assert!(n.is_none(), "Is Some, should be None: {:?}", n); + return; + } else { + let n = ui.next().unwrap(); + assert!(n.is_ok(), "Not ok: {:#?}", n); + let tt = n.unwrap(); + assert_eq!(tt.get_moment().unwrap().year() , 2017); + assert_eq!(tt.get_moment().unwrap().month() , 01); + assert_eq!(tt.get_moment().unwrap().day() , 01); + assert_eq!(tt.get_moment().unwrap().hour() , hour); + assert_eq!(tt.get_moment().unwrap().minute(), 00); + assert_eq!(tt.get_moment().unwrap().second(), 00); + } + } + } + + #[test] + fn test_until_iterator_2() { + let res = iterator(&b"2017-01-01 every 2mins until 2017-01-01T00:10:00"[..]); + assert!(res.is_done(), format!("Not done: {:?}", res)); + let (_, i) = res.unwrap(); + println!("{:#?}", i); + + let ui : Result<UserIterator<iter::Iter>, _> = i.into_user_iterator(); + assert!(ui.is_ok(), "Not okay: {:#?}", ui); + let mut ui = ui.unwrap(); + + for min in (1..60).into_iter().filter(|n| n % 2 == 0) { + if min > 10 - 1 { + let n = ui.next(); + assert!(n.is_none(), "Is Some, should be None: {:?}", n); + return; + } else { + let n = ui.next().unwrap(); + assert!(n.is_ok(), "Not ok: {:#?}", n); + let tt = n.unwrap(); + assert_eq!(tt.get_moment().unwrap().year() , 2017); + assert_eq!(tt.get_moment().unwrap().month() , 01); + assert_eq!(tt.get_moment().unwrap().day() , 01); + assert_eq!(tt.get_moment().unwrap().hour() , 00); + assert_eq!(tt.get_moment().unwrap().minute(), min); + assert_eq!(tt.get_moment().unwrap().second(), 00); + } + } + } + + #[test] + fn test_until_iterator_3() { + let res = iterator(&b"2017-01-01 daily until 2017-01-05"[..]); + assert!(res.is_done(), format!("Not done: {:?}", res)); + let (_, i) = res.unwrap(); + println!("{:#?}", i); + + let ui : Result<UserIterator<iter::Iter>, _> = i.into_user_iterator(); + assert!(ui.is_ok(), "Not okay: {:#?}", ui); + let mut ui = ui.unwrap(); + + for day in 2..30 { + if day > 5 - 1 { + let n = ui.next(); + assert!(n.is_none(), "Is Some, should be None: {:?}", n); + return; + } else { + let n = ui.next().unwrap(); + assert!(n.is_ok(), "Not ok: {:#?}", n); + let tt = n.unwrap(); + assert_eq!(tt.get_moment().unwrap().year() , 2017); + assert_eq!(tt.get_moment().unwrap().month() , 01); + assert_eq!(tt.get_moment().unwrap().day() , day); + assert_eq!(tt.get_moment().unwrap().hour() , 00); + assert_eq!(tt.get_moment().unwrap().minute(), 00); + assert_eq!(tt.get_moment().unwrap().second(), 00); + } + } + } + + #[test] + fn test_until_iterator_4() { + let res = iterator(&b"2017-01-01 weekly until 2017-01-14"[..]); + assert!(res.is_done(), format!("Not done: {:?}", res)); + let (_, i) = res.unwrap(); + println!("{:#?}", i); + + let ui : Result<UserIterator<iter::Iter>, _> = i.into_user_iterator(); + assert!(ui.is_ok(), "Not okay: {:#?}", ui); + let mut ui = ui.unwrap(); + + for week in 1..3 { + if (week * 7 + 1) > 14 { + let n = ui.next(); + assert!(n.is_none(), "Is Some, should be None: {:?}", n); + return; + } else { + let n = ui.next().unwrap(); + assert!(n.is_ok(), "Not ok: {:#?}", n); + let tt = n.unwrap(); + assert_eq!(tt.get_moment().unwrap().year() , 2017); + assert_eq!(tt.get_moment().unwrap().month() , 01); + assert_eq!(tt.get_moment().unwrap().day() , 01 + (week * 7)); + assert_eq!(tt.get_moment().unwrap().hour() , 00); + assert_eq!(tt.get_moment().unwrap().minute(), 00); + assert_eq!(tt.get_moment().unwrap().second(), 00); + } + } + } } |