use serde_spanned::Spanned; use crate::alloc_prelude::*; use crate::de::parser::array::on_array; use crate::de::parser::key::on_key; use crate::de::parser::prelude::*; use crate::de::parser::value::on_scalar; use crate::de::DeString; use crate::de::DeTable; use crate::de::DeValue; use crate::map::Entry; /// ```bnf /// ;; Inline Table /// /// inline-table = inline-table-open inline-table-keyvals inline-table-close /// ``` pub(crate) fn on_inline_table<'i>( open_event: &toml_parser::parser::Event, input: &mut Input<'_>, source: toml_parser::Source<'i>, errors: &mut dyn ErrorSink, ) -> Spanned> { #[cfg(feature = "debug")] let _scope = TraceScope::new("inline_table::on_inline_table"); let mut result = DeTable::new(); result.set_inline(true); let mut close_span = open_event.span(); let mut state = State::default(); while let Some(event) = input.next_token() { close_span = event.span(); match event.kind() { EventKind::StdTableOpen | EventKind::ArrayTableOpen | EventKind::StdTableClose | EventKind::ArrayClose | EventKind::ArrayTableClose | EventKind::KeySep => { #[cfg(feature = "debug")] trace( &format!("unexpected {event:?}"), anstyle::AnsiColor::Red.on_default(), ); break; } EventKind::Error => { #[cfg(feature = "debug")] trace( &format!("unexpected {event:?}"), anstyle::AnsiColor::Red.on_default(), ); continue; } EventKind::SimpleKey => { let (path, key) = on_key(event, input, source, errors); state.capture_key(event, path, key); } EventKind::KeyValSep => { state.finish_key(event); } EventKind::InlineTableOpen => { let value = on_inline_table(event, input, source, errors); state.capture_value(event, value); } EventKind::ArrayOpen => { let value = on_array(event, input, source, errors); state.capture_value(event, value); } EventKind::Scalar => { let value = on_scalar(event, source, errors); state.capture_value(event, value); } EventKind::ValueSep => { state.finish_value(event, &mut result, errors); } EventKind::Whitespace | EventKind::Comment | EventKind::Newline => { state.whitespace(event); } EventKind::InlineTableClose => { state.finish_value(event, &mut result, errors); state.close(open_event, event, &mut result); break; } } } let span = open_event.span().start()..close_span.end(); Spanned::new(span, DeValue::Table(result)) } #[derive(Default)] struct State<'i> { current_key: Option<(Vec>>, Spanned>)>, seen_keyval_sep: bool, current_value: Option>>, } impl<'i> State<'i> { fn whitespace(&mut self, _event: &toml_parser::parser::Event) {} fn capture_key( &mut self, _event: &toml_parser::parser::Event, path: Vec>>, key: Option>>, ) { if let Some(key) = key { self.current_key = Some((path, key)); } } fn finish_key(&mut self, _event: &toml_parser::parser::Event) { self.seen_keyval_sep = true; } fn capture_value(&mut self, _event: &toml_parser::parser::Event, value: Spanned>) { self.current_value = Some(value); } fn finish_value( &mut self, _event: &toml_parser::parser::Event, result: &mut DeTable<'i>, errors: &mut dyn ErrorSink, ) { #[cfg(feature = "debug")] let _scope = TraceScope::new("inline_table::finish_value"); self.seen_keyval_sep = false; if let (Some((path, key)), Some(value)) = (self.current_key.take(), self.current_value.take()) { let Some(table) = descend_path(result, &path, true, errors) else { return; }; // "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 { let key_span = get_key_span(&key); errors.report_error(ParseError::new("duplicate key").with_unexpected(key_span)); } else { let key_span = get_key_span(&key); match table.entry(key) { Entry::Vacant(o) => { o.insert(value); } Entry::Occupied(o) => { let old_span = get_key_span(o.key()); errors.report_error( ParseError::new("duplicate key") .with_unexpected(key_span) .with_context(old_span), ); } } } } } fn close( &mut self, _open_event: &toml_parser::parser::Event, _close_event: &toml_parser::parser::Event, _result: &mut DeTable<'i>, ) { #[cfg(feature = "debug")] let _scope = TraceScope::new("inline_table::close"); } } fn descend_path<'a, 'i>( mut table: &'a mut DeTable<'i>, path: &'a [Spanned>], dotted: bool, errors: &mut dyn ErrorSink, ) -> Option<&'a mut DeTable<'i>> { #[cfg(feature = "debug")] let _scope = TraceScope::new("inline_table::descend_path"); #[cfg(feature = "debug")] trace( &format!( "key={:?}", path.iter().map(|k| k.get_ref()).collect::>() ), anstyle::AnsiColor::Blue.on_default(), ); for key in path.iter() { table = match table.entry(key.clone()) { Entry::Vacant(entry) => { let mut new_table = DeTable::new(); new_table.set_implicit(true); new_table.set_dotted(dotted); new_table.set_inline(true); let value = DeValue::Table(new_table); let value = Spanned::new(key.span(), value); let value = entry.insert(value); value.as_mut().as_table_mut().unwrap() } Entry::Occupied(entry) => { let spanned = entry.into_mut(); match spanned.as_mut() { DeValue::Table(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() { let key_span = get_key_span(key); errors.report_error( ParseError::new("duplicate key").with_unexpected(key_span), ); return None; } sweet_child_of_mine } item => { let key_span = get_key_span(key); errors.report_error( ParseError::new(format!( "cannot extend value of type {} with a dotted key", item.type_str() )) .with_unexpected(key_span), ); return None; } } } }; } Some(table) } fn get_key_span(key: &Spanned>) -> toml_parser::Span { let key_span = key.span(); toml_parser::Span::new_unchecked(key_span.start, key_span.end) }