Fix incorrectly reported spans for Datetime

This commit is contained in:
John-John Tedro 2018-05-07 05:36:09 +02:00
parent 8a9ae07de5
commit 407845d620
3 changed files with 47 additions and 13 deletions

View file

@ -853,16 +853,16 @@ impl<'a> Deserializer<'a> {
{ {
if s.contains('T') || (s.len() > 1 && s[1..].contains('-')) && if s.contains('T') || (s.len() > 1 && s[1..].contains('-')) &&
!s.contains("e-") { !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), e: E::Datetime(d),
start: span.start, start: start,
end: span.end end: end
}) })
} else if self.eat(Token::Colon)? { } 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), e: E::Datetime(d),
start: span.start, start: start,
end: span.end end: end
}) })
} else { } else {
self.number(span, s) self.number(span, s)
@ -1006,9 +1006,10 @@ impl<'a> Deserializer<'a> {
}) })
} }
fn datetime(&mut self, date: &'a str, colon_eaten: bool) fn datetime(&mut self, mut span: Span, date: &'a str, colon_eaten: bool)
-> Result<&'a str, Error> { -> Result<(Span, &'a str), Error> {
let start = self.tokens.substr_offset(date); let start = self.tokens.substr_offset(date);
if colon_eaten || self.eat(Token::Colon)? { if colon_eaten || self.eat(Token::Colon)? {
// minutes // minutes
match self.next()? { match self.next()? {
@ -1018,13 +1019,17 @@ impl<'a> Deserializer<'a> {
// Seconds // Seconds
self.expect(Token::Colon)?; self.expect(Token::Colon)?;
match self.next()? { match self.next()? {
Some((_, Token::Keylike(_))) => {} Some((Span { end, .. }, Token::Keylike(_))) => {
span.end = end;
},
_ => return Err(self.error(start, ErrorKind::DateInvalid)), _ => return Err(self.error(start, ErrorKind::DateInvalid)),
} }
// Fractional seconds // Fractional seconds
if self.eat(Token::Period)? { if self.eat(Token::Period)? {
match self.next()? { match self.next()? {
Some((_, Token::Keylike(_))) => {} Some((Span { end, .. }, Token::Keylike(_))) => {
span.end = end;
},
_ => return Err(self.error(start, ErrorKind::DateInvalid)), _ => return Err(self.error(start, ErrorKind::DateInvalid)),
} }
} }
@ -1032,19 +1037,24 @@ impl<'a> Deserializer<'a> {
// offset // offset
if self.eat(Token::Plus)? { if self.eat(Token::Plus)? {
match self.next()? { match self.next()? {
Some((_, Token::Keylike(_))) => {} Some((Span { end, .. }, Token::Keylike(_))) => {
span.end = end;
},
_ => return Err(self.error(start, ErrorKind::DateInvalid)), _ => return Err(self.error(start, ErrorKind::DateInvalid)),
} }
} }
if self.eat(Token::Colon)? { if self.eat(Token::Colon)? {
match self.next()? { match self.next()? {
Some((_, Token::Keylike(_))) => {} Some((Span { end, .. }, Token::Keylike(_))) => {
span.end = end;
},
_ => return Err(self.error(start, ErrorKind::DateInvalid)), _ => return Err(self.error(start, ErrorKind::DateInvalid)),
} }
} }
} }
let end = self.tokens.current(); 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 // TODO(#140): shouldn't buffer up this entire table in memory, it'd be

View file

@ -171,4 +171,5 @@ mod tokens;
pub mod macros; pub mod macros;
pub mod spanned; pub mod spanned;
#[doc(no_inline)]
pub use spanned::Spanned; pub use spanned::Spanned;

View file

@ -4,8 +4,26 @@ extern crate toml;
extern crate serde_derive; extern crate serde_derive;
use toml::Spanned; use toml::Spanned;
use toml::value::Datetime;
use std::collections::HashMap; 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] #[test]
fn test_spanned_field() { fn test_spanned_field() {
#[derive(Deserialize)] #[derive(Deserialize)]
@ -40,4 +58,9 @@ fn test_spanned_field() {
"foo = \"1997-09-09T09:09:09Z\"", "foo = \"1997-09-09T09:09:09Z\"",
"\"1997-09-09T09:09:09Z\"" "\"1997-09-09T09:09:09Z\""
); );
for expected in good_datetimes() {
let s = format!("foo = {}", expected);
good::<Datetime>(&s, expected);
}
} }