diff options
Diffstat (limited to 'src/parser/iterator.rs')
-rw-r--r-- | src/parser/iterator.rs | 315 |
1 files changed, 166 insertions, 149 deletions
diff --git a/src/parser/iterator.rs b/src/parser/iterator.rs index 7d3007c..06ecc2b 100644 --- a/src/parser/iterator.rs +++ b/src/parser/iterator.rs @@ -1,27 +1,32 @@ -use nom::whitespace::sp; - -use error::Result; -use error::Error; -use parser::timetype::*; -use timetype::IntoTimeType; -use timetype; -use iter; - -named!(pub iter_spec<Iterspec>, alt_complete!( - tag!("secondly") => { |_| Iterspec::Secondly } | - tag!("minutely") => { |_| Iterspec::Minutely } | - tag!("hourly") => { |_| Iterspec::Hourly } | - tag!("daily") => { |_| Iterspec::Daily } | - tag!("weekly") => { |_| Iterspec::Weekly } | - tag!("monthly") => { |_| Iterspec::Monthly } | - tag!("yearly") => { |_| Iterspec::Yearly } | - do_parse!( - tag!("every") >> - number:integer >> - unit:unit_parser >> - (Iterspec::Every(number, unit)) - ) -)); +use nom::branch::alt; +use nom::bytes::complete::tag; +use nom::character::complete::{multispace0, multispace1}; +use nom::combinator::{complete, map, opt}; +use nom::sequence::tuple; +use nom::IResult; + +use crate::error::Error; +use crate::error::Result; +use crate::iter; +use crate::timetype; +use crate::timetype::IntoTimeType; + +use super::timetype::*; + +pub fn iter_spec(i: &[u8]) -> IResult<&[u8], Iterspec> { + complete(alt(( + map(tag("secondly"), |_| Iterspec::Secondly), + map(tag("minutely"), |_| Iterspec::Minutely), + map(tag("hourly"), |_| Iterspec::Hourly), + map(tag("daily"), |_| Iterspec::Daily), + map(tag("weekly"), |_| Iterspec::Weekly), + map(tag("monthly"), |_| Iterspec::Monthly), + map(tag("yearly"), |_| Iterspec::Yearly), + map(tuple((tag("every"), integer, unit_parser)), |(_, number, unit)| { + Iterspec::Every(number, unit) + }), + )))(i) +} #[derive(Debug, PartialEq, Eq)] pub enum Iterspec { @@ -35,31 +40,37 @@ pub enum Iterspec { Every(i64, Unit), } -named!(pub until_spec<UntilSpec>, alt_complete!( - do_parse!( - tag!("until") >> sp >> - exact: exact_date_parser >> - (UntilSpec::Exact(exact)) - ) | - do_parse!( - num: integer >> sp >> - tag!("times") >> - (UntilSpec::Times(num)) - ) -)); +pub fn until_spec(i: &[u8]) -> IResult<&[u8], UntilSpec> { + complete(alt(( + map( + tuple((tag("until"), multispace1, exact_date_parser)), + |(_, _, exact)| UntilSpec::Exact(exact), + ), + map(tuple((integer, multispace1, tag("times"))), |(num, _, _)| { + UntilSpec::Times(num) + }), + )))(i) +} #[derive(Debug, PartialEq, Eq)] pub enum UntilSpec { Exact(ExactDate), - Times(i64) + Times(i64), } -named!(pub iterator<Iterator>, do_parse!( - opt!(sp) >> d: date >> - opt!(sp) >> spec: iter_spec >> - opt!(sp) >> until: opt!(complete!(until_spec)) >> - (Iterator(d, spec, until)) -)); +pub fn iterator(i: &[u8]) -> IResult<&[u8], Iterator> { + map( + tuple(( + multispace0, + date, + multispace0, + iter_spec, + multispace0, + opt(complete(until_spec)), + )), + |(_, d, _, spec, _, until)| Iterator(d, spec, until), + )(i) +} #[derive(Debug, PartialEq, Eq)] pub struct Iterator(Date, Iterspec, Option<UntilSpec>); @@ -72,37 +83,38 @@ impl Iterator { 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), + 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), + 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| e.calculate()? - .get_moment() - .ok_or(Error::NotADateInsideIterator) - .map_err(Error::from) - .map(Clone::clone); + let into_ndt = |e: timetype::TimeType| { + e.calculate()? + .get_moment() + .ok_or(Error::NotADateInsideIterator) + .map_err(Error::from) + .map(Clone::clone) + }; match self.2 { Some(UntilSpec::Exact(e)) => { let base = into_ndt(self.0.into_timetype()?)?; - let e = into_ndt(e.into_timetype()?)?; + let e = into_ndt(e.into_timetype()?)?; - iter::Iter::build(base, recur) - .map(|it| UserIterator::UntilIterator(it.until(e))) + iter::Iter::build(base, recur).map(|it| UserIterator::UntilIterator(it.until(e))) }, Some(UntilSpec::Times(i)) => { @@ -114,8 +126,7 @@ impl Iterator { None => { let base = into_ndt(self.0.into_timetype()?)?; - iter::Iter::build(base, recur) - .map(UserIterator::Iterator) + iter::Iter::build(base, recur).map(UserIterator::Iterator) }, } } @@ -124,104 +135,110 @@ impl Iterator { // names are hard #[derive(Debug)] pub enum UserIterator<I> - where I: ::std::iter::Iterator<Item = Result<timetype::TimeType>> +where + I: std::iter::Iterator<Item = Result<timetype::TimeType>>, { Iterator(iter::Iter), TimesIter(iter::TimesIter<I>), - UntilIterator(iter::UntilIter<I>) + UntilIterator(iter::UntilIter<I>), } -impl<I> ::std::iter::Iterator for UserIterator<I> - where I: ::std::iter::Iterator<Item = Result<timetype::TimeType>> +impl<I> std::iter::Iterator for UserIterator<I> +where + I: std::iter::Iterator<Item = Result<timetype::TimeType>>, { type Item = 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::Iterator(ref mut i) => i.next(), + UserIterator::TimesIter(ref mut i) => i.next(), UserIterator::UntilIterator(ref mut i) => i.next(), } } } - #[cfg(test)] mod tests { - use nom::IResult; - use super::*; + use std::iter::Iterator; - use chrono::Timelike; use chrono::Datelike; + use chrono::Timelike; + + use super::*; #[test] fn test_iterspec() { - assert_eq!(iter_spec(&b"secondly"[..]), IResult::Done(&b""[..], Iterspec::Secondly)); - assert_eq!(iter_spec(&b"minutely"[..]), IResult::Done(&b""[..], Iterspec::Minutely)); - assert_eq!(iter_spec(&b"hourly"[..]), IResult::Done(&b""[..], Iterspec::Hourly)); - assert_eq!(iter_spec(&b"daily"[..]), IResult::Done(&b""[..], Iterspec::Daily)); - assert_eq!(iter_spec(&b"weekly"[..]), IResult::Done(&b""[..], Iterspec::Weekly)); - assert_eq!(iter_spec(&b"monthly"[..]), IResult::Done(&b""[..], Iterspec::Monthly)); - assert_eq!(iter_spec(&b"yearly"[..]), IResult::Done(&b""[..], Iterspec::Yearly)); - assert_eq!(iter_spec(&b"every 5min"[..]), IResult::Done(&b""[..], Iterspec::Every(5, Unit::Minute))); + assert_eq!(iter_spec(&b"secondly"[..]), Ok((&b""[..], Iterspec::Secondly))); + assert_eq!(iter_spec(&b"minutely"[..]), Ok((&b""[..], Iterspec::Minutely))); + assert_eq!(iter_spec(&b"hourly"[..]), Ok((&b""[..], Iterspec::Hourly))); + assert_eq!(iter_spec(&b"daily"[..]), Ok((&b""[..], Iterspec::Daily))); + assert_eq!(iter_spec(&b"weekly"[..]), Ok((&b""[..], Iterspec::Weekly))); + assert_eq!(iter_spec(&b"monthly"[..]), Ok((&b""[..], Iterspec::Monthly))); + assert_eq!(iter_spec(&b"yearly"[..]), Ok((&b""[..], Iterspec::Yearly))); + assert_eq!( + iter_spec(&b"every 5min"[..]), + Ok((&b""[..], Iterspec::Every(5, Unit::Minute))) + ); } #[test] fn test_iterator_1() { let res = iterator(&b"2017-01-01 hourly"[..]); - assert!(res.is_done(), format!("Not done: {:?}", res)); + assert!(res.is_ok(), "Not done: {:?}", res); let (_, i) = res.unwrap(); println!("{:#?}", i); - let ui : Result<UserIterator<iter::Iter>> = i.into_user_iterator(); + 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 0..10 { // 10 is randomly chosen (fair dice roll... ) + for hour in 0..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); + assert_eq!(tt.get_moment().unwrap().year(), 2017); + assert_eq!(tt.get_moment().unwrap().month(), 1); + assert_eq!(tt.get_moment().unwrap().day(), 1); + assert_eq!(tt.get_moment().unwrap().hour(), hour); + assert_eq!(tt.get_moment().unwrap().minute(), 0); + assert_eq!(tt.get_moment().unwrap().second(), 0); } } #[test] fn test_iterator_2() { let res = iterator(&b"2017-01-01 every 2mins"[..]); - assert!(res.is_done(), format!("Not done: {:?}", res)); + assert!(res.is_ok(), "Not done: {:?}", res); let (_, i) = res.unwrap(); println!("{:#?}", i); - let ui : Result<UserIterator<iter::Iter>> = i.into_user_iterator(); + 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 (0..60).into_iter().filter(|n| n % 2 == 0) { + for min in (0..60).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().year(), 2017); + assert_eq!(tt.get_moment().unwrap().month(), 1); + assert_eq!(tt.get_moment().unwrap().day(), 1); + assert_eq!(tt.get_moment().unwrap().hour(), 0); assert_eq!(tt.get_moment().unwrap().minute(), min); - assert_eq!(tt.get_moment().unwrap().second(), 00); + assert_eq!(tt.get_moment().unwrap().second(), 0); } } #[test] fn test_iterator_3() { let res = iterator(&b"2017-01-01 daily"[..]); - assert!(res.is_done(), format!("Not done: {:?}", res)); + assert!(res.is_ok(), "Not done: {:?}", res); let (_, i) = res.unwrap(); println!("{:#?}", i); - let ui : Result<UserIterator<iter::Iter>> = i.into_user_iterator(); + let ui: Result<UserIterator<iter::Iter>> = i.into_user_iterator(); assert!(ui.is_ok(), "Not okay: {:#?}", ui); let mut ui = ui.unwrap(); @@ -229,23 +246,23 @@ mod tests { 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); + assert_eq!(tt.get_moment().unwrap().year(), 2017); + assert_eq!(tt.get_moment().unwrap().month(), 1); + assert_eq!(tt.get_moment().unwrap().day(), day); + assert_eq!(tt.get_moment().unwrap().hour(), 0); + assert_eq!(tt.get_moment().unwrap().minute(), 0); + assert_eq!(tt.get_moment().unwrap().second(), 0); } } #[test] fn test_iterator_4() { let res = iterator(&b"2017-01-01 weekly"[..]); - assert!(res.is_done(), format!("Not done: {:?}", res)); + assert!(res.is_ok(), "Not done: {:?}", res); let (_, i) = res.unwrap(); println!("{:#?}", i); - let ui : Result<UserIterator<iter::Iter>> = i.into_user_iterator(); + let ui: Result<UserIterator<iter::Iter>> = i.into_user_iterator(); assert!(ui.is_ok(), "Not okay: {:#?}", ui); let mut ui = ui.unwrap(); @@ -253,19 +270,19 @@ mod tests { 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); + assert_eq!(tt.get_moment().unwrap().year(), 2017); + assert_eq!(tt.get_moment().unwrap().month(), 1); + assert_eq!(tt.get_moment().unwrap().day(), 1 + (week * 7)); + assert_eq!(tt.get_moment().unwrap().hour(), 0); + assert_eq!(tt.get_moment().unwrap().minute(), 0); + assert_eq!(tt.get_moment().unwrap().second(), 0); } } #[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)); + assert!(res.is_ok(), "Not done: {:?}", res); let (_, i) = res.unwrap(); println!("{:#?}", i); } @@ -273,16 +290,17 @@ mod tests { #[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)); + assert!(res.is_ok(), "Not done: {:?}", res); let (_, i) = res.unwrap(); println!("{:#?}", i); - let ui : Result<UserIterator<iter::Iter>> = i.into_user_iterator(); + 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 0..10 { // 10 is randomly chosen (fair dice roll... ) + for hour in 0..10 { + // 10 is randomly chosen (fair dice roll... ) if hour > 4 { let n = ui.next(); assert!(n.is_none(), "Is Some, should be None: {:?}", n); @@ -291,12 +309,12 @@ mod tests { 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); + assert_eq!(tt.get_moment().unwrap().year(), 2017); + assert_eq!(tt.get_moment().unwrap().month(), 1); + assert_eq!(tt.get_moment().unwrap().day(), 1); + assert_eq!(tt.get_moment().unwrap().hour(), hour); + assert_eq!(tt.get_moment().unwrap().minute(), 0); + assert_eq!(tt.get_moment().unwrap().second(), 0); } } } @@ -304,15 +322,15 @@ mod tests { #[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)); + assert!(res.is_ok(), "Not done: {:?}", res); let (_, i) = res.unwrap(); println!("{:#?}", i); - let ui : Result<UserIterator<iter::Iter>> = i.into_user_iterator(); + 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 (0..60).into_iter().filter(|n| n % 2 == 0) { + for min in (0..60).filter(|n| n % 2 == 0) { if min > 9 { let n = ui.next(); assert!(n.is_none(), "Is Some, should be None: {:?}", n); @@ -321,12 +339,12 @@ mod tests { 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().year(), 2017); + assert_eq!(tt.get_moment().unwrap().month(), 1); + assert_eq!(tt.get_moment().unwrap().day(), 1); + assert_eq!(tt.get_moment().unwrap().hour(), 0); assert_eq!(tt.get_moment().unwrap().minute(), min); - assert_eq!(tt.get_moment().unwrap().second(), 00); + assert_eq!(tt.get_moment().unwrap().second(), 0); } } } @@ -334,11 +352,11 @@ mod tests { #[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)); + assert!(res.is_ok(), "Not done: {:?}", res); let (_, i) = res.unwrap(); println!("{:#?}", i); - let ui : Result<UserIterator<iter::Iter>> = i.into_user_iterator(); + let ui: Result<UserIterator<iter::Iter>> = i.into_user_iterator(); assert!(ui.is_ok(), "Not okay: {:#?}", ui); let mut ui = ui.unwrap(); @@ -351,12 +369,12 @@ mod tests { 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); + assert_eq!(tt.get_moment().unwrap().year(), 2017); + assert_eq!(tt.get_moment().unwrap().month(), 1); + assert_eq!(tt.get_moment().unwrap().day(), day); + assert_eq!(tt.get_moment().unwrap().hour(), 0); + assert_eq!(tt.get_moment().unwrap().minute(), 0); + assert_eq!(tt.get_moment().unwrap().second(), 0); } } } @@ -364,11 +382,11 @@ mod tests { #[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)); + assert!(res.is_ok(), "Not done: {:?}", res); let (_, i) = res.unwrap(); println!("{:#?}", i); - let ui : Result<UserIterator<iter::Iter>> = i.into_user_iterator(); + let ui: Result<UserIterator<iter::Iter>> = i.into_user_iterator(); assert!(ui.is_ok(), "Not okay: {:#?}", ui); let mut ui = ui.unwrap(); @@ -381,14 +399,13 @@ mod tests { 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); + assert_eq!(tt.get_moment().unwrap().year(), 2017); + assert_eq!(tt.get_moment().unwrap().month(), 1); + assert_eq!(tt.get_moment().unwrap().day(), 1 + (week * 7)); + assert_eq!(tt.get_moment().unwrap().hour(), 0); + assert_eq!(tt.get_moment().unwrap().minute(), 0); + assert_eq!(tt.get_moment().unwrap().second(), 0); } } } } - |