diff --git a/Cargo.toml b/Cargo.toml index fd55d1a..8c7bef2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ repository = "https://github.com/pydantic/speedate/" [dependencies] strum = { version = "0.25", features = ["derive"] } strum_macros = "0.25" +lexical-core = { version = "0.8.5", features = ["format"] } [dev-dependencies] chrono = "0.4.19" diff --git a/src/date.rs b/src/date.rs index aeac4c7..dc8ebe7 100644 --- a/src/date.rs +++ b/src/date.rs @@ -1,6 +1,6 @@ use std::fmt; -use crate::numbers::int_parse_bytes; +use crate::numbers::parse_int_with_json_semantics; use crate::{get_digit_unchecked, DateTime, ParseError}; /// A Date @@ -159,9 +159,9 @@ impl Date { pub fn parse_bytes(bytes: &[u8]) -> Result { match Self::parse_bytes_rfc3339(bytes) { Ok(d) => Ok(d), - Err(e) => match int_parse_bytes(bytes) { - Some(int) => Self::from_timestamp(int, true), - None => Err(e), + Err(e) => match parse_int_with_json_semantics(bytes) { + Some(int_or_float) => Self::from_timestamp(int_or_float, true), + _ => Err(e), }, } } diff --git a/src/numbers.rs b/src/numbers.rs index 85a4190..3b77845 100644 --- a/src/numbers.rs +++ b/src/numbers.rs @@ -1,3 +1,17 @@ +use lexical_core::{format as lexical_format, parse_with_options, ParseIntegerOptions}; + +// Parse bytes as an int with JSON semantics. +pub fn parse_int_with_json_semantics(bytes: &[u8]) -> Option { + const JSON: u128 = lexical_format::JSON; + let int_options = ParseIntegerOptions::new(); + let int_result: Result = parse_with_options::(bytes, &int_options); + + match int_result { + Ok(parsed_int) => Some(parsed_int), + Err(_) => None, + } +} + /// Parse a string as an int. /// /// This is around 2x faster than using `str::parse::()` diff --git a/tests/main.rs b/tests/main.rs index 50a9df9..041682a 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -1348,3 +1348,14 @@ fn test_time_config_builder() { ); assert_eq!(TimeConfigBuilder::new().build(), TimeConfig::builder().build()); } + +#[test] +fn date_dash_err() { + let error = match Date::parse_str("-") { + Ok(_) => panic!("unexpectedly valid"), + Err(e) => e, + }; + assert_eq!(error, ParseError::TooShort); + assert_eq!(error.to_string(), "too_short"); + assert_eq!(error.get_documentation(), Some("input is too short")); +}