From ef24de24a82fe681581cc130f342363c47c0969a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 7 Jun 2024 07:48:48 +0200 Subject: Merging upstream version 1.75.0+dfsg1. Signed-off-by: Daniel Baumann --- .../toml_edit-0.19.11/src/parser/inline_table.rs | 182 +++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 vendor/toml_edit-0.19.11/src/parser/inline_table.rs (limited to 'vendor/toml_edit-0.19.11/src/parser/inline_table.rs') diff --git a/vendor/toml_edit-0.19.11/src/parser/inline_table.rs b/vendor/toml_edit-0.19.11/src/parser/inline_table.rs new file mode 100644 index 000000000..0a75c2104 --- /dev/null +++ b/vendor/toml_edit-0.19.11/src/parser/inline_table.rs @@ -0,0 +1,182 @@ +use winnow::combinator::cut_err; +use winnow::combinator::delimited; +use winnow::combinator::separated0; +use winnow::token::one_of; + +use crate::key::Key; +use crate::parser::errors::CustomError; +use crate::parser::key::key; +use crate::parser::prelude::*; +use crate::parser::trivia::ws; +use crate::parser::value::value; +use crate::table::TableKeyValue; +use crate::{InlineTable, InternalString, Item, RawString, Value}; + +use indexmap::map::Entry; + +// ;; Inline Table + +// inline-table = inline-table-open inline-table-keyvals inline-table-close +pub(crate) fn inline_table( + check: RecursionCheck, +) -> impl FnMut(Input<'_>) -> IResult, InlineTable, ParserError<'_>> { + move |input| { + delimited( + INLINE_TABLE_OPEN, + cut_err(inline_table_keyvals(check).try_map(|(kv, p)| table_from_pairs(kv, p))), + cut_err(INLINE_TABLE_CLOSE) + .context(Context::Expression("inline table")) + .context(Context::Expected(ParserValue::CharLiteral('}'))), + ) + .parse_next(input) + } +} + +fn table_from_pairs( + v: Vec<(Vec, TableKeyValue)>, + preamble: RawString, +) -> Result { + let mut root = InlineTable::new(); + root.set_preamble(preamble); + // Assuming almost all pairs will be directly in `root` + root.items.reserve(v.len()); + + for (path, kv) in v { + let table = descend_path(&mut root, &path)?; + let key: InternalString = kv.key.get_internal().into(); + match table.items.entry(key) { + Entry::Vacant(o) => { + o.insert(kv); + } + Entry::Occupied(o) => { + return Err(CustomError::DuplicateKey { + key: o.key().as_str().into(), + table: None, + }); + } + } + } + Ok(root) +} + +fn descend_path<'a>( + mut table: &'a mut InlineTable, + path: &'a [Key], +) -> Result<&'a mut InlineTable, CustomError> { + 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); + + Value::InlineTable(new_table) + }); + match *entry { + Value::InlineTable(ref mut sweet_child_of_mine) => { + table = sweet_child_of_mine; + } + ref v => { + return Err(CustomError::extend_wrong_type(path, i, v.type_name())); + } + } + } + Ok(table) +} + +// inline-table-open = %x7B ws ; { +pub(crate) const INLINE_TABLE_OPEN: u8 = b'{'; +// inline-table-close = ws %x7D ; } +const INLINE_TABLE_CLOSE: u8 = b'}'; +// inline-table-sep = ws %x2C ws ; , Comma +const INLINE_TABLE_SEP: u8 = b','; +// keyval-sep = ws %x3D ws ; = +pub(crate) const KEYVAL_SEP: u8 = b'='; + +// inline-table-keyvals = [ inline-table-keyvals-non-empty ] +// inline-table-keyvals-non-empty = +// ( key keyval-sep val inline-table-sep inline-table-keyvals-non-empty ) / +// ( key keyval-sep val ) + +fn inline_table_keyvals( + check: RecursionCheck, +) -> impl FnMut( + Input<'_>, +) -> IResult, (Vec<(Vec, TableKeyValue)>, RawString), ParserError<'_>> { + move |input| { + let check = check.recursing(input)?; + ( + separated0(keyval(check), INLINE_TABLE_SEP), + ws.span().map(RawString::with_span), + ) + .parse_next(input) + } +} + +fn keyval( + check: RecursionCheck, +) -> impl FnMut(Input<'_>) -> IResult, (Vec, TableKeyValue), ParserError<'_>> { + move |input| { + ( + key, + cut_err(( + one_of(KEYVAL_SEP) + .context(Context::Expected(ParserValue::CharLiteral('.'))) + .context(Context::Expected(ParserValue::CharLiteral('='))), + (ws.span(), value(check), ws.span()), + )), + ) + .map(|(key, (_, v))| { + let mut path = key; + let key = path.pop().expect("grammar ensures at least 1"); + + let (pre, v, suf) = v; + let pre = RawString::with_span(pre); + let suf = RawString::with_span(suf); + let v = v.decorated(pre, suf); + ( + path, + TableKeyValue { + key, + value: Item::Value(v), + }, + ) + }) + .parse_next(input) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn inline_tables() { + let inputs = [ + r#"{}"#, + r#"{ }"#, + r#"{a = 1e165}"#, + r#"{ hello = "world", a = 1}"#, + r#"{ hello.world = "a" }"#, + ]; + for input in inputs { + dbg!(input); + let mut parsed = inline_table(Default::default()).parse(new_input(input)); + if let Ok(parsed) = &mut parsed { + parsed.despan(input); + } + assert_eq!(parsed.map(|a| a.to_string()), Ok(input.to_owned())); + } + } + + #[test] + fn invalid_inline_tables() { + let invalid_inputs = [r#"{a = 1e165"#, r#"{ hello = "world", a = 2, hello = 1}"#]; + for input in invalid_inputs { + dbg!(input); + let mut parsed = inline_table(Default::default()).parse(new_input(input)); + if let Ok(parsed) = &mut parsed { + parsed.despan(input); + } + assert!(parsed.is_err()); + } + } +} -- cgit v1.2.3