From e8afcf56c124b228e4328760af6a7741b1bdd658 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Sun, 19 Nov 2017 20:03:16 +0100 Subject: Add simple fuzzer for parser --- fuzz/.gitignore | 4 ++++ fuzz/Cargo.toml | 22 ++++++++++++++++++++++ fuzz/fuzz_targets/parse.rs | 9 +++++++++ 3 files changed, 35 insertions(+) create mode 100644 fuzz/.gitignore create mode 100644 fuzz/Cargo.toml create mode 100644 fuzz/fuzz_targets/parse.rs diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 0000000..572e03b --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,4 @@ + +target +corpus +artifacts diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml new file mode 100644 index 0000000..8aa3986 --- /dev/null +++ b/fuzz/Cargo.toml @@ -0,0 +1,22 @@ + +[package] +name = "kairos-fuzz" +version = "0.0.1" +authors = ["Automatically generated"] +publish = false + +[package.metadata] +cargo-fuzz = true + +[dependencies.kairos] +path = ".." +[dependencies.libfuzzer-sys] +git = "https://github.com/rust-fuzz/libfuzzer-sys.git" + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[[bin]] +name = "parse" +path = "fuzz_targets/parse.rs" diff --git a/fuzz/fuzz_targets/parse.rs b/fuzz/fuzz_targets/parse.rs new file mode 100644 index 0000000..5d6aa8b --- /dev/null +++ b/fuzz/fuzz_targets/parse.rs @@ -0,0 +1,9 @@ +#![no_main] +#[macro_use] extern crate libfuzzer_sys; +extern crate kairos; + +fuzz_target!(|data: &[u8]| { + if let Ok(data) = std::str::from_utf8(data) { + let _ = kairos::parser::parse(data); + } +}); -- cgit v1.2.3 From 02939068e351ce5e37f5258c3ecb45480f3d3656 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 20 Nov 2017 18:36:04 +0100 Subject: Add out of bounds check and error propagation for NaiveDate::from_ymd() calls * Added recursion limit for error_chain * Added new error for out-of-bounds error * Added IntoTimeType helper trait --- src/error.rs | 5 ++ src/lib.rs | 2 + src/parser/iterator.rs | 9 ++-- src/parser/mod.rs | 12 +++-- src/parser/timetype.rs | 138 +++++++++++++++++++++++++++---------------------- src/timetype.rs | 13 +++++ 6 files changed, 107 insertions(+), 72 deletions(-) diff --git a/src/error.rs b/src/error.rs index b9e7949..43413d7 100644 --- a/src/error.rs +++ b/src/error.rs @@ -59,6 +59,11 @@ error_chain! { display("Cannot compare Month to non-Moment TimeType: {:?}", tt_rep) } + OutOfBounds(y: i32, mo: u32, d: u32, hr: u32, mi: u32, s: u32) { + description("Out of bounds error") + display("Out of bounds: {}-{}-{}T{}:{}:{}", y, mo, d, hr, mi, s) + } + NotADateInsideIterator { description("Cannot calculate date for iterator") display("Cannot calculate date for iterator") diff --git a/src/lib.rs b/src/lib.rs index d39493a..d8e1d7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![recursion_limit="256"] + #[macro_use] extern crate error_chain; extern crate chrono; diff --git a/src/parser/iterator.rs b/src/parser/iterator.rs index a1db5ae..f06edd0 100644 --- a/src/parser/iterator.rs +++ b/src/parser/iterator.rs @@ -1,6 +1,7 @@ use nom::whitespace::sp; use parser::timetype::*; +use timetype::IntoTimeType; use timetype; use iter; use error; @@ -95,22 +96,22 @@ impl Iterator { match self.2 { Some(UntilSpec::Exact(e)) => { - let base = try!(into_ndt(self.0.into())); - let e = try!(into_ndt(e.into())); + let base = try!(into_ndt(self.0.into_timetype()?)); + let e = try!(into_ndt(e.into_timetype()?)); iter::Iter::build(base, recur) .map(|it| UserIterator::UntilIterator(it.until(e))) }, Some(UntilSpec::Times(i)) => { - let base = try!(into_ndt(self.0.into())); + let base = try!(into_ndt(self.0.into_timetype()?)); iter::Iter::build(base, recur) .map(|it| it.times(i)) .map(UserIterator::TimesIter) }, None => { - let base = try!(into_ndt(self.0.into())); + let base = try!(into_ndt(self.0.into_timetype()?)); iter::Iter::build(base, recur) .map(UserIterator::Iterator) }, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 884ba95..f67a3cb 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -52,6 +52,7 @@ mod iterator; use error::Result; use error::KairosErrorKind as KEK; use iter::Iter; +use timetype::IntoTimeType; use parser::timetype::timetype; use parser::iterator::iterator; @@ -60,15 +61,16 @@ pub enum Parsed { TimeType(::timetype::TimeType) } -named!(do_parse, alt_complete!( - do_parse!(it: iterator >> (Parsed::Iterator(it.into_user_iterator()))) | - do_parse!(tt: timetype >> (Parsed::TimeType(tt.into()))) +named!(do_parse>, alt_complete!( + do_parse!(it: iterator >> (Ok(Parsed::Iterator(it.into_user_iterator())))) | + do_parse!(tt: timetype >> (tt.into_timetype().map(Parsed::TimeType))) )); pub fn parse(s: &str) -> Result { match do_parse(s.as_bytes()) { - IResult::Done(_, o) => Ok(o), - IResult::Error(e) => Err(e).map_err(From::from), + IResult::Done(_, Ok(o)) => Ok(o), + IResult::Done(_, Err(e)) => Err(e), + IResult::Error(e) => Err(e).map_err(From::from), IResult::Incomplete(Needed::Unknown) => Err(KEK::UnknownParserError.into()), IResult::Incomplete(Needed::Size(_)) => Err(KEK::UnknownParserError.into()), diff --git a/src/parser/timetype.rs b/src/parser/timetype.rs index 62e321b..bdd7eba 100644 --- a/src/parser/timetype.rs +++ b/src/parser/timetype.rs @@ -5,7 +5,10 @@ use nom::digit; use nom::whitespace::sp; use chrono::NaiveDate; +use timetype::IntoTimeType; use timetype; +use error::Result; +use error::KairosErrorKind as KEK; named!(pub integer, alt!( map_res!( @@ -76,9 +79,9 @@ named!(pub amount_parser, do_parse!( #[derive(Debug, PartialEq, Eq)] pub struct Amount(i64, Unit); -impl Into for Amount { - fn into(self) -> timetype::TimeType { - match self.1 { +impl IntoTimeType for Amount { + fn into_timetype(self) -> Result { + 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), @@ -86,7 +89,7 @@ impl Into for Amount { Unit::Week => timetype::TimeType::weeks(self.0), Unit::Month => timetype::TimeType::months(self.0), Unit::Year => timetype::TimeType::years(self.0), - } + }) } } @@ -110,22 +113,18 @@ pub struct AmountExpr { next: Option<(Operator, Box)>, } -impl Into for AmountExpr { - fn into(self) -> timetype::TimeType { - let mut amount = self.amount.into(); +impl IntoTimeType for AmountExpr { + fn into_timetype(self) -> Result { + 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(); - }, - Operator::Minus => { - amount = amount - (*other_amonut_expr).into(); - }, + Operator::Plus => amount = amount + (*other_amonut_expr).into_timetype()?, + Operator::Minus => amount = amount - (*other_amonut_expr).into_timetype()?, } } - amount + Ok(amount) } } @@ -150,56 +149,69 @@ pub enum ExactDate { Iso8601DateTime(::iso8601::DateTime) } -impl Into for ExactDate { - fn into(self) -> timetype::TimeType { +impl IntoTimeType for ExactDate { + fn into_timetype(self) -> Result { match self { - ExactDate::Today => timetype::TimeType::today(), - ExactDate::Yesterday => timetype::TimeType::today() - timetype::TimeType::days(1), - ExactDate::Tomorrow => timetype::TimeType::today() + timetype::TimeType::days(1), + 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 } => { - let ndt = NaiveDate::from_ymd(year, month, day).and_hms(0, 0, 0); - timetype::TimeType::moment(ndt) - }, - ::iso8601::Date::Week { year, ww, d } => { - let ndt = NaiveDate::from_ymd(year, 1, 1).and_hms(0, 0, 0); - timetype::TimeType::moment(ndt) + ::iso8601::Date::YMD { year, month, day } => NaiveDate::from_ymd_opt(year, month, day) + .ok_or(KEK::OutOfBounds(year, month, day, 0, 0, 0).into()) + .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(KEK::OutOfBounds(year, 1, 1, 0, 0, 0).into()) + .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 } => { - let ndt = NaiveDate::from_ymd(year, 1, 1).and_hms(0, 0, 0); - timetype::TimeType::moment(ndt) - + timetype::TimeType::days(ddd as i64) - }, + }), + + ::iso8601::Date::Ordinal { year, ddd } => NaiveDate::from_ymd_opt(year, 1, 1) + .ok_or(KEK::OutOfBounds(year, 1, 1, 0, 0, 0).into()) + .map(|ndt| ndt.and_hms(0, 0, 0)) + .map(timetype::TimeType::moment) + .map(|m| m + timetype::TimeType::days(ddd as i64)), } }, ExactDate::Iso8601DateTime(::iso8601::DateTime { date, time }) => { let (hour, minute, second) = (time.hour, time.minute, time.second); match date { - ::iso8601::Date::YMD { year, month, day } => { - let ndt = NaiveDate::from_ymd(year, month, day).and_hms(hour, minute, second); - timetype::TimeType::moment(ndt) - }, - ::iso8601::Date::Week { year, ww, d } => { - let ndt = NaiveDate::from_ymd(year, 1, 1).and_hms(0, 0, 0); - timetype::TimeType::moment(ndt) + ::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(KEK::OutOfBounds(year, month, day, hour, minute, second).into()) + .map(timetype::TimeType::moment), + + ::iso8601::Date::Week { year, ww, d } => NaiveDate::from_ymd_opt(year, 1, 1) + .ok_or(KEK::OutOfBounds(year, 1, 1, 0, 0, 0).into()) + .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) + timetype::TimeType::hours(hour as i64) + timetype::TimeType::minutes(minute as i64) + timetype::TimeType::seconds(second as i64) - }, - ::iso8601::Date::Ordinal { year, ddd } => { - let ndt = NaiveDate::from_ymd(year, 1, 1).and_hms(0, 0, 0); - timetype::TimeType::moment(ndt) + }), + + ::iso8601::Date::Ordinal { year, ddd } => NaiveDate::from_ymd_opt(year, 1, 1) + .ok_or(KEK::OutOfBounds(year, 1, 1, 0, 0, 0).into()) + .map(|ndt| ndt.and_hms(0, 0, 0)) + .map(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) - }, + }), } }, } @@ -217,13 +229,13 @@ named!(pub date, do_parse!( #[derive(Debug, PartialEq, Eq)] pub struct Date(ExactDate, Option<(Operator, AmountExpr)>); -impl Into for Date { - fn into(self) -> timetype::TimeType { - let base : timetype::TimeType = self.0.into(); +impl IntoTimeType for Date { + fn into_timetype(self) -> Result { + let base : timetype::TimeType = self.0.into_timetype()?; match self.1 { - Some((Operator::Plus, amount)) => base + amount.into(), - Some((Operator::Minus, amount)) => base - amount.into(), - None => base, + Some((Operator::Plus, amount)) => Ok(base + amount.into_timetype()?), + Some((Operator::Minus, amount)) => Ok(base - amount.into_timetype()?), + None => Ok(base), } } } @@ -234,11 +246,11 @@ pub enum TimeType { AmountExpr(AmountExpr), } -impl Into for TimeType { - fn into(self) -> timetype::TimeType { +impl IntoTimeType for TimeType { + fn into_timetype(self) -> Result { match self { - TimeType::Date(d) => d.into(), - TimeType::AmountExpr(a) => a.into(), + TimeType::Date(d) => d.into_timetype(), + TimeType::AmountExpr(a) => a.into_timetype(), } } } @@ -414,7 +426,7 @@ mod tests { println!("{:#?}", o); - let calc_res : timetype::TimeType = o.into(); + let calc_res : timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); @@ -437,7 +449,7 @@ mod tests { println!("{:#?}", o); - let calc_res : timetype::TimeType = o.into(); + let calc_res : timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); @@ -458,7 +470,7 @@ mod tests { assert!(res.is_done()); let (_, o) = res.unwrap(); - let calc_res : timetype::TimeType = o.into(); + let calc_res : timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); @@ -476,7 +488,7 @@ mod tests { assert!(res.is_done()); let (_, o) = res.unwrap(); - let calc_res : timetype::TimeType = o.into(); + let calc_res : timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); @@ -494,7 +506,7 @@ mod tests { assert!(res.is_done(), "Not done: {:?}", res.unwrap_err().description()); let (_, o) = res.unwrap(); - let calc_res : timetype::TimeType = o.into(); + let calc_res : timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); @@ -511,7 +523,7 @@ mod tests { println!("{:#?}", o); - let calc_res : timetype::TimeType = o.into(); + let calc_res : timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); @@ -532,7 +544,7 @@ mod tests { assert!(res.is_done()); let (_, o) = res.unwrap(); - let calc_res : ::timetype::TimeType = o.into(); + let calc_res : ::timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); @@ -550,7 +562,7 @@ mod tests { assert!(res.is_done(), "Not done: {:?}", res.unwrap_err().description()); let (_, o) = res.unwrap(); - let calc_res : ::timetype::TimeType = o.into(); + let calc_res : ::timetype::TimeType = o.into_timetype().unwrap(); let calc_res = calc_res.calculate(); assert!(calc_res.is_ok()); @@ -567,7 +579,7 @@ mod tests { println!("{:#?}", o); - let calc_res : ::timetype::TimeType = o.into(); + let calc_res : ::timetype::TimeType = o.into_timetype().unwrap(); println!("{:#?}", calc_res); let calc_res = calc_res.calculate(); diff --git a/src/timetype.rs b/src/timetype.rs index 6725edd..fa6fe11 100644 --- a/src/timetype.rs +++ b/src/timetype.rs @@ -438,6 +438,19 @@ impl TimeType { } +/// Helper trait for converting things into a TimeType object +/// +/// Until `TryInto` is stabilized in Rust, we need a helper trait for this. +pub trait IntoTimeType { + fn into_timetype(self) -> Result; +} + +impl IntoTimeType for TimeType { + fn into_timetype(self) -> Result { + Ok(self) + } +} + fn do_calculate(tt: TimeType) -> Result { use timetype::TimeType as TT; -- cgit v1.2.3 From 721057583db22c0087563066f32428b6d5f45805 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 22 Nov 2017 12:18:07 +0100 Subject: Optimize implementation Change the implementation from O(n) to O(1). --- src/util.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/util.rs b/src/util.rs index 7730b2b..1ed9a7a 100644 --- a/src/util.rs +++ b/src/util.rs @@ -2,16 +2,16 @@ pub fn adjust_times_add(mut y: i64, mut mo: i64, mut d: i64, mut h: i64, mut mi: i64, mut s: i64) -> (i64, i64, i64, i64, i64, i64) { + // Subtract $border from the $base as long as the $base is bigger or equal to the $border. + // The number of subtractions are added to $next. macro_rules! fix { { $base:ident, $border:expr, $next:ident } => { - while $base >= $border { - $next += 1; - $base -= $border; - } + $next += ($base - ($base % $border)) / $border; + $base = $base % $border; } } -- cgit v1.2.3 From acdc871abf4f637f9cb15c292e459d95d45920f0 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 22 Nov 2017 14:30:32 +0100 Subject: Use NaiveDate::from_ymd_opt() / ::and_hms_opt() functions for error safety --- src/timetype.rs | 105 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 37 deletions(-) diff --git a/src/timetype.rs b/src/timetype.rs index fa6fe11..7534b8d 100644 --- a/src/timetype.rs +++ b/src/timetype.rs @@ -482,7 +482,10 @@ fn end_of_year(tt: TimeType) -> Result { els @ TT::Years(_) | els @ TT::Addition(_, _) | els @ TT::Subtraction(_, _) => Err(KE::from_kind(KEK::CannotCalculateEndOfYearOn(els))), - TT::Moment(m) => Ok(TT::moment(NaiveDate::from_ymd(m.year(), 12, 31).and_hms(0, 0, 0))), + TT::Moment(m) => NaiveDate::from_ymd_opt(m.year(), 12, 31) + .map(|nd| nd.and_hms(0, 0, 0)) + .map(TT::moment) + .ok_or(KEK::OutOfBounds(m.year() as i32, 12, 31, 0, 0, 0).into()), TT::EndOfYear(e) => do_calculate(*e), TT::EndOfMonth(e) => do_calculate(*e), @@ -510,7 +513,10 @@ fn end_of_month(tt: TimeType) -> Result { els @ TT::Subtraction(_, _) => Err(KE::from_kind(KEK::CannotCalculateEndOfMonthOn(els))), TT::Moment(m) => { let last_day = get_num_of_days_in_month(m.year() as i64, m.month() as i64) as u32; - Ok(TT::moment(NaiveDate::from_ymd(m.year(), m.month(), last_day).and_hms(0, 0, 0))) + NaiveDate::from_ymd_opt(m.year(), m.month(), last_day) + .map(|nd| nd.and_hms(0, 0, 0)) + .map(TT::moment) + .ok_or(KEK::OutOfBounds(m.year() as i32, m.month() as u32, last_day, 0, 0, 0).into()) }, TT::EndOfYear(e) => do_calculate(*e), TT::EndOfMonth(e) => do_calculate(*e), @@ -536,9 +542,10 @@ fn end_of_day(tt: TimeType) -> Result { els @ TT::Years(_) | els @ TT::Addition(_, _) | els @ TT::Subtraction(_, _) => Err(KE::from_kind(KEK::CannotCalculateEndOfMonthOn(els))), - TT::Moment(m) => { - Ok(TT::moment(NaiveDate::from_ymd(m.year(), m.month(), m.day()).and_hms(23, 59, 59))) - }, + TT::Moment(m) => NaiveDate::from_ymd_opt(m.year(), m.month(), m.day()) + .map(|nd| nd.and_hms(23, 59, 59)) + .map(TT::moment) + .ok_or(KEK::OutOfBounds(m.year() as i32, m.month() as u32, m.day() as u32, 23, 59, 59).into()), TT::EndOfYear(e) => do_calculate(*e), TT::EndOfMonth(e) => do_calculate(*e), TT::EndOfDay(e) => do_calculate(*e), @@ -563,10 +570,10 @@ fn end_of_hour(tt: TimeType) -> Result { els @ TT::Years(_) | els @ TT::Addition(_, _) | els @ TT::Subtraction(_, _) => Err(KE::from_kind(KEK::CannotCalculateEndOfMonthOn(els))), - TT::Moment(m) => { - Ok(TT::moment(NaiveDate::from_ymd(m.year(), m.month(), m.day()) - .and_hms(m.hour(), 59, 59))) - }, + TT::Moment(m) => NaiveDate::from_ymd_opt(m.year(), m.month(), m.day()) + .and_then(|nd| nd.and_hms_opt(m.hour(), 59, 59)) + .map(TT::moment) + .ok_or(KEK::OutOfBounds(m.year() as i32, m.month() as u32, m.day() as u32, m.hour() as u32, 59, 59).into()), TT::EndOfYear(e) => do_calculate(*e), TT::EndOfMonth(e) => do_calculate(*e), TT::EndOfDay(e) => do_calculate(*e), @@ -591,10 +598,10 @@ fn end_of_minute(tt: TimeType) -> Result { els @ TT::Years(_) | els @ TT::Addition(_, _) | els @ TT::Subtraction(_, _) => Err(KE::from_kind(KEK::CannotCalculateEndOfMonthOn(els))), - TT::Moment(m) => { - Ok(TT::moment(NaiveDate::from_ymd(m.year(), m.month(), m.day()) - .and_hms(m.hour(), m.minute(), 59))) - }, + TT::Moment(m) => NaiveDate::from_ymd_opt(m.year(), m.month(), m.day()) + .and_then(|nd| nd.and_hms_opt(m.hour(), m.minute(), 59)) + .map(TT::moment) + .ok_or(KEK::OutOfBounds(m.year() as i32, m.month() as u32, m.day() as u32, m.hour() as u32, m.minute() as u32, 59 as u32).into()), TT::EndOfYear(e) => do_calculate(*e), TT::EndOfMonth(e) => do_calculate(*e), TT::EndOfDay(e) => do_calculate(*e), @@ -789,8 +796,10 @@ fn add_to_moment(mom: NaiveDateTime, tt: TimeType) -> Result { let (y, mo, d, h, mi, s) = adjust_times_add(y, mo, d, h, mi, s); - let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32) - .and_hms(h as u32, mi as u32, s as u32); + let tt = NaiveDate::from_ymd_opt(y as i32, mo as u32, d as u32) + .and_then(|nd| nd.and_hms_opt(h as u32, mi as u32, s as u32)) + .ok_or(KEK::OutOfBounds(y as i32, mo as u32, h as u32, h as u32, mi as u32, s as u32).into()) + .map_err(KE::from_kind)?; Ok(TimeType::moment(tt)) }, TT::Minutes(a) => { @@ -803,8 +812,10 @@ fn add_to_moment(mom: NaiveDateTime, tt: TimeType) -> Result { let (y, mo, d, h, mi, s) = adjust_times_add(y, mo, d, h, mi, s); - let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32) - .and_hms(h as u32, mi as u32, s as u32); + let tt = NaiveDate::from_ymd_opt(y as i32, mo as u32, d as u32) + .and_then(|nd| nd.and_hms_opt(h as u32, mi as u32, s as u32)) + .ok_or(KEK::OutOfBounds(y as i32, mo as u32, h as u32, h as u32, mi as u32, s as u32).into()) + .map_err(KE::from_kind)?; Ok(TimeType::moment(tt)) }, TT::Hours(a) => { @@ -817,8 +828,10 @@ fn add_to_moment(mom: NaiveDateTime, tt: TimeType) -> Result { let (y, mo, d, h, mi, s) = adjust_times_add(y, mo, d, h, mi, s); - let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32) - .and_hms(h as u32, mi as u32, s as u32); + let tt = NaiveDate::from_ymd_opt(y as i32, mo as u32, d as u32) + .and_then(|nd| nd.and_hms_opt(h as u32, mi as u32, s as u32)) + .ok_or(KEK::OutOfBounds(y as i32, mo as u32, h as u32, h as u32, mi as u32, s as u32).into()) + .map_err(KE::from_kind)?; Ok(TimeType::moment(tt)) }, TT::Days(a) => { @@ -831,8 +844,10 @@ fn add_to_moment(mom: NaiveDateTime, tt: TimeType) -> Result { let (y, mo, d, h, mi, s) = adjust_times_add(y, mo, d, h, mi, s); - let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32) - .and_hms(h as u32, mi as u32, s as u32); + let tt = NaiveDate::from_ymd_opt(y as i32, mo as u32, d as u32) + .and_then(|nd| nd.and_hms_opt(h as u32, mi as u32, s as u32)) + .ok_or(KEK::OutOfBounds(y as i32, mo as u32, h as u32, h as u32, mi as u32, s as u32).into()) + .map_err(KE::from_kind)?; Ok(TimeType::moment(tt)) }, TT::Months(a) => { @@ -845,8 +860,10 @@ fn add_to_moment(mom: NaiveDateTime, tt: TimeType) -> Result { let (y, mo, d, h, mi, s) = adjust_times_add(y, mo, d, h, mi, s); - let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32) - .and_hms(h as u32, mi as u32, s as u32); + let tt = NaiveDate::from_ymd_opt(y as i32, mo as u32, d as u32) + .and_then(|nd| nd.and_hms_opt(h as u32, mi as u32, s as u32)) + .ok_or(KEK::OutOfBounds(y as i32, mo as u32, h as u32, h as u32, mi as u32, s as u32).into()) + .map_err(KE::from_kind)?; Ok(TimeType::moment(tt)) }, TT::Years(a) => { @@ -859,8 +876,10 @@ fn add_to_moment(mom: NaiveDateTime, tt: TimeType) -> Result { let (y, mo, d, h, mi, s) = adjust_times_add(y, mo, d, h, mi, s); - let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32) - .and_hms(h as u32, mi as u32, s as u32); + let tt = NaiveDate::from_ymd_opt(y as i32, mo as u32, d as u32) + .and_then(|nd| nd.and_hms_opt(h as u32, mi as u32, s as u32)) + .ok_or(KEK::OutOfBounds(y as i32, mo as u32, h as u32, h as u32, mi as u32, s as u32).into()) + .map_err(KE::from_kind)?; Ok(TimeType::moment(tt)) }, TT::Moment(m) => Err(KE::from_kind(KEK::CannotAdd(TT::Moment(mom), TT::Moment(m)))), @@ -1058,8 +1077,10 @@ fn sub_from_moment(mom: NaiveDateTime, tt: TimeType) -> Result { let (y, mo, d, h, mi, s) = adjust_times_sub(y, mo, d, h, mi, s); - let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32) - .and_hms(h as u32, mi as u32, s as u32); + let tt = NaiveDate::from_ymd_opt(y as i32, mo as u32, d as u32) + .and_then(|nd| nd.and_hms_opt(h as u32, mi as u32, s as u32)) + .ok_or(KEK::OutOfBounds(y as i32, mo as u32, h as u32, h as u32, mi as u32, s as u32).into()) + .map_err(KE::from_kind)?; Ok(TimeType::moment(tt)) }, TT::Minutes(a) => { @@ -1072,8 +1093,10 @@ fn sub_from_moment(mom: NaiveDateTime, tt: TimeType) -> Result { let (y, mo, d, h, mi, s) = adjust_times_sub(y, mo, d, h, mi, s); - let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32) - .and_hms(h as u32, mi as u32, s as u32); + let tt = NaiveDate::from_ymd_opt(y as i32, mo as u32, d as u32) + .and_then(|nd| nd.and_hms_opt(h as u32, mi as u32, s as u32)) + .ok_or(KEK::OutOfBounds(y as i32, mo as u32, h as u32, h as u32, mi as u32, s as u32).into()) + .map_err(KE::from_kind)?; Ok(TimeType::moment(tt)) }, TT::Hours(a) => { @@ -1086,8 +1109,10 @@ fn sub_from_moment(mom: NaiveDateTime, tt: TimeType) -> Result { let (y, mo, d, h, mi, s) = adjust_times_sub(y, mo, d, h, mi, s); - let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32) - .and_hms(h as u32, mi as u32, s as u32); + let tt = NaiveDate::from_ymd_opt(y as i32, mo as u32, d as u32) + .and_then(|nd| nd.and_hms_opt(h as u32, mi as u32, s as u32)) + .ok_or(KEK::OutOfBounds(y as i32, mo as u32, h as u32, h as u32, mi as u32, s as u32).into()) + .map_err(KE::from_kind)?; Ok(TimeType::moment(tt)) }, TT::Days(a) => { @@ -1100,8 +1125,10 @@ fn sub_from_moment(mom: NaiveDateTime, tt: TimeType) -> Result { let (y, mo, d, h, mi, s) = adjust_times_sub(y, mo, d, h, mi, s); - let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32) - .and_hms(h as u32, mi as u32, s as u32); + let tt = NaiveDate::from_ymd_opt(y as i32, mo as u32, d as u32) + .and_then(|nd| nd.and_hms_opt(h as u32, mi as u32, s as u32)) + .ok_or(KEK::OutOfBounds(y as i32, mo as u32, h as u32, h as u32, mi as u32, s as u32).into()) + .map_err(KE::from_kind)?; Ok(TimeType::moment(tt)) }, TT::Months(a) => { @@ -1114,8 +1141,10 @@ fn sub_from_moment(mom: NaiveDateTime, tt: TimeType) -> Result { let (y, mo, d, h, mi, s) = adjust_times_sub(y, mo, d, h, mi, s); - let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32) - .and_hms(h as u32, mi as u32, s as u32); + let tt = NaiveDate::from_ymd_opt(y as i32, mo as u32, d as u32) + .and_then(|nd| nd.and_hms_opt(h as u32, mi as u32, s as u32)) + .ok_or(KEK::OutOfBounds(y as i32, mo as u32, h as u32, h as u32, mi as u32, s as u32).into()) + .map_err(KE::from_kind)?; Ok(TimeType::moment(tt)) }, TT::Years(a) => { @@ -1128,8 +1157,10 @@ fn sub_from_moment(mom: NaiveDateTime, tt: TimeType) -> Result { let (y, mo, d, h, mi, s) = adjust_times_sub(y, mo, d, h, mi, s); - let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32) - .and_hms(h as u32, mi as u32, s as u32); + let tt = NaiveDate::from_ymd_opt(y as i32, mo as u32, d as u32) + .and_then(|nd| nd.and_hms_opt(h as u32, mi as u32, s as u32)) + .ok_or(KEK::OutOfBounds(y as i32, mo as u32, h as u32, h as u32, mi as u32, s as u32).into()) + .map_err(KE::from_kind)?; Ok(TimeType::moment(tt)) }, TT::Moment(m) => Err(KE::from_kind(KEK::CannotSub(TT::Moment(mom), TT::Moment(m)))), -- cgit v1.2.3 From a19b88d52c54229faaceb06a470e7c38f23805cf Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 24 Nov 2017 15:30:53 +0100 Subject: Update version string: 0.1.0-beta-1 -> 0.1.0-beta-2 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 12a610c..b4c5d79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kairos" -version = "0.1.0-beta-1" +version = "0.1.0-beta-2" authors = ["Matthias Beyer "] description = "A library on top of chrono to calculate times and dates ergonomically" -- cgit v1.2.3