aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--README.md2
-rw-r--r--src/de.rs13
-rw-r--r--src/lib.rs2
-rw-r--r--src/ser.rs4
-rw-r--r--src/tokens.rs19
-rw-r--r--src/value.rs63
-rw-r--r--test-suite/tests/datetime.rs2
-rw-r--r--test-suite/tests/invalid/string-bad-line-ending-escape.toml3
-rw-r--r--test-suite/tests/serde.rs60
-rw-r--r--test-suite/tests/valid/multiline-string.json8
-rw-r--r--test-suite/tests/valid/multiline-string.toml11
12 files changed, 161 insertions, 28 deletions
diff --git a/Cargo.toml b/Cargo.toml
index e950091..a526fbc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "toml"
-version = "0.4.8"
+version = "0.4.9"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
license = "MIT/Apache-2.0"
readme = "README.md"
diff --git a/README.md b/README.md
index 9fb8b8c..6424c1f 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
[![Documentation](https://docs.rs/toml/badge.svg)](https://docs.rs/toml)
A [TOML][toml] decoder and encoder for Rust. This library is currently compliant
-with the v0.4.0 version of TOML. This library will also likely continue to stay
+with the v0.5.0 version of TOML. This library will also likely continue to stay
up to date with the TOML specification as changes happen.
[toml]: https://github.com/toml-lang/toml
diff --git a/src/de.rs b/src/de.rs
index 9b58606..9334cd3 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -1324,13 +1324,12 @@ impl<'a> Deserializer<'a> {
let start = self.tokens.substr_offset(date);
// Check for space separated date and time.
- if let Some((_, Token::Whitespace(s))) = self.peek()? {
- if s == " " {
- self.next()?;
- // Skip past the hour.
- if let Some((_, Token::Keylike(_))) = self.peek()? {
- self.next()?;
- }
+ let mut lookahead = self.tokens.clone();
+ if let Ok(Some((_, Token::Whitespace(" ")))) = lookahead.next() {
+ // Check if hour follows.
+ if let Ok(Some((_, Token::Keylike(_)))) = lookahead.next() {
+ self.next()?; // skip space
+ self.next()?; // skip keylike hour
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 2f038e8..e36ff52 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,6 @@
//! A [TOML]-parsing library
//!
-//! This library implements a [TOML] v0.4.0 compatible parser,
+//! This library implements a [TOML] v0.5.0 compatible parser,
//! primarily supporting the [`serde`] library for encoding/decoding
//! various types in Rust.
//!
diff --git a/src/ser.rs b/src/ser.rs
index 9f36f59..e1fe1a2 100644
--- a/src/ser.rs
+++ b/src/ser.rs
@@ -1420,11 +1420,11 @@ impl ser::Serializer for StringExtractor {
Err(Error::KeyNotString)
}
- fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, _value: &T)
+ fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T)
-> Result<String, Self::Error>
where T: ser::Serialize,
{
- Err(Error::KeyNotString)
+ value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(self,
diff --git a/src/tokens.rs b/src/tokens.rs
index 15c3b41..382c1ec 100644
--- a/src/tokens.rs
+++ b/src/tokens.rs
@@ -364,7 +364,24 @@ impl<'a> Tokenizer<'a> {
let len = if c == 'u' {4} else {8};
val.push(me.hex(start, i, len)?);
}
- Some((_, '\n')) if multi => {
+ Some((i, c @ ' ')) |
+ Some((i, c @ '\t')) |
+ Some((i, c @ '\n')) if multi => {
+ if c != '\n' {
+ while let Some((_, ch)) = me.chars.clone().next() {
+ match ch {
+ ' ' | '\t' => {
+ me.chars.next();
+ continue
+ },
+ '\n' => {
+ me.chars.next();
+ break
+ },
+ _ => return Err(Error::InvalidEscape(i, c)),
+ }
+ }
+ }
while let Some((_, ch)) = me.chars.clone().next() {
match ch {
' ' | '\t' | '\n' => {
diff --git a/src/value.rs b/src/value.rs
index 64f4555..2e42dc3 100644
--- a/src/value.rs
+++ b/src/value.rs
@@ -675,9 +675,9 @@ impl ser::Serializer for Serializer {
type Error = ::ser::Error;
type SerializeSeq = SerializeVec;
- type SerializeTuple = ser::Impossible<Value, ::ser::Error>;
- type SerializeTupleStruct = ser::Impossible<Value, ::ser::Error>;
- type SerializeTupleVariant = ser::Impossible<Value, ::ser::Error>;
+ type SerializeTuple = SerializeVec;
+ type SerializeTupleStruct = SerializeVec;
+ type SerializeTupleVariant = SerializeVec;
type SerializeMap = SerializeMap;
type SerializeStruct = SerializeMap;
type SerializeStructVariant = ser::Impossible<Value, ::ser::Error>;
@@ -800,23 +800,23 @@ impl ser::Serializer for Serializer {
})
}
- fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, ::ser::Error> {
- Err(::ser::Error::UnsupportedType)
+ fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, ::ser::Error> {
+ self.serialize_seq(Some(len))
}
- fn serialize_tuple_struct(self, _name: &'static str, _len: usize)
+ fn serialize_tuple_struct(self, _name: &'static str, len: usize)
-> Result<Self::SerializeTupleStruct, ::ser::Error> {
- Err(::ser::Error::UnsupportedType)
+ self.serialize_seq(Some(len))
}
fn serialize_tuple_variant(self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
- _len: usize)
+ len: usize)
-> Result<Self::SerializeTupleVariant, ::ser::Error>
{
- Err(::ser::Error::UnsupportedType)
+ self.serialize_seq(Some(len))
}
fn serialize_map(self, _len: Option<usize>)
@@ -869,6 +869,51 @@ impl ser::SerializeSeq for SerializeVec {
}
}
+impl ser::SerializeTuple for SerializeVec {
+ type Ok = Value;
+ type Error = ::ser::Error;
+
+ fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), ::ser::Error>
+ where T: ser::Serialize
+ {
+ ser::SerializeSeq::serialize_element(self, value)
+ }
+
+ fn end(self) -> Result<Value, ::ser::Error> {
+ ser::SerializeSeq::end(self)
+ }
+}
+
+impl ser::SerializeTupleStruct for SerializeVec {
+ type Ok = Value;
+ type Error = ::ser::Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), ::ser::Error>
+ where T: ser::Serialize
+ {
+ ser::SerializeSeq::serialize_element(self, value)
+ }
+
+ fn end(self) -> Result<Value, ::ser::Error> {
+ ser::SerializeSeq::end(self)
+ }
+}
+
+impl ser::SerializeTupleVariant for SerializeVec {
+ type Ok = Value;
+ type Error = ::ser::Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), ::ser::Error>
+ where T: ser::Serialize
+ {
+ ser::SerializeSeq::serialize_element(self, value)
+ }
+
+ fn end(self) -> Result<Value, ::ser::Error> {
+ ser::SerializeSeq::end(self)
+ }
+}
+
impl ser::SerializeMap for SerializeMap {
type Ok = Value;
type Error = ::ser::Error;
diff --git a/test-suite/tests/datetime.rs b/test-suite/tests/datetime.rs
index f3b77e3..a0064fb 100644
--- a/test-suite/tests/datetime.rs
+++ b/test-suite/tests/datetime.rs
@@ -21,6 +21,8 @@ fn times() {
good("1997-09-09T09:09:09-09:09");
good("1997-09-09T09:09:09");
good("1997-09-09");
+ dogood("1997-09-09 ", "1997-09-09");
+ dogood("1997-09-09 # comment", "1997-09-09");
good("09:09:09");
good("1997-09-09T09:09:09.09Z");
good("1997-09-09T09:09:09.09+09:09");
diff --git a/test-suite/tests/invalid/string-bad-line-ending-escape.toml b/test-suite/tests/invalid/string-bad-line-ending-escape.toml
new file mode 100644
index 0000000..32e2c48
--- /dev/null
+++ b/test-suite/tests/invalid/string-bad-line-ending-escape.toml
@@ -0,0 +1,3 @@
+invalid-escape = """\
+ This string has a non whitespace-character after the line ending escape. \ a
+"""
diff --git a/test-suite/tests/serde.rs b/test-suite/tests/serde.rs
index b97937f..c1b6d78 100644
--- a/test-suite/tests/serde.rs
+++ b/test-suite/tests/serde.rs
@@ -580,15 +580,63 @@ fn table_structs_empty() {
#[test]
fn fixed_size_array() {
- #[derive(Serialize, PartialEq, Eq, Deserialize, Debug)]
+ #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
struct Entity {
pos: [i32; 2]
}
- let text = "pos = [1, 2]\n";
- let value: Entity = toml::from_str(text).unwrap();
- let expected = Entity { pos: [1, 2] };
- assert_eq!(value, expected);
- assert_eq!(toml::to_string(&value).unwrap(), text);
+
+ equivalent! {
+ Entity { pos: [1, 2] },
+ Table(map! {
+ pos: Array(vec![
+ Integer(1),
+ Integer(2),
+ ])
+ }),
+ }
+}
+
+#[test]
+fn homogeneous_tuple() {
+ #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+ struct Collection {
+ elems: (i64, i64, i64),
+ }
+
+ equivalent! {
+ Collection { elems: (0, 1, 2) },
+ Table(map! {
+ elems: Array(vec![
+ Integer(0),
+ Integer(1),
+ Integer(2),
+ ])
+ }),
+ }
+}
+
+#[test]
+fn homogeneous_tuple_struct() {
+ #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+ struct Object(Vec<String>, Vec<String>, Vec<String>);
+
+ equivalent! {
+ map! {
+ obj: Object(vec!["foo".to_string()], vec![], vec!["bar".to_string(), "baz".to_string()])
+ },
+ Table(map! {
+ obj: Array(vec![
+ Array(vec![
+ Value::String("foo".to_string()),
+ ]),
+ Array(vec![]),
+ Array(vec![
+ Value::String("bar".to_string()),
+ Value::String("baz".to_string()),
+ ]),
+ ])
+ }),
+ }
}
#[test]
diff --git a/test-suite/tests/valid/multiline-string.json b/test-suite/tests/valid/multiline-string.json
index 075bf50..3223bae 100644
--- a/test-suite/tests/valid/multiline-string.json
+++ b/test-suite/tests/valid/multiline-string.json
@@ -15,6 +15,10 @@
"type": "string",
"value": ""
},
+ "multiline_empty_five": {
+ "type": "string",
+ "value": ""
+ },
"equivalent_one": {
"type": "string",
"value": "The quick brown fox jumps over the lazy dog."
@@ -26,5 +30,9 @@
"equivalent_three": {
"type": "string",
"value": "The quick brown fox jumps over the lazy dog."
+ },
+ "equivalent_four": {
+ "type": "string",
+ "value": "The quick brown fox jumps over the lazy dog."
}
}
diff --git a/test-suite/tests/valid/multiline-string.toml b/test-suite/tests/valid/multiline-string.toml
index 15b1143..2c4237f 100644
--- a/test-suite/tests/valid/multiline-string.toml
+++ b/test-suite/tests/valid/multiline-string.toml
@@ -7,6 +7,11 @@ multiline_empty_four = """\
\
\
"""
+multiline_empty_five = """\
+ \
+ \
+ \
+ """
equivalent_one = "The quick brown fox jumps over the lazy dog."
equivalent_two = """
@@ -21,3 +26,9 @@ equivalent_three = """\
fox jumps over \
the lazy dog.\
"""
+
+equivalent_four = """\
+ The quick brown \
+ fox jumps over \
+ the lazy dog.\
+ """