aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml37
-rw-r--r--Cargo.toml3
-rw-r--r--README.md2
-rw-r--r--src/de.rs36
-rw-r--r--test-suite/tests/backcompat.rs24
-rw-r--r--test-suite/tests/invalid.rs2
-rw-r--r--test-suite/tests/invalid/duplicate-table.toml8
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
diff --git a/Cargo.toml b/Cargo.toml
index 39dae2d..408337d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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" }
diff --git a/README.md b/README.md
index 6424c1f..8770bfd 100644
--- a/README.md
+++ b/README.md
@@ -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)
diff --git a/src/de.rs b/src/de.rs
index 5f04027..85aef61 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -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"