diff options
-rw-r--r-- | .travis.yml | 37 | ||||
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | src/de.rs | 36 | ||||
-rw-r--r-- | test-suite/tests/backcompat.rs | 24 | ||||
-rw-r--r-- | test-suite/tests/invalid.rs | 2 | ||||
-rw-r--r-- | test-suite/tests/invalid/duplicate-table.toml | 8 |
7 files changed, 82 insertions, 30 deletions
diff --git a/.travis.yml b/.travis.yml index 88ce22f..c28b88e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,31 +1,24 @@ language: rust -rust: - - 1.15.0 - - stable - - beta - - nightly -sudo: false -before_script: - - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH +matrix: + include: + - rust: stable + - rust: beta + - rust: nightly + - name: "master doc to gh-pages" + rust: nightly + script: + - cargo doc --no-deps + deploy: + provider: script + script: curl -LsSf https://git.io/fhJ8n | rustc - && (cd target/doc && ../../rust_out) + skip_cleanup: true + on: + branch: master script: - cargo test - cargo test --features preserve_order - cargo test --manifest-path test-suite/Cargo.toml - rustdoc --test README.md -L target - - test "$TRAVIS_RUST_VERSION" != "1.15.0" && cargo doc --no-deps || echo "skipping cargo doc" -after_success: - - travis-cargo --only nightly doc-upload - - travis-cargo coveralls --no-sudo -env: - global: - secure: "IDm3Oc3bmIL4/6zixovwkuTkbinqWnKdLfeuKTtHqT4ZbVy+rxTDQBgLGfVngymjciHWkJnvQ8/2nT3/KW4MPNY9Sqt3NfWvO7vj9cXypeNeJ4xFrVK49F7CMM4KTCeSMlDKR1C0TVYGgxFIViLtBw/imivl9fk6J489eKv36sA=" - notifications: email: on_success: never -addons: - apt: - packages: - - libcurl4-openssl-dev - - libelf-dev - - libdw-dev @@ -15,6 +15,9 @@ facilitate deserializing and serializing Rust structures. """ categories = ["config", "encoding", "parser-implementations"] +[workspace] +members = ['test-suite'] + [badges] travis-ci = { repository = "alexcrichton/toml-rs" } @@ -1,6 +1,6 @@ # toml-rs -[![Build Status](https://travis-ci.org/alexcrichton/toml-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/toml-rs) +[![Build Status](https://travis-ci.com/alexcrichton/toml-rs.svg?branch=master)](https://travis-ci.com/alexcrichton/toml-rs) [![Coverage Status](https://coveralls.io/repos/alexcrichton/toml-rs/badge.svg?branch=master&service=github)](https://coveralls.io/github/alexcrichton/toml-rs?branch=master) [![Latest Version](https://img.shields.io/crates/v/toml.svg)](https://crates.io/crates/toml) [![Documentation](https://docs.rs/toml/badge.svg)](https://docs.rs/toml) @@ -197,6 +197,7 @@ enum ErrorKind { /// Deserialization implementation for TOML. pub struct Deserializer<'a> { require_newline_after_table: bool, + allow_duplciate_after_longer_table: bool, input: &'a str, tokens: Tokenizer<'a>, } @@ -335,12 +336,24 @@ impl<'de, 'b> de::MapAccess<'de> for MapVisitor<'de, 'b> { // Test to see if we're duplicating our parent's table, and if so // then this is an error in the toml format - if self.cur_parent != pos - && self.tables[self.cur_parent].header == self.tables[pos].header - { - let at = self.tables[pos].at; - let name = self.tables[pos].header.join("."); - return Err(self.de.error(at, ErrorKind::DuplicateTable(name))); + if self.cur_parent != pos { + if self.tables[self.cur_parent].header == self.tables[pos].header { + let at = self.tables[pos].at; + let name = self.tables[pos].header.join("."); + return Err(self.de.error(at, ErrorKind::DuplicateTable(name))); + } + + // If we're here we know we should share the same prefix, and if + // the longer table was defined first then we want to narrow + // down our parent's length if possible to ensure that we catch + // duplicate tables defined afterwards. + if !self.de.allow_duplciate_after_longer_table { + let parent_len = self.tables[self.cur_parent].header.len(); + let cur_len = self.tables[pos].header.len(); + if cur_len < parent_len { + self.cur_parent = pos; + } + } } let table = &mut self.tables[pos]; @@ -965,6 +978,7 @@ impl<'a> Deserializer<'a> { tokens: Tokenizer::new(input), input: input, require_newline_after_table: true, + allow_duplciate_after_longer_table: false, } } @@ -986,6 +1000,16 @@ impl<'a> Deserializer<'a> { self.require_newline_after_table = require; } + /// Historical versions of toml-rs accidentally allowed a duplicate table + /// header after a longer table header was previously defined. This is + /// invalid according to the TOML spec, however. + /// + /// This option can be set to `true` (the default is `false`) to emulate + /// this behavior for backwards compatibility with older toml-rs versions. + pub fn set_allow_duplicate_after_longer_table(&mut self, allow: bool) { + self.allow_duplciate_after_longer_table = allow; + } + fn tables(&mut self) -> Result<Vec<Table<'a>>, Error> { let mut tables = Vec::new(); let mut cur_table = Table { diff --git a/test-suite/tests/backcompat.rs b/test-suite/tests/backcompat.rs index 1b3f599..e06eefc 100644 --- a/test-suite/tests/backcompat.rs +++ b/test-suite/tests/backcompat.rs @@ -4,7 +4,7 @@ extern crate serde; use serde::de::Deserialize; #[test] -fn main() { +fn newlines_after_tables() { let s = " [a] foo = 1 [[b]] foo = 1 @@ -17,3 +17,25 @@ fn main() { assert_eq!(value["a"]["foo"].as_integer(), Some(1)); assert_eq!(value["b"][0]["foo"].as_integer(), Some(1)); } + +#[test] +fn allow_duplicate_after_longer() { + let s = " + [dependencies.openssl-sys] + version = 1 + + [dependencies] + libc = 1 + + [dependencies] + bitflags = 1 + "; + assert!(s.parse::<toml::Value>().is_err()); + + let mut d = toml::de::Deserializer::new(s); + d.set_allow_duplicate_after_longer_table(true); + let value = toml::Value::deserialize(&mut d).unwrap(); + assert_eq!(value["dependencies"]["openssl-sys"]["version"].as_integer(), Some(1)); + assert_eq!(value["dependencies"]["libc"].as_integer(), Some(1)); + assert_eq!(value["dependencies"]["bitflags"].as_integer(), Some(1)); +} diff --git a/test-suite/tests/invalid.rs b/test-suite/tests/invalid.rs index 4679684..9f36e2c 100644 --- a/test-suite/tests/invalid.rs +++ b/test-suite/tests/invalid.rs @@ -96,3 +96,5 @@ test!(text_before_array_separator, include_str!("invalid/text-before-array-separator.toml")); test!(text_in_array, include_str!("invalid/text-in-array.toml")); +test!(duplicate_table, + include_str!("invalid/duplicate-table.toml")); diff --git a/test-suite/tests/invalid/duplicate-table.toml b/test-suite/tests/invalid/duplicate-table.toml new file mode 100644 index 0000000..5bd2571 --- /dev/null +++ b/test-suite/tests/invalid/duplicate-table.toml @@ -0,0 +1,8 @@ +[dependencies.openssl-sys] +version = "0.5.2" + +[dependencies] +libc = "0.1" + +[dependencies] +bitflags = "0.1.1" |