diff options
Diffstat (limited to 'src/parser/inline_table.rs')
-rw-r--r-- | src/parser/inline_table.rs | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/src/parser/inline_table.rs b/src/parser/inline_table.rs index 994e003..c2e6619 100644 --- a/src/parser/inline_table.rs +++ b/src/parser/inline_table.rs @@ -5,7 +5,7 @@ use winnow::token::one_of; use winnow::trace::trace; use crate::key::Key; -use crate::parser::errors::CustomError; +use crate::parser::error::CustomError; use crate::parser::key::key; use crate::parser::prelude::*; use crate::parser::trivia::ws; @@ -44,6 +44,16 @@ fn table_from_pairs( for (path, kv) in v { let table = descend_path(&mut root, &path)?; + + // "Likewise, using dotted keys to redefine tables already defined in [table] form is not allowed" + let mixed_table_types = table.is_dotted() == path.is_empty(); + if mixed_table_types { + return Err(CustomError::DuplicateKey { + key: kv.key.get().into(), + table: None, + }); + } + let key: InternalString = kv.key.get_internal().into(); match table.items.entry(key) { Entry::Vacant(o) => { @@ -64,15 +74,26 @@ fn descend_path<'a>( mut table: &'a mut InlineTable, path: &'a [Key], ) -> Result<&'a mut InlineTable, CustomError> { + let dotted = !path.is_empty(); for (i, key) in path.iter().enumerate() { let entry = table.entry_format(key).or_insert_with(|| { let mut new_table = InlineTable::new(); - new_table.set_dotted(true); + new_table.set_implicit(dotted); + new_table.set_dotted(dotted); Value::InlineTable(new_table) }); match *entry { Value::InlineTable(ref mut sweet_child_of_mine) => { + // Since tables cannot be defined more than once, redefining such tables using a + // [table] header is not allowed. Likewise, using dotted keys to redefine tables + // already defined in [table] form is not allowed. + if dotted && !sweet_child_of_mine.is_implicit() { + return Err(CustomError::DuplicateKey { + key: key.get().into(), + table: None, + }); + } table = sweet_child_of_mine; } ref v => { @@ -144,6 +165,8 @@ fn keyval<'i>( } #[cfg(test)] +#[cfg(feature = "parse")] +#[cfg(feature = "display")] mod test { use super::*; |