From c1a9ab6a43d14b007f9787d9eb48752b13ac7dc4 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 11 Nov 2017 11:19:42 +0100 Subject: Add parser iterator type -> API iterator type mapping --- src/iter.rs | 5 ++++ src/parser.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 6 deletions(-) diff --git a/src/iter.rs b/src/iter.rs index 7399de5..05669c2 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -9,6 +9,7 @@ use error::Result; use timetype::TimeType; use matcher::Matcher; +#[derive(Debug)] pub struct Iter { base: TimeType, increment: TimeType, @@ -80,6 +81,7 @@ impl Iterator for Iter { } +#[derive(Debug)] pub struct FilterIter(I, M) where I: Iterator>, M: Matcher; @@ -127,6 +129,7 @@ impl EveryFilter for I } } +#[derive(Debug)] pub struct WithoutIter(I, M) where I: Iterator>, M: Matcher; @@ -174,6 +177,7 @@ impl WithoutFilter for I } } +#[derive(Debug)] pub struct UntilIter(I, NaiveDateTime) where I: Iterator>; @@ -222,6 +226,7 @@ impl Until for I } } +#[derive(Debug)] pub struct TimesIter where I: Iterator> { diff --git a/src/parser.rs b/src/parser.rs index 7a2e7a1..80ff151 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, alt!( map_res!( @@ -345,18 +347,92 @@ pub enum UntilSpec { } named!(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); -impl Into for Iterator { - fn into(self) -> timetype::TimeType { - unimplemented!() +impl Iterator { + pub fn into_user_iterator(self) -> error::Result> { + 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 + where I: ::std::iter::Iterator> +{ + Iterator(iter::Iter), + TimesIter(iter::TimesIter), + UntilIterator(iter::UntilIter) +} + +impl ::std::iter::Iterator for UserIterator + where I: ::std::iter::Iterator> +{ + type Item = error::Result; + + fn next(&mut self) -> Option { + match *self { + UserIterator::Iterator(ref mut i) => i.next(), + UserIterator::TimesIter(ref mut i) => i.next(), + UserIterator::UntilIterator(ref mut i) => i.next(), + } } } -- cgit v1.2.3