From b7fb44f8d6c7ea9693df758d038328dce5dd019a Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Sun, 18 Feb 2018 12:39:18 +0100 Subject: [PATCH 2/2] use the CompleteByteSlice input type to fix Incomplete usage --- src/lib.rs | 6 +- src/parsers.rs | 195 +++++++++++++++++++++++----------------------- tests/lib.rs | 206 +++++++++++++++++++++++++------------------------ 3 files changed, 209 insertions(+), 198 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4d8c965..59be807 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,7 +100,7 @@ impl Default for Date { /// let date = iso8601::date("2015-11-02").unwrap(); /// ``` pub fn date(string: &str) -> Result { - if let Ok((_, parsed)) = parsers::parse_date(string.as_bytes()) { + if let Ok((_, parsed)) = parsers::parse_date(nom::types::CompleteByteSlice(string.as_bytes())) { Ok(parsed) } else { Err(format!("Parser Error: {}", string)) @@ -123,7 +123,7 @@ pub fn date(string: &str) -> Result { /// let time = iso8601::time("21:56:42").unwrap(); /// ``` pub fn time(string: &str) -> Result { - if let Ok((_, parsed)) = parsers::parse_time(string.as_bytes()) { + if let Ok((_, parsed)) = parsers::parse_time(nom::types::CompleteByteSlice(string.as_bytes())) { Ok(parsed) } else { Err(format!("Parser Error: {}", string)) @@ -143,7 +143,7 @@ pub fn time(string: &str) -> Result { /// let dt = iso8601::datetime("2015-11-03T21:56").unwrap(); /// ``` pub fn datetime(string: &str) -> Result { - if let Ok((_left_overs, parsed)) = parsers::parse_datetime(string.as_bytes()) { + if let Ok((_left_overs, parsed)) = parsers::parse_datetime(nom::types::CompleteByteSlice(string.as_bytes())) { Ok(parsed) } else { Err(format!("Parser Error: {}", string)) diff --git a/src/parsers.rs b/src/parsers.rs index ed87388..e9679d5 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -10,12 +10,14 @@ use helper::*; use nom::{self, is_digit, digit}; +use nom::types::CompleteByteSlice; use super::{Time, DateTime, Date}; use std::str::{self, FromStr}; macro_rules! empty_or( - ($i:expr, $submac:ident!( $($args:tt)* )) => ( - if $i.len() == 0 { + ($i:expr, $submac:ident!( $($args:tt)* )) => ({ + use nom::InputLength; + if $i.input_len() == 0 { Ok(($i, None)) } else { match $submac!($i, $($args)*) { @@ -26,7 +28,7 @@ macro_rules! empty_or( } } - ); + }); ); macro_rules! check( @@ -34,7 +36,7 @@ macro_rules! check( { let mut failed = false; - for &idx in $input { + for &idx in $input.0 { if !$submac!(idx, $($args)*) { failed = true; break; @@ -43,7 +45,7 @@ macro_rules! check( if failed { Err(nom::Err::Error(error_position!($input, nom::ErrorKind::Custom(20u32)))) } else { - Ok((&b""[..], $input)) + Ok((CompleteByteSlice(&b""[..]), $input)) } } ); @@ -61,52 +63,52 @@ macro_rules! char_between( ); ); -named!(take_4_digits, flat_map!(take!(4), check!(is_digit))); +named!(take_4_digits, flat_map!(take!(4), check!(is_digit))); // year -named!(year_prefix, alt!(tag!("+") | tag!("-"))); -named!(year , do_parse!( +named!(year_prefix, alt!(tag!("+") | tag!("-"))); +named!(year , do_parse!( pref: opt!(year_prefix) >> year: call!(take_4_digits) >> ( match pref { - Some(b"-") => -buf_to_i32(year), - _ => buf_to_i32(year) + Some(CompleteByteSlice(b"-")) => -buf_to_i32(year.0), + _ => buf_to_i32(year.0) } ))); // MM -named!(lower_month , do_parse!(tag!("0") >> s:char_between!('1', '9') >> (buf_to_u32(s)))); -named!(upper_month , do_parse!(tag!("1") >> s:char_between!('0', '2') >> (10+buf_to_u32(s)))); -named!(month , alt!(lower_month | upper_month)); +named!(lower_month , do_parse!(tag!("0") >> s:char_between!('1', '9') >> (buf_to_u32(s.0)))); +named!(upper_month , do_parse!(tag!("1") >> s:char_between!('0', '2') >> (10+buf_to_u32(s.0)))); +named!(month , alt!(lower_month | upper_month)); // DD -named!(day_zero , do_parse!(tag!("0") >> s:char_between!('1', '9') >> (buf_to_u32(s)))); -named!(day_one , do_parse!(tag!("1") >> s:char_between!('0', '9') >> (10+buf_to_u32(s)))); -named!(day_two , do_parse!(tag!("2") >> s:char_between!('0', '9') >> (20+buf_to_u32(s)))); -named!(day_three , do_parse!(tag!("3") >> s:char_between!('0', '1') >> (30+buf_to_u32(s)))); -named!(day , alt!(day_zero | day_one | day_two | day_three)); +named!(day_zero , do_parse!(tag!("0") >> s:char_between!('1', '9') >> (buf_to_u32(s.0)))); +named!(day_one , do_parse!(tag!("1") >> s:char_between!('0', '9') >> (10+buf_to_u32(s.0)))); +named!(day_two , do_parse!(tag!("2") >> s:char_between!('0', '9') >> (20+buf_to_u32(s.0)))); +named!(day_three , do_parse!(tag!("3") >> s:char_between!('0', '1') >> (30+buf_to_u32(s.0)))); +named!(day , alt!(day_zero | day_one | day_two | day_three)); // WW // reusing day_N parsers, sorry -named!(week_three , do_parse!(tag!("3") >> s:char_between!('0', '9') >> (30+buf_to_u32(s)))); -named!(week_four , do_parse!(tag!("4") >> s:char_between!('0', '9') >> (40+buf_to_u32(s)))); -named!(week_five , do_parse!(tag!("5") >> s:char_between!('0', '3') >> (50+buf_to_u32(s)))); +named!(week_three , do_parse!(tag!("3") >> s:char_between!('0', '9') >> (30+buf_to_u32(s.0)))); +named!(week_four , do_parse!(tag!("4") >> s:char_between!('0', '9') >> (40+buf_to_u32(s.0)))); +named!(week_five , do_parse!(tag!("5") >> s:char_between!('0', '3') >> (50+buf_to_u32(s.0)))); -named!(week , alt!(day_zero | day_one | day_two | week_three| week_four | week_five )); -named!(week_day , map!(char_between!('1', '7') , |s| buf_to_u32(s))); +named!(week , alt!(day_zero | day_one | day_two | week_three| week_four | week_five )); +named!(week_day , map!(char_between!('1', '7') , |s| buf_to_u32(s.0))); // ordinal DDD -named!(ord_day , do_parse!( +named!(ord_day , do_parse!( a:char_between!('0','3') >> b:char_between!('0','9') >> c:char_between!('0','9') >> - ( buf_to_u32(a)*100 + buf_to_u32(b)*10 + buf_to_u32(c) ) + ( buf_to_u32(a.0)*100 + buf_to_u32(b.0)*10 + buf_to_u32(c.0) ) )); // YYYY-MM-DD -named!(pub ymd_date , do_parse!( +named!(pub ymd_date , do_parse!( y: year >> opt!(tag!("-")) >> m: month >> @@ -116,7 +118,7 @@ named!(pub ymd_date , do_parse!( )); // YYYY-MM-DD -named!(pub ordinal_date , do_parse!( +named!(pub ordinal_date , do_parse!( y: year >> opt!(tag!("-")) >> d: ord_day >> @@ -124,7 +126,7 @@ named!(pub ordinal_date , do_parse!( )); // YYYY-"W"WW-D -named!(pub iso_week_date , do_parse!( +named!(pub iso_week_date , do_parse!( y: year >> opt!(tag!("-")) >> tag!("W") >> @@ -134,42 +136,42 @@ named!(pub iso_week_date , do_parse!( ( Date::Week{ year: y, ww: w, d: d } ) )); -named!(pub parse_date , alt!( ymd_date | iso_week_date | ordinal_date ) ); +named!(pub parse_date , alt!( ymd_date | iso_week_date | ordinal_date ) ); // TIME // HH -named!(lower_hour , do_parse!(f:char_between!('0','1') >> +named!(lower_hour , do_parse!(f:char_between!('0','1') >> s:char_between!('0','9') >> - ( buf_to_u32(f)*10 + buf_to_u32(s) ))); -named!(upper_hour , do_parse!(tag!("2") >> + ( buf_to_u32(f.0)*10 + buf_to_u32(s.0) ))); +named!(upper_hour , do_parse!(tag!("2") >> s:char_between!('0','4') >> - (20+buf_to_u32(s)))); -named!(hour , alt!(lower_hour | upper_hour)); + (20+buf_to_u32(s.0)))); +named!(hour , alt!(lower_hour | upper_hour)); // MM -named!(below_sixty , do_parse!(f:char_between!('0','5') >> +named!(below_sixty , do_parse!(f:char_between!('0','5') >> s:char_between!('0','9') >> - ( buf_to_u32(f)*10 + buf_to_u32(s) ) )); -named!(upto_sixty , alt!(below_sixty | map!(tag!("60"), |_| 60))); + ( buf_to_u32(f.0)*10 + buf_to_u32(s.0) ) )); +named!(upto_sixty , alt!(below_sixty | map!(tag!("60"), |_| 60))); -fn into_fraction_string(digits: &[u8]) -> Result { +fn into_fraction_string(digits: CompleteByteSlice) -> Result { let mut s = String::from("0."); - s += str::from_utf8(digits).unwrap(); + s += str::from_utf8(digits.0).unwrap(); FromStr::from_str(&s) } -named!(minute , call!(below_sixty)); -named!(second , call!(upto_sixty)); -named!(fractions , map_res!(digit, into_fraction_string)); +named!(minute , call!(below_sixty)); +named!(second , call!(upto_sixty)); +named!(fractions , map_res!(digit, into_fraction_string)); fn millisecond(fraction: f32) -> u32 { (1000.0 * fraction) as u32 } // HH:MM:[SS][.(m*)][(Z|+...|-...)] -named!(pub parse_time