From 407845d62038c93a19d1d934b3a555ec9c005277 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Mon, 7 May 2018 05:36:09 +0200 Subject: [PATCH] Fix incorrectly reported spans for Datetime --- src/de.rs | 36 +++++++++++++++++++++++------------- src/lib.rs | 1 + test-suite/tests/spanned.rs | 23 +++++++++++++++++++++++ 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/de.rs b/src/de.rs index 5521e00..1d43cc9 100644 --- a/src/de.rs +++ b/src/de.rs @@ -853,16 +853,16 @@ impl<'a> Deserializer<'a> { { if s.contains('T') || (s.len() > 1 && s[1..].contains('-')) && !s.contains("e-") { - self.datetime(s, false).map(|d| Value { + self.datetime(span, s, false).map(|(Span { start, end }, d)| Value { e: E::Datetime(d), - start: span.start, - end: span.end + start: start, + end: end }) } else if self.eat(Token::Colon)? { - self.datetime(s, true).map(|d| Value { + self.datetime(span, s, true).map(|(Span { start, end }, d)| Value { e: E::Datetime(d), - start: span.start, - end: span.end + start: start, + end: end }) } else { self.number(span, s) @@ -1006,9 +1006,10 @@ impl<'a> Deserializer<'a> { }) } - fn datetime(&mut self, date: &'a str, colon_eaten: bool) - -> Result<&'a str, Error> { + fn datetime(&mut self, mut span: Span, date: &'a str, colon_eaten: bool) + -> Result<(Span, &'a str), Error> { let start = self.tokens.substr_offset(date); + if colon_eaten || self.eat(Token::Colon)? { // minutes match self.next()? { @@ -1018,13 +1019,17 @@ impl<'a> Deserializer<'a> { // Seconds self.expect(Token::Colon)?; match self.next()? { - Some((_, Token::Keylike(_))) => {} + Some((Span { end, .. }, Token::Keylike(_))) => { + span.end = end; + }, _ => return Err(self.error(start, ErrorKind::DateInvalid)), } // Fractional seconds if self.eat(Token::Period)? { match self.next()? { - Some((_, Token::Keylike(_))) => {} + Some((Span { end, .. }, Token::Keylike(_))) => { + span.end = end; + }, _ => return Err(self.error(start, ErrorKind::DateInvalid)), } } @@ -1032,19 +1037,24 @@ impl<'a> Deserializer<'a> { // offset if self.eat(Token::Plus)? { match self.next()? { - Some((_, Token::Keylike(_))) => {} + Some((Span { end, .. }, Token::Keylike(_))) => { + span.end = end; + }, _ => return Err(self.error(start, ErrorKind::DateInvalid)), } } if self.eat(Token::Colon)? { match self.next()? { - Some((_, Token::Keylike(_))) => {} + Some((Span { end, .. }, Token::Keylike(_))) => { + span.end = end; + }, _ => return Err(self.error(start, ErrorKind::DateInvalid)), } } } + let end = self.tokens.current(); - Ok(&self.tokens.input()[start..end]) + Ok((span, &self.tokens.input()[start..end])) } // TODO(#140): shouldn't buffer up this entire table in memory, it'd be diff --git a/src/lib.rs b/src/lib.rs index b90612c..6fbf5d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -171,4 +171,5 @@ mod tokens; pub mod macros; pub mod spanned; +#[doc(no_inline)] pub use spanned::Spanned; diff --git a/test-suite/tests/spanned.rs b/test-suite/tests/spanned.rs index c5dc28e..4339a0c 100644 --- a/test-suite/tests/spanned.rs +++ b/test-suite/tests/spanned.rs @@ -4,8 +4,26 @@ extern crate toml; extern crate serde_derive; use toml::Spanned; +use toml::value::Datetime; use std::collections::HashMap; +/// A set of good datetimes. +pub fn good_datetimes() -> Vec<&'static str> { + let mut v = Vec::new(); + v.push("1997-09-09T09:09:09Z"); + v.push("1997-09-09T09:09:09+09:09"); + v.push("1997-09-09T09:09:09-09:09"); + v.push("1997-09-09T09:09:09"); + v.push("1997-09-09"); + v.push("09:09:09"); + v.push("1997-09-09T09:09:09.09Z"); + v.push("1997-09-09T09:09:09.09+09:09"); + v.push("1997-09-09T09:09:09.09-09:09"); + v.push("1997-09-09T09:09:09.09"); + v.push("09:09:09.09"); + v +} + #[test] fn test_spanned_field() { #[derive(Deserialize)] @@ -40,4 +58,9 @@ fn test_spanned_field() { "foo = \"1997-09-09T09:09:09Z\"", "\"1997-09-09T09:09:09Z\"" ); + + for expected in good_datetimes() { + let s = format!("foo = {}", expected); + good::(&s, expected); + } }