29: Properly handle no date content being found r=bspeice a=bspeice

Fixes #22 

Co-authored-by: Bradlee Speice <bradlee@speice.io>
pull/30/head
bors[bot] 2020-06-11 19:33:20 +00:00 committed by GitHub
commit 23f50fb62b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 16 deletions

View File

@ -147,6 +147,8 @@ pub enum ParseError {
/// Parser unable to make sense of year/month/day parameters in the time string; /// Parser unable to make sense of year/month/day parameters in the time string;
/// please report to maintainer as the timestring likely exposes a bug in implementation /// please report to maintainer as the timestring likely exposes a bug in implementation
YearMonthDayError(&'static str), YearMonthDayError(&'static str),
/// Parser unable to find any date/time-related content in the supplied string
NoDate,
} }
impl fmt::Display for ParseError { impl fmt::Display for ParseError {
@ -624,6 +626,31 @@ struct ParsingResult {
any_unused_tokens: Vec<String>, any_unused_tokens: Vec<String>,
} }
macro_rules! option_len {
($o:expr) => {{
if $o.is_some() {
1
} else {
0
}
}};
}
impl ParsingResult {
fn len(&self) -> usize {
option_len!(self.year)
+ option_len!(self.month)
+ option_len!(self.day)
+ option_len!(self.weekday)
+ option_len!(self.hour)
+ option_len!(self.minute)
+ option_len!(self.second)
+ option_len!(self.microsecond)
+ option_len!(self.tzname)
+ option_len!(self.ampm)
}
}
/// Parser is responsible for doing the actual work of understanding a time string. /// Parser is responsible for doing the actual work of understanding a time string.
/// The root level `parse` function is responsible for constructing a default `Parser` /// The root level `parse` function is responsible for constructing a default `Parser`
/// and triggering its behavior. /// and triggering its behavior.
@ -691,6 +718,10 @@ impl Parser {
let (res, tokens) = let (res, tokens) =
self.parse_with_tokens(timestr, dayfirst, yearfirst, fuzzy, fuzzy_with_tokens)?; self.parse_with_tokens(timestr, dayfirst, yearfirst, fuzzy, fuzzy_with_tokens)?;
if res.len() == 0 {
return Err(ParseError::NoDate);
}
let naive = self.build_naive(&res, &default_ts)?; let naive = self.build_naive(&res, &default_ts)?;
if !ignoretz { if !ignoretz {

View File

@ -17,23 +17,20 @@ fn test_fuzz() {
parse("2..\x00\x000d\x00+\x010d\x01\x00\x00\x00+"), parse("2..\x00\x000d\x00+\x010d\x01\x00\x00\x00+"),
Err(ParseError::UnrecognizedFormat) Err(ParseError::UnrecognizedFormat)
); );
// OverflowError: Python int too large to convert to C long
// assert_eq!(parse("8888884444444888444444444881"), Err(ParseError::AmPmWithoutHour));
let default = NaiveDate::from_ymd(2016, 6, 29).and_hms(0, 0, 0); let default = NaiveDate::from_ymd(2016, 6, 29).and_hms(0, 0, 0);
let p = Parser::default(); let p = Parser::default();
let res = p let res = p.parse(
.parse( "\x0D\x31",
"\x0D\x31", None,
None, None,
None, false,
false, false,
false, Some(&default),
Some(&default), false,
false, &HashMap::new(),
&HashMap::new(), );
) assert_eq!(res, Err(ParseError::NoDate));
.unwrap();
assert_eq!(res.0, default);
assert_eq!( assert_eq!(
parse("\x2D\x2D\x32\x31\x38\x6D"), parse("\x2D\x2D\x32\x31\x38\x6D"),
@ -45,5 +42,9 @@ fn test_fuzz() {
fn large_int() { fn large_int() {
let parse_result = parse("1412409095009.jpg"); let parse_result = parse("1412409095009.jpg");
assert!(parse_result.is_err()); assert!(parse_result.is_err());
println!("{:?}", parse_result); }
#[test]
fn empty_string() {
assert_eq!(parse(""), Err(ParseError::NoDate))
} }