diff options
Diffstat (limited to 'src/parser/timetype.rs')
-rw-r--r-- | src/parser/timetype.rs | 610 |
1 files changed, 304 insertions, 306 deletions
diff --git a/src/parser/timetype.rs b/src/parser/timetype.rs index 1437242..904fcc9 100644 --- a/src/parser/timetype.rs +++ b/src/parser/timetype.rs @@ -1,52 +1,41 @@ use std::str; -use std::str::FromStr; -use nom::digit; -use nom::whitespace::sp; use chrono::NaiveDate; - -use timetype::IntoTimeType; -use timetype; -use error::Result; -use error::Error; - -named!(pub integer<i64>, alt!( - map_res!( - map_res!( - ws!(digit), - str::from_utf8 - ), - FromStr::from_str - ) -)); +use iso8601::parsers::{parse_date, parse_datetime}; +use nom::branch::alt; +use nom::bytes::complete::tag; +use nom::character::complete::{digit1, multispace0, multispace1}; +use nom::combinator::{complete, map, map_opt, opt}; +use nom::sequence::{delimited, tuple}; +use nom::IResult; + +use crate::error::Error; +use crate::error::Result; +use crate::timetype::IntoTimeType; + +pub fn integer(input: &[u8]) -> IResult<&[u8], i64> { + map_opt(delimited(multispace0, digit1, multispace0), |digit| { + str::from_utf8(digit).ok().and_then(|s| s.parse().ok()) + })(input) +} // WARNING: Order is important here. Long tags first, shorter tags later -named!(pub unit_parser<Unit>, alt_complete!( - tag!("seconds") => { |_| Unit::Second } | - tag!("second") => { |_| Unit::Second } | - tag!("secs") => { |_| Unit::Second } | - tag!("sec") => { |_| Unit::Second } | - tag!("s") => { |_| Unit::Second } | - tag!("minutes") => { |_| Unit::Minute } | - tag!("minute") => { |_| Unit::Minute } | - tag!("mins") => { |_| Unit::Minute } | - tag!("min") => { |_| Unit::Minute } | - tag!("hours") => { |_| Unit::Hour } | - tag!("hour") => { |_| Unit::Hour } | - tag!("hrs") => { |_| Unit::Hour } | - tag!("hr") => { |_| Unit::Hour } | - tag!("days") => { |_| Unit::Day } | - tag!("day") => { |_| Unit::Day } | - tag!("d") => { |_| Unit::Day } | - tag!("weeks") => { |_| Unit::Week } | - tag!("week") => { |_| Unit::Week } | - tag!("w") => { |_| Unit::Week } | - tag!("months") => { |_| Unit::Month } | - tag!("month") => { |_| Unit::Month } | - tag!("years") => { |_| Unit::Year } | - tag!("year") => { |_| Unit::Year } | - tag!("yrs") => { |_| Unit::Year } -)); +pub fn unit_parser(input: &[u8]) -> IResult<&[u8], Unit> { + complete(alt(( + map( + alt((tag("seconds"), tag("second"), tag("secs"), tag("sec"), tag("s"))), + |_| Unit::Second, + ), + map(alt((tag("minutes"), tag("minute"), tag("mins"), tag("min"))), |_| { + Unit::Minute + }), + map(alt((tag("hours"), tag("hour"), tag("hrs"), tag("hr"))), |_| Unit::Hour), + map(alt((tag("days"), tag("day"), tag("d"))), |_| Unit::Day), + map(alt((tag("weeks"), tag("week"), tag("w"))), |_| Unit::Week), + map(alt((tag("months"), tag("month"))), |_| Unit::Month), + map(alt((tag("years"), tag("year"), tag("yrs"))), |_| Unit::Year), + )))(input) +} #[derive(Debug, PartialEq, Eq)] pub enum Unit { @@ -70,24 +59,23 @@ pub enum UnitAlias { Yearly, } -impl Into<Unit> for UnitAlias { - fn into(self) -> Unit { - match self { +impl From<UnitAlias> for Unit { + fn from(val: UnitAlias) -> Self { + match val { UnitAlias::Secondly => Unit::Second, UnitAlias::Minutely => Unit::Minute, - UnitAlias::Hourly => Unit::Hour, - UnitAlias::Daily => Unit::Day, - UnitAlias::Weekly => Unit::Week, - UnitAlias::Monthly => Unit::Month, - UnitAlias::Yearly => Unit::Year, + UnitAlias::Hourly => Unit::Hour, + UnitAlias::Daily => Unit::Day, + UnitAlias::Weekly => Unit::Week, + UnitAlias::Monthly => Unit::Month, + UnitAlias::Yearly => Unit::Year, } } } -named!(pub operator_parser<Operator>, alt!( - tag!("+") => { |_| Operator::Plus } | - tag!("-") => { |_| Operator::Minus } -)); +pub fn operator_parser(input: &[u8]) -> IResult<&[u8], Operator> { + alt((map(tag("+"), |_| Operator::Plus), map(tag("-"), |_| Operator::Minus)))(input) +} #[derive(Debug, PartialEq, Eq)] pub enum Operator { @@ -95,51 +83,54 @@ pub enum Operator { Minus, } -named!(pub unit_alias<UnitAlias>, alt_complete!( - tag!("secondly") => { |_| UnitAlias::Secondly } | - tag!("minutely") => { |_| UnitAlias::Minutely } | - tag!("hourly") => { |_| UnitAlias::Hourly } | - tag!("daily") => { |_| UnitAlias::Daily } | - tag!("weekly") => { |_| UnitAlias::Weekly } | - tag!("monthly") => { |_| UnitAlias::Monthly } | - tag!("yearly") => { |_| UnitAlias::Yearly } -)); - -named!(pub amount_parser<Amount>, alt!( - do_parse!(number: integer >> unit: unit_parser >> (Amount(number, unit))) | - do_parse!(unitalias: unit_alias >> (Amount(1, unitalias.into()))) -)); +pub fn unit_alias(input: &[u8]) -> IResult<&[u8], UnitAlias> { + complete(alt(( + map(tag("secondly"), |_| UnitAlias::Secondly), + map(tag("minutely"), |_| UnitAlias::Minutely), + map(tag("hourly"), |_| UnitAlias::Hourly), + map(tag("daily"), |_| UnitAlias::Daily), + map(tag("weekly"), |_| UnitAlias::Weekly), + map(tag("monthly"), |_| UnitAlias::Monthly), + map(tag("yearly"), |_| UnitAlias::Yearly), + )))(input) +} + +pub fn amount_parser(input: &[u8]) -> IResult<&[u8], Amount> { + alt(( + map(tuple((integer, unit_parser)), |(number, unit)| Amount(number, unit)), + map(unit_alias, |unit| Amount(1, unit.into())), + ))(input) +} #[derive(Debug, PartialEq, Eq)] pub struct Amount(i64, Unit); impl IntoTimeType for Amount { - fn into_timetype(self) -> Result<timetype::TimeType> { + fn into_timetype(self) -> Result<crate::timetype::TimeType> { Ok(match self.1 { - Unit::Second => timetype::TimeType::seconds(self.0), - Unit::Minute => timetype::TimeType::minutes(self.0), - Unit::Hour => timetype::TimeType::hours(self.0), - Unit::Day => timetype::TimeType::days(self.0), - Unit::Week => timetype::TimeType::weeks(self.0), - Unit::Month => timetype::TimeType::months(self.0), - Unit::Year => timetype::TimeType::years(self.0), + Unit::Second => crate::timetype::TimeType::seconds(self.0), + Unit::Minute => crate::timetype::TimeType::minutes(self.0), + Unit::Hour => crate::timetype::TimeType::hours(self.0), + Unit::Day => crate::timetype::TimeType::days(self.0), + Unit::Week => crate::timetype::TimeType::weeks(self.0), + Unit::Month => crate::timetype::TimeType::months(self.0), + Unit::Year => crate::timetype::TimeType::years(self.0), }) } } -named!(pub amount_expr_next<(Operator, Box<AmountExpr>)>, do_parse!( - op:operator_parser - >> opt!(sp) - >> amexp:amount_expr - >> ((op, Box::new(amexp))) -)); +pub fn amount_expr_next(input: &[u8]) -> IResult<&[u8], (Operator, Box<AmountExpr>)> { + map(tuple((operator_parser, multispace0, amount_expr)), |(op, _, amexp)| { + (op, Box::new(amexp)) + })(input) +} -named!(pub amount_expr<AmountExpr>, do_parse!( - amount:amount_parser >> - opt!(sp) >> - o: opt!(complete!(amount_expr_next)) >> - (AmountExpr { amount: amount, next: o, }) -)); +pub fn amount_expr(input: &[u8]) -> IResult<&[u8], AmountExpr> { + map( + tuple((amount_parser, multispace0, opt(complete(amount_expr_next)))), + |(amount, _, next)| AmountExpr { amount, next }, + )(input) +} #[derive(Debug, PartialEq, Eq)] pub struct AmountExpr { @@ -148,13 +139,13 @@ pub struct AmountExpr { } impl IntoTimeType for AmountExpr { - fn into_timetype(self) -> Result<timetype::TimeType> { + fn into_timetype(self) -> Result<crate::timetype::TimeType> { let mut amount = self.amount.into_timetype()?; if let Some((op, other_amonut_expr)) = self.next { match op { - Operator::Plus => amount = amount + (*other_amonut_expr).into_timetype()?, - Operator::Minus => amount = amount - (*other_amonut_expr).into_timetype()?, + Operator::Plus => amount += (*other_amonut_expr).into_timetype()?, + Operator::Minus => amount -= (*other_amonut_expr).into_timetype()?, } } @@ -162,89 +153,83 @@ impl IntoTimeType for AmountExpr { } } -use iso8601::parsers::parse_date; -use iso8601::parsers::parse_datetime; // The order is relevant here, because datetime is longer than date, we must parse datetime before // date. -named!(pub exact_date_parser<ExactDate>, alt_complete!( - tag!("today") => { |_| ExactDate::Today } | - tag!("yesterday") => { |_| ExactDate::Yesterday } | - tag!("tomorrow") => { |_| ExactDate::Tomorrow } | - do_parse!(d: parse_datetime >> (ExactDate::Iso8601DateTime(d))) | - do_parse!(d: parse_date >> (ExactDate::Iso8601Date(d))) -)); +pub fn exact_date_parser(input: &[u8]) -> IResult<&[u8], ExactDate> { + complete(alt(( + map(tag("today"), |_| ExactDate::Today), + map(tag("yesterday"), |_| ExactDate::Yesterday), + map(tag("tomorrow"), |_| ExactDate::Tomorrow), + map(parse_datetime, ExactDate::Iso8601DateTime), + map(parse_date, ExactDate::Iso8601Date), + )))(input) +} #[derive(Debug, PartialEq, Eq)] pub enum ExactDate { Today, Yesterday, Tomorrow, - Iso8601Date(::iso8601::Date), - Iso8601DateTime(::iso8601::DateTime) + Iso8601Date(iso8601::Date), + Iso8601DateTime(iso8601::DateTime), } impl IntoTimeType for ExactDate { - fn into_timetype(self) -> Result<timetype::TimeType> { + fn into_timetype(self) -> Result<crate::timetype::TimeType> { match self { - ExactDate::Today => Ok(timetype::TimeType::today()), - ExactDate::Yesterday => Ok(timetype::TimeType::today() - timetype::TimeType::days(1)), - ExactDate::Tomorrow => Ok(timetype::TimeType::today() + timetype::TimeType::days(1)), - ExactDate::Iso8601Date(date) => { - match date { - ::iso8601::Date::YMD { year, month, day } => NaiveDate::from_ymd_opt(year, month, day) - .ok_or(Error::OutOfBounds(year, month, day, 0, 0, 0)) - .map(|ndt| ndt.and_hms(0, 0, 0)) - .map(timetype::TimeType::moment), - - ::iso8601::Date::Week { year, ww, d } => NaiveDate::from_ymd_opt(year, 1, 1) - .ok_or(Error::OutOfBounds(year, 1, 1, 0, 0, 0)) - .map(|ndt| ndt.and_hms(0, 0, 0)) - .map(timetype::TimeType::moment) - .map(|m| { - m - + timetype::TimeType::weeks(ww as i64) - + timetype::TimeType::days(d as i64) - }), - - ::iso8601::Date::Ordinal { year, ddd } => NaiveDate::from_ymd_opt(year, 1, 1) - .ok_or(Error::OutOfBounds(year, 1, 1, 0, 0, 0)) - .map(|ndt| ndt.and_hms(0, 0, 0)) - .map(timetype::TimeType::moment) - .map(|m| m + timetype::TimeType::days(ddd as i64)), - } + ExactDate::Today => Ok(crate::timetype::TimeType::today()), + ExactDate::Yesterday => Ok(crate::timetype::TimeType::today() - crate::timetype::TimeType::days(1)), + ExactDate::Tomorrow => Ok(crate::timetype::TimeType::today() + crate::timetype::TimeType::days(1)), + ExactDate::Iso8601Date(date) => match date { + iso8601::Date::YMD { year, month, day } => NaiveDate::from_ymd_opt(year, month, day) + .and_then(|ndt| ndt.and_hms_opt(0, 0, 0)) + .ok_or(Error::OutOfBounds(year, month, day, 0, 0, 0)) + .map(crate::timetype::TimeType::moment), + + iso8601::Date::Week { year, ww, d } => NaiveDate::from_ymd_opt(year, 1, 1) + .and_then(|ndt| ndt.and_hms_opt(0, 0, 0)) + .ok_or(Error::OutOfBounds(year, 1, 1, 0, 0, 0)) + .map(crate::timetype::TimeType::moment) + .map(|m| { + m + crate::timetype::TimeType::weeks(ww as i64) + crate::timetype::TimeType::days(d as i64) + }), + + iso8601::Date::Ordinal { year, ddd } => NaiveDate::from_ymd_opt(year, 1, 1) + .and_then(|ndt| ndt.and_hms_opt(0, 0, 0)) + .ok_or(Error::OutOfBounds(year, 1, 1, 0, 0, 0)) + .map(crate::timetype::TimeType::moment) + .map(|m| m + crate::timetype::TimeType::days(ddd as i64)), }, - ExactDate::Iso8601DateTime(::iso8601::DateTime { date, time }) => { + ExactDate::Iso8601DateTime(iso8601::DateTime { date, time }) => { let (hour, minute, second) = (time.hour, time.minute, time.second); match date { - ::iso8601::Date::YMD { year, month, day } => NaiveDate::from_ymd_opt(year, month, day) + iso8601::Date::YMD { year, month, day } => NaiveDate::from_ymd_opt(year, month, day) .and_then(|ndt| ndt.and_hms_opt(hour, minute, second)) .ok_or(Error::OutOfBounds(year, month, day, hour, minute, second)) - .map(timetype::TimeType::moment), + .map(crate::timetype::TimeType::moment), - ::iso8601::Date::Week { year, ww, d } => NaiveDate::from_ymd_opt(year, 1, 1) + iso8601::Date::Week { year, ww, d } => NaiveDate::from_ymd_opt(year, 1, 1) + .and_then(|ndt| ndt.and_hms_opt(0, 0, 0)) .ok_or(Error::OutOfBounds(year, 1, 1, 0, 0, 0)) - .map(|ndt| ndt.and_hms(0, 0, 0)) - .map(timetype::TimeType::moment) + .map(crate::timetype::TimeType::moment) .map(|m| { - m - + timetype::TimeType::weeks(ww as i64) - + timetype::TimeType::days(d as i64) - + timetype::TimeType::hours(hour as i64) - + timetype::TimeType::minutes(minute as i64) - + timetype::TimeType::seconds(second as i64) + m + crate::timetype::TimeType::weeks(ww as i64) + + crate::timetype::TimeType::days(d as i64) + + crate::timetype::TimeType::hours(hour as i64) + + crate::timetype::TimeType::minutes(minute as i64) + + crate::timetype::TimeType::seconds(second as i64) }), - ::iso8601::Date::Ordinal { year, ddd } => NaiveDate::from_ymd_opt(year, 1, 1) + iso8601::Date::Ordinal { year, ddd } => NaiveDate::from_ymd_opt(year, 1, 1) + .and_then(|ndt| ndt.and_hms_opt(0, 0, 0)) .ok_or(Error::OutOfBounds(year, 1, 1, 0, 0, 0)) - .map(|ndt| ndt.and_hms(0, 0, 0)) - .map(timetype::TimeType::moment) + .map(crate::timetype::TimeType::moment) .map(|m| { - m - + timetype::TimeType::days(ddd as i64) - + timetype::TimeType::hours(hour as i64) - + timetype::TimeType::minutes(minute as i64) - + timetype::TimeType::seconds(second as i64) + m + crate::timetype::TimeType::days(ddd as i64) + + crate::timetype::TimeType::hours(hour as i64) + + crate::timetype::TimeType::minutes(minute as i64) + + crate::timetype::TimeType::seconds(second as i64) }), } }, @@ -252,24 +237,29 @@ impl IntoTimeType for ExactDate { } } -named!(pub date<Date>, do_parse!( - exact: exact_date_parser >> - o: opt!( - complete!(do_parse!(sp >> op:operator_parser >> sp >> a:amount_expr >> (op, a))) - ) >> - (Date(exact, o)) -)); +pub fn date(input: &[u8]) -> IResult<&[u8], Date> { + map( + tuple(( + exact_date_parser, + opt(complete(map( + tuple((multispace1, operator_parser, multispace1, amount_expr)), + |(_, op, _, a)| (op, a), + ))), + )), + |(exact, o)| Date(exact, o), + )(input) +} #[derive(Debug, PartialEq, Eq)] pub struct Date(ExactDate, Option<(Operator, AmountExpr)>); impl IntoTimeType for Date { - fn into_timetype(self) -> Result<timetype::TimeType> { - let base : timetype::TimeType = self.0.into_timetype()?; + fn into_timetype(self) -> Result<crate::timetype::TimeType> { + let base: crate::timetype::TimeType = self.0.into_timetype()?; match self.1 { - Some((Operator::Plus, amount)) => Ok(base + amount.into_timetype()?), + Some((Operator::Plus, amount)) => Ok(base + amount.into_timetype()?), Some((Operator::Minus, amount)) => Ok(base - amount.into_timetype()?), - None => Ok(base), + None => Ok(base), } } } @@ -281,161 +271,170 @@ pub enum TimeType { } impl IntoTimeType for TimeType { - fn into_timetype(self) -> Result<timetype::TimeType> { + fn into_timetype(self) -> Result<crate::timetype::TimeType> { match self { - TimeType::Date(d) => d.into_timetype(), + TimeType::Date(d) => d.into_timetype(), TimeType::AmountExpr(a) => a.into_timetype(), } } } - -/// Main entry function for timetype parser -/// -/// # Notice -/// -/// Note that this function returns a parser::TimeType, not a timetype::TimeType. Though, the -/// parser::TimeType can be `Into::into()`ed. -/// -named!(pub timetype<TimeType>, alt!( - do_parse!(d: date >> (TimeType::Date(d))) | - do_parse!(a: amount_expr >> (TimeType::AmountExpr(a))) -)); +// Main entry function for timetype parser +// +// # Notice +// +// Note that this function returns a parser::TimeType, not a timetype::TimeType. Though, the +// parser::TimeType can be `Into::into()`ed. +// +pub fn timetype(input: &[u8]) -> IResult<&[u8], TimeType> { + alt((map(date, TimeType::Date), map(amount_expr, TimeType::AmountExpr)))(input) +} #[cfg(test)] mod tests { - use nom::IResult; - use super::*; - - use chrono::Timelike; use chrono::Datelike; + use chrono::Timelike; + + use super::*; #[test] fn test_integer() { - assert_eq!(integer(&b"2"[..]), IResult::Done(&b""[..], 2)); - assert_eq!(integer(&b"217"[..]), IResult::Done(&b""[..], 217)); + assert_eq!(integer(&b"2"[..]), Ok((&b""[..], 2))); + assert_eq!(integer(&b"217"[..]), Ok((&b""[..], 217))); } #[test] fn test_unit() { - assert_eq!(unit_parser(&b"second"[..]), IResult::Done(&b""[..], Unit::Second)); - assert_eq!(unit_parser(&b"seconds"[..]), IResult::Done(&b""[..], Unit::Second)); - assert_eq!(unit_parser(&b"sec"[..]), IResult::Done(&b""[..], Unit::Second)); - assert_eq!(unit_parser(&b"secs"[..]), IResult::Done(&b""[..], Unit::Second)); - assert_eq!(unit_parser(&b"s"[..]), IResult::Done(&b""[..], Unit::Second)); - assert_eq!(unit_parser(&b"minute"[..]), IResult::Done(&b""[..], Unit::Minute)); - assert_eq!(unit_parser(&b"minutes"[..]), IResult::Done(&b""[..], Unit::Minute)); - assert_eq!(unit_parser(&b"min"[..]), IResult::Done(&b""[..], Unit::Minute)); - assert_eq!(unit_parser(&b"mins"[..]), IResult::Done(&b""[..], Unit::Minute)); - assert_eq!(unit_parser(&b"hour"[..]), IResult::Done(&b""[..], Unit::Hour)); - assert_eq!(unit_parser(&b"hours"[..]), IResult::Done(&b""[..], Unit::Hour)); - assert_eq!(unit_parser(&b"hr"[..]), IResult::Done(&b""[..], Unit::Hour)); - assert_eq!(unit_parser(&b"hrs"[..]), IResult::Done(&b""[..], Unit::Hour)); - assert_eq!(unit_parser(&b"day"[..]), IResult::Done(&b""[..], Unit::Day)); - assert_eq!(unit_parser(&b"days"[..]), IResult::Done(&b""[..], Unit::Day)); - assert_eq!(unit_parser(&b"d"[..]), IResult::Done(&b""[..], Unit::Day)); - assert_eq!(unit_parser(&b"week"[..]), IResult::Done(&b""[..], Unit::Week)); - assert_eq!(unit_parser(&b"weeks"[..]), IResult::Done(&b""[..], Unit::Week)); - assert_eq!(unit_parser(&b"w"[..]), IResult::Done(&b""[..], Unit::Week)); - assert_eq!(unit_parser(&b"month"[..]), IResult::Done(&b""[..], Unit::Month)); - assert_eq!(unit_parser(&b"months"[..]), IResult::Done(&b""[..], Unit::Month)); - assert_eq!(unit_parser(&b"year"[..]), IResult::Done(&b""[..], Unit::Year)); - assert_eq!(unit_parser(&b"years"[..]), IResult::Done(&b""[..], Unit::Year)); - assert_eq!(unit_parser(&b"yrs"[..]), IResult::Done(&b""[..], Unit::Year)); + assert_eq!(unit_parser(&b"second"[..]), Ok((&b""[..], Unit::Second))); + assert_eq!(unit_parser(&b"seconds"[..]), Ok((&b""[..], Unit::Second))); + assert_eq!(unit_parser(&b"sec"[..]), Ok((&b""[..], Unit::Second))); + assert_eq!(unit_parser(&b"secs"[..]), Ok((&b""[..], Unit::Second))); + assert_eq!(unit_parser(&b"s"[..]), Ok((&b""[..], Unit::Second))); + assert_eq!(unit_parser(&b"minute"[..]), Ok((&b""[..], Unit::Minute))); + assert_eq!(unit_parser(&b"minutes"[..]), Ok((&b""[..], Unit::Minute))); + assert_eq!(unit_parser(&b"min"[..]), Ok((&b""[..], Unit::Minute))); + assert_eq!(unit_parser(&b"mins"[..]), Ok((&b""[..], Unit::Minute))); + assert_eq!(unit_parser(&b"hour"[..]), Ok((&b""[..], Unit::Hour))); + assert_eq!(unit_parser(&b"hours"[..]), Ok((&b""[..], Unit::Hour))); + assert_eq!(unit_parser(&b"hr"[..]), Ok((&b""[..], Unit::Hour))); + assert_eq!(unit_parser(&b"hrs"[..]), Ok((&b""[..], Unit::Hour))); + assert_eq!(unit_parser(&b"day"[..]), Ok((&b""[..], Unit::Day))); + assert_eq!(unit_parser(&b"days"[..]), Ok((&b""[..], Unit::Day))); + assert_eq!(unit_parser(&b"d"[..]), Ok((&b""[..], Unit::Day))); + assert_eq!(unit_parser(&b"week"[..]), Ok((&b""[..], Unit::Week))); + assert_eq!(unit_parser(&b"weeks"[..]), Ok((&b""[..], Unit::Week))); + assert_eq!(unit_parser(&b"w"[..]), Ok((&b""[..], Unit::Week))); + assert_eq!(unit_parser(&b"month"[..]), Ok((&b""[..], Unit::Month))); + assert_eq!(unit_parser(&b"months"[..]), Ok((&b""[..], Unit::Month))); + assert_eq!(unit_parser(&b"year"[..]), Ok((&b""[..], Unit::Year))); + assert_eq!(unit_parser(&b"years"[..]), Ok((&b""[..], Unit::Year))); + assert_eq!(unit_parser(&b"yrs"[..]), Ok((&b""[..], Unit::Year))); } #[test] fn test_unit_alias() { - assert_eq!(unit_alias(&b"secondly"[..]), IResult::Done(&b""[..], UnitAlias::Secondly)); - assert_eq!(unit_alias(&b"minutely"[..]), IResult::Done(&b""[..], UnitAlias::Minutely)); - assert_eq!(unit_alias(&b"hourly"[..]), IResult::Done(&b""[..], UnitAlias::Hourly)); - assert_eq!(unit_alias(&b"daily"[..]), IResult::Done(&b""[..], UnitAlias::Daily)); - assert_eq!(unit_alias(&b"weekly"[..]), IResult::Done(&b""[..], UnitAlias::Weekly)); - assert_eq!(unit_alias(&b"monthly"[..]), IResult::Done(&b""[..], UnitAlias::Monthly)); - assert_eq!(unit_alias(&b"yearly"[..]), IResult::Done(&b""[..], UnitAlias::Yearly)); + assert_eq!(unit_alias(&b"secondly"[..]), Ok((&b""[..], UnitAlias::Secondly))); + assert_eq!(unit_alias(&b"minutely"[..]), Ok((&b""[..], UnitAlias::Minutely))); + assert_eq!(unit_alias(&b"hourly"[..]), Ok((&b""[..], UnitAlias::Hourly))); + assert_eq!(unit_alias(&b"daily"[..]), Ok((&b""[..], UnitAlias::Daily))); + assert_eq!(unit_alias(&b"weekly"[..]), Ok((&b""[..], UnitAlias::Weekly))); + assert_eq!(unit_alias(&b"monthly"[..]), Ok((&b""[..], UnitAlias::Monthly))); + assert_eq!(unit_alias(&b"yearly"[..]), Ok((&b""[..], UnitAlias::Yearly))); } #[test] fn test_operator() { - assert_eq!(operator_parser(&b"+"[..]), IResult::Done(&b""[..], Operator::Plus)); - assert_eq!(operator_parser(&b"-"[..]), IResult::Done(&b""[..], Operator::Minus)); + assert_eq!(operator_parser(&b"+"[..]), Ok((&b""[..], Operator::Plus))); + assert_eq!(operator_parser(&b"-"[..]), Ok((&b""[..], Operator::Minus))); } #[test] fn test_amount() { - assert_eq!(amount_parser(&b"5s"[..]), IResult::Done(&b""[..], Amount(5, Unit::Second))); - assert_eq!(amount_parser(&b"5min"[..]), IResult::Done(&b""[..], Amount(5, Unit::Minute))); - assert_eq!(amount_parser(&b"55hrs"[..]), IResult::Done(&b""[..], Amount(55, Unit::Hour))); - assert_eq!(amount_parser(&b"25days"[..]), IResult::Done(&b""[..], Amount(25, Unit::Day))); - assert_eq!(amount_parser(&b"15weeks"[..]), IResult::Done(&b""[..], Amount(15, Unit::Week))); + assert_eq!(amount_parser(&b"5s"[..]), Ok((&b""[..], Amount(5, Unit::Second)))); + assert_eq!(amount_parser(&b"5min"[..]), Ok((&b""[..], Amount(5, Unit::Minute)))); + assert_eq!(amount_parser(&b"55hrs"[..]), Ok((&b""[..], Amount(55, Unit::Hour)))); + assert_eq!(amount_parser(&b"25days"[..]), Ok((&b""[..], Amount(25, Unit::Day)))); + assert_eq!(amount_parser(&b"15weeks"[..]), Ok((&b""[..], Amount(15, Unit::Week)))); } #[test] fn test_unit_alias_with_amount_parser() { - assert_eq!(amount_parser(&b"secondly"[..]), IResult::Done(&b""[..], Amount(1, Unit::Second))); - assert_eq!(amount_parser(&b"minutely"[..]), IResult::Done(&b""[..], Amount(1, Unit::Minute))); - assert_eq!(amount_parser(&b"hourly"[..]), IResult::Done(&b""[..], Amount(1, Unit::Hour))); - assert_eq!(amount_parser(&b"daily"[..]), IResult::Done(&b""[..], Amount(1, Unit::Day))); - assert_eq!(amount_parser(&b"weekly"[..]), IResult::Done(&b""[..], Amount(1, Unit::Week))); - assert_eq!(amount_parser(&b"monthly"[..]), IResult::Done(&b""[..], Amount(1, Unit::Month))); - assert_eq!(amount_parser(&b"yearly"[..]), IResult::Done(&b""[..], Amount(1, Unit::Year))); + assert_eq!(amount_parser(&b"secondly"[..]), Ok((&b""[..], Amount(1, Unit::Second)))); + assert_eq!(amount_parser(&b"minutely"[..]), Ok((&b""[..], Amount(1, Unit::Minute)))); + assert_eq!(amount_parser(&b"hourly"[..]), Ok((&b""[..], Amount(1, Unit::Hour)))); + assert_eq!(amount_parser(&b"daily"[..]), Ok((&b""[..], Amount(1, Unit::Day)))); + assert_eq!(amount_parser(&b"weekly"[..]), Ok((&b""[..], Amount(1, Unit::Week)))); + assert_eq!(amount_parser(&b"monthly"[..]), Ok((&b""[..], Amount(1, Unit::Month)))); + assert_eq!(amount_parser(&b"yearly"[..]), Ok((&b""[..], Amount(1, Unit::Year)))); } - #[test] fn test_amountexpr_next() { - assert_eq!(amount_expr_next(&b"+ 12minutes"[..]), - IResult::Done(&b""[..], + assert_eq!( + amount_expr_next(&b"+ 12minutes"[..]), + Ok(( + &b""[..], ( Operator::Plus, - Box::new(AmountExpr { amount: Amount(12, Unit::Minute), next: None }) + Box::new(AmountExpr { + amount: Amount(12, Unit::Minute), + next: None + }) ) - )); + )) + ); } #[test] fn test_amountexpr() { - assert_eq!(amount_expr(&b"5minutes"[..]), - IResult::Done(&b""[..], - AmountExpr { - amount: Amount(5, Unit::Minute), - next: None - }) + assert_eq!( + amount_expr(&b"5minutes"[..]), + Ok(( + &b""[..], + AmountExpr { + amount: Amount(5, Unit::Minute), + next: None + } + )) ); - assert_eq!(amount_expr(&b"5min + 12min"[..]), - IResult::Done(&b""[..], - AmountExpr { - amount: Amount(5, Unit::Minute), - next: Some((Operator::Plus, Box::new( - AmountExpr { - amount: Amount(12, Unit::Minute), - next: None - }))) - })); + assert_eq!( + amount_expr(&b"5min + 12min"[..]), + Ok(( + &b""[..], + AmountExpr { + amount: Amount(5, Unit::Minute), + next: Some(( + Operator::Plus, + Box::new(AmountExpr { + amount: Amount(12, Unit::Minute), + next: None + }) + )) + } + )) + ); } #[test] fn test_parse_expressions_date() { use iso8601::Date; let res = exact_date_parser(&b"2017-01-01"[..]); - assert!(res.is_done()); + assert!(res.is_ok()); match res.unwrap().1 { - ExactDate::Iso8601DateTime(_) => assert!(false), - ExactDate::Iso8601Date(d) => { - match d { - Date::YMD { year, month, day } => { - assert_eq!(year, 2017); - assert_eq!(month, 1); - assert_eq!(day, 1) - }, - _ => assert!(false), - } + ExactDate::Iso8601DateTime(_) => panic!("Unexpected enum variant"), + ExactDate::Iso8601Date(d) => match d { + Date::YMD { year, month, day } => { + assert_eq!(year, 2017); + assert_eq!(month, 1); + assert_eq!(day, 1) + }, + _ => panic!("Unexpected enum variant"), }, - ExactDate::Tomorrow => assert!(false), - ExactDate::Yesterday => assert!(false), - ExactDate::Today => assert!(false), + ExactDate::Tomorrow => panic!("Unexpected enum variant"), + ExactDate::Yesterday => panic!("Unexpected enum variant"), + ExactDate::Today => panic!("Unexpected enum variant"), }; } @@ -443,7 +442,7 @@ mod tests { fn test_parse_expressions_datetime() { use iso8601::Date; let res = exact_date_parser(&b"2017-01-01T22:00:11"[..]); - assert!(res.is_done()); + assert!(res.is_ok()); match res.unwrap().1 { ExactDate::Iso8601DateTime(obj) => { @@ -453,81 +452,81 @@ mod tests { assert_eq!(month, 1); assert_eq!(day, 1) }, - _ => assert!(false), + _ => panic!("Unexpected enum variant"), } assert_eq!(obj.time.hour, 22); assert_eq!(obj.time.minute, 0); assert_eq!(obj.time.second, 11); }, - ExactDate::Iso8601Date(_) => assert!(false), - ExactDate::Tomorrow => assert!(false), - ExactDate::Yesterday => assert!(false), - ExactDate::Today => assert!(false), + ExactDate::Iso8601Date(_) => panic!("Unexpected enum variant"), + ExactDate::Tomorrow => panic!("Unexpected enum variant"), + ExactDate::Yesterday => panic!("Unexpected enum variant"), + ExactDate::Today => panic!("Unexpected enum variant"), }; } #[test] fn test_simple_date_1() { let res = exact_date_parser(&b"today"[..]); - assert!(res.is_done(), format!("Not done: {:?}", res)); + assert!(res.is_ok(), "Not done: {:?}", res); let res = date(&b"today"[..]); - assert!(res.is_done(), format!("Not done: {:?}", res)); + assert!(res.is_ok(), "Not done: {:?}", res); } #[test] fn test_simple_date_2() { let res = date(&b"2017-01-01"[..]); - assert!(res.is_done(), format!("Not done: {:?}", res)); + assert!(res.is_ok(), "Not done: {:?}", res); let (_, o) = res.unwrap(); println!("{:#?}", o); - let calc_res : timetype::TimeType = o.into_timetype().unwrap(); + let calc_res: crate::timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); let calc_res = calc_res.unwrap(); println!("{:#?}", calc_res); - assert_eq!(calc_res.get_moment().unwrap().year() , 2017); - assert_eq!(calc_res.get_moment().unwrap().month() , 01); - assert_eq!(calc_res.get_moment().unwrap().day() , 01); - assert_eq!(calc_res.get_moment().unwrap().hour() , 00); - assert_eq!(calc_res.get_moment().unwrap().minute(), 00); - assert_eq!(calc_res.get_moment().unwrap().second(), 00); + assert_eq!(calc_res.get_moment().unwrap().year(), 2017); + assert_eq!(calc_res.get_moment().unwrap().month(), 1); + assert_eq!(calc_res.get_moment().unwrap().day(), 1); + assert_eq!(calc_res.get_moment().unwrap().hour(), 0); + assert_eq!(calc_res.get_moment().unwrap().minute(), 0); + assert_eq!(calc_res.get_moment().unwrap().second(), 0); } #[test] fn test_simple_date_3() { let res = date(&b"2017-01-01T01:02:03"[..]); - assert!(res.is_done(), format!("Not done: {:?}", res)); + assert!(res.is_ok(), "Not done: {:?}", res); let (_, o) = res.unwrap(); println!("{:#?}", o); - let calc_res : timetype::TimeType = o.into_timetype().unwrap(); + let calc_res: crate::timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); let calc_res = calc_res.unwrap(); println!("{:#?}", calc_res); - assert_eq!(calc_res.get_moment().unwrap().year() , 2017); - assert_eq!(calc_res.get_moment().unwrap().month() , 01); - assert_eq!(calc_res.get_moment().unwrap().day() , 01); - assert_eq!(calc_res.get_moment().unwrap().hour() , 01); - assert_eq!(calc_res.get_moment().unwrap().minute(), 02); - assert_eq!(calc_res.get_moment().unwrap().second(), 03); + assert_eq!(calc_res.get_moment().unwrap().year(), 2017); + assert_eq!(calc_res.get_moment().unwrap().month(), 1); + assert_eq!(calc_res.get_moment().unwrap().day(), 1); + assert_eq!(calc_res.get_moment().unwrap().hour(), 1); + assert_eq!(calc_res.get_moment().unwrap().minute(), 2); + assert_eq!(calc_res.get_moment().unwrap().second(), 3); } #[test] fn test_expressions_to_date() { let res = amount_expr(&b"5min + 12min"[..]); - assert!(res.is_done()); + assert!(res.is_ok()); let (_, o) = res.unwrap(); - let calc_res : timetype::TimeType = o.into_timetype().unwrap(); + let calc_res: crate::timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); @@ -542,10 +541,10 @@ mod tests { #[test] fn test_expressions_to_date_2() { let res = amount_expr(&b"5min + 12min + 15hours"[..]); - assert!(res.is_done()); + assert!(res.is_ok()); let (_, o) = res.unwrap(); - let calc_res : timetype::TimeType = o.into_timetype().unwrap(); + let calc_res: crate::timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); @@ -560,10 +559,10 @@ mod tests { #[test] fn test_expressions_to_date_3() { let res = date(&b"today + 5min + 12min"[..]); - assert!(res.is_done(), "Not done: {:?}", res.unwrap_err().description()); + assert!(res.is_ok(), "Not done: {:?}", res.unwrap_err()); let (_, o) = res.unwrap(); - let calc_res : timetype::TimeType = o.into_timetype().unwrap(); + let calc_res: crate::timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); @@ -575,33 +574,33 @@ mod tests { #[test] fn test_expressions_to_date_4() { let res = date(&b"2017-01-01 + 5min + 12min"[..]); - assert!(res.is_done(), "Not done: {:?}", res.unwrap_err().description()); + assert!(res.is_ok(), "Not done: {:?}", res.unwrap_err()); let (_, o) = res.unwrap(); println!("{:#?}", o); - let calc_res : timetype::TimeType = o.into_timetype().unwrap(); + let calc_res: crate::timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); let calc_res = calc_res.unwrap(); println!("{:#?}", calc_res); - assert_eq!(calc_res.get_moment().unwrap().year() , 2017); - assert_eq!(calc_res.get_moment().unwrap().month() , 01); - assert_eq!(calc_res.get_moment().unwrap().day() , 01); - assert_eq!(calc_res.get_moment().unwrap().hour() , 00); + assert_eq!(calc_res.get_moment().unwrap().year(), 2017); + assert_eq!(calc_res.get_moment().unwrap().month(), 1); + assert_eq!(calc_res.get_moment().unwrap().day(), 1); + assert_eq!(calc_res.get_moment().unwrap().hour(), 0); assert_eq!(calc_res.get_moment().unwrap().minute(), 17); - assert_eq!(calc_res.get_moment().unwrap().second(), 00); + assert_eq!(calc_res.get_moment().unwrap().second(), 0); } #[test] fn test_expressions_to_timetype() { let res = timetype(&b"5min + 12min + 15hours"[..]); - assert!(res.is_done()); + assert!(res.is_ok()); let (_, o) = res.unwrap(); - let calc_res : ::timetype::TimeType = o.into_timetype().unwrap(); + let calc_res: crate::timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); @@ -616,10 +615,10 @@ mod tests { #[test] fn test_expressions_to_timetype_2() { let res = timetype(&b"today + 5min + 12min"[..]); - assert!(res.is_done(), "Not done: {:?}", res.unwr |