summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2017-11-11 11:19:42 +0100
committerMatthias Beyer <mail@beyermatthias.de>2017-11-19 14:00:24 +0100
commitc1a9ab6a43d14b007f9787d9eb48752b13ac7dc4 (patch)
treebb48d5ecbba45f70e9aad2c16dafac85d776070f
parent3a4f59eafe6e8a4e00d0a3aa0fe1853a3351adaa (diff)
Add parser iterator type -> API iterator type mapping
-rw-r--r--src/iter.rs5
-rw-r--r--src/parser.rs88
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>(I, M)
where I: Iterator<Item = Result<TimeType>>,
M: Matcher;
@@ -127,6 +129,7 @@ impl<I, M> EveryFilter<M> for I
}
}
+#[derive(Debug)]
pub struct WithoutIter<I, M>(I, M)
where I: Iterator<Item = Result<TimeType>>,
M: Matcher;
@@ -174,6 +177,7 @@ impl<I, M> WithoutFilter<M> for I
}
}
+#[derive(Debug)]
pub struct UntilIter<I>(I, NaiveDateTime)
where I: Iterator<Item = Result<TimeType>>;
@@ -222,6 +226,7 @@ impl<I> Until for I
}
}
+#[derive(Debug)]
pub struct TimesIter<I>
where I: Iterator<Item = Result<TimeType>>
{
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<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(),
+ }
}
}