toml/de/parser/
inline_table.rs

1use serde_spanned::Spanned;
2
3use crate::alloc_prelude::*;
4use crate::de::parser::array::on_array;
5use crate::de::parser::key::on_key;
6use crate::de::parser::prelude::*;
7use crate::de::parser::value::on_scalar;
8use crate::de::DeString;
9use crate::de::DeTable;
10use crate::de::DeValue;
11use crate::map::Entry;
12
13/// ```bnf
14/// ;; Inline Table
15///
16/// inline-table = inline-table-open inline-table-keyvals inline-table-close
17/// ```
18pub(crate) fn on_inline_table<'i>(
19    open_event: &toml_parser::parser::Event,
20    input: &mut Input<'_>,
21    source: toml_parser::Source<'i>,
22    errors: &mut dyn ErrorSink,
23) -> Spanned<DeValue<'i>> {
24    #[cfg(feature = "debug")]
25    let _scope = TraceScope::new("inline_table::on_inline_table");
26    let mut result = DeTable::new();
27    result.set_inline(true);
28    let mut close_span = open_event.span();
29
30    let mut state = State::default();
31    while let Some(event) = input.next_token() {
32        close_span = event.span();
33        match event.kind() {
34            EventKind::StdTableOpen
35            | EventKind::ArrayTableOpen
36            | EventKind::StdTableClose
37            | EventKind::ArrayClose
38            | EventKind::ArrayTableClose
39            | EventKind::KeySep => {
40                #[cfg(feature = "debug")]
41                trace(
42                    &format!("unexpected {event:?}"),
43                    anstyle::AnsiColor::Red.on_default(),
44                );
45                break;
46            }
47            EventKind::Error => {
48                #[cfg(feature = "debug")]
49                trace(
50                    &format!("unexpected {event:?}"),
51                    anstyle::AnsiColor::Red.on_default(),
52                );
53                continue;
54            }
55            EventKind::SimpleKey => {
56                let (path, key) = on_key(event, input, source, errors);
57                state.capture_key(event, path, key);
58            }
59            EventKind::KeyValSep => {
60                state.finish_key(event);
61            }
62            EventKind::InlineTableOpen => {
63                let value = on_inline_table(event, input, source, errors);
64                state.capture_value(event, value);
65            }
66            EventKind::ArrayOpen => {
67                let value = on_array(event, input, source, errors);
68                state.capture_value(event, value);
69            }
70            EventKind::Scalar => {
71                let value = on_scalar(event, source, errors);
72                state.capture_value(event, value);
73            }
74            EventKind::ValueSep => {
75                state.finish_value(event, &mut result, errors);
76            }
77            EventKind::Whitespace | EventKind::Comment | EventKind::Newline => {
78                state.whitespace(event);
79            }
80            EventKind::InlineTableClose => {
81                state.finish_value(event, &mut result, errors);
82                state.close(open_event, event, &mut result);
83                break;
84            }
85        }
86    }
87
88    let span = open_event.span().start()..close_span.end();
89
90    Spanned::new(span, DeValue::Table(result))
91}
92
93#[derive(Default)]
94struct State<'i> {
95    current_key: Option<(Vec<Spanned<DeString<'i>>>, Spanned<DeString<'i>>)>,
96    seen_keyval_sep: bool,
97    current_value: Option<Spanned<DeValue<'i>>>,
98}
99
100impl<'i> State<'i> {
101    fn whitespace(&mut self, _event: &toml_parser::parser::Event) {}
102
103    fn capture_key(
104        &mut self,
105        _event: &toml_parser::parser::Event,
106        path: Vec<Spanned<DeString<'i>>>,
107        key: Option<Spanned<DeString<'i>>>,
108    ) {
109        if let Some(key) = key {
110            self.current_key = Some((path, key));
111        }
112    }
113
114    fn finish_key(&mut self, _event: &toml_parser::parser::Event) {
115        self.seen_keyval_sep = true;
116    }
117
118    fn capture_value(&mut self, _event: &toml_parser::parser::Event, value: Spanned<DeValue<'i>>) {
119        self.current_value = Some(value);
120    }
121
122    fn finish_value(
123        &mut self,
124        _event: &toml_parser::parser::Event,
125        result: &mut DeTable<'i>,
126        errors: &mut dyn ErrorSink,
127    ) {
128        #[cfg(feature = "debug")]
129        let _scope = TraceScope::new("inline_table::finish_value");
130        self.seen_keyval_sep = false;
131        if let (Some((path, key)), Some(value)) =
132            (self.current_key.take(), self.current_value.take())
133        {
134            let Some(table) = descend_path(result, &path, true, errors) else {
135                return;
136            };
137
138            // "Likewise, using dotted keys to redefine tables already defined in [table] form is not allowed"
139            let mixed_table_types = table.is_dotted() == path.is_empty();
140            if mixed_table_types {
141                let key_span = get_key_span(&key);
142                errors.report_error(ParseError::new("duplicate key").with_unexpected(key_span));
143            } else {
144                let key_span = get_key_span(&key);
145                match table.entry(key) {
146                    Entry::Vacant(o) => {
147                        o.insert(value);
148                    }
149                    Entry::Occupied(o) => {
150                        let old_span = get_key_span(o.key());
151                        errors.report_error(
152                            ParseError::new("duplicate key")
153                                .with_unexpected(key_span)
154                                .with_context(old_span),
155                        );
156                    }
157                }
158            }
159        }
160    }
161
162    fn close(
163        &mut self,
164        _open_event: &toml_parser::parser::Event,
165        _close_event: &toml_parser::parser::Event,
166        _result: &mut DeTable<'i>,
167    ) {
168        #[cfg(feature = "debug")]
169        let _scope = TraceScope::new("inline_table::close");
170    }
171}
172
173fn descend_path<'a, 'i>(
174    mut table: &'a mut DeTable<'i>,
175    path: &'a [Spanned<DeString<'i>>],
176    dotted: bool,
177    errors: &mut dyn ErrorSink,
178) -> Option<&'a mut DeTable<'i>> {
179    #[cfg(feature = "debug")]
180    let _scope = TraceScope::new("inline_table::descend_path");
181    #[cfg(feature = "debug")]
182    trace(
183        &format!(
184            "key={:?}",
185            path.iter().map(|k| k.get_ref()).collect::<Vec<_>>()
186        ),
187        anstyle::AnsiColor::Blue.on_default(),
188    );
189    for key in path.iter() {
190        table = match table.entry(key.clone()) {
191            Entry::Vacant(entry) => {
192                let mut new_table = DeTable::new();
193                new_table.set_implicit(true);
194                new_table.set_dotted(dotted);
195                new_table.set_inline(true);
196                let value = DeValue::Table(new_table);
197                let value = Spanned::new(key.span(), value);
198                let value = entry.insert(value);
199                value.as_mut().as_table_mut().unwrap()
200            }
201            Entry::Occupied(entry) => {
202                let spanned = entry.into_mut();
203                match spanned.as_mut() {
204                    DeValue::Table(ref mut sweet_child_of_mine) => {
205                        // Since tables cannot be defined more than once, redefining such tables using a
206                        // [table] header is not allowed. Likewise, using dotted keys to redefine tables
207                        // already defined in [table] form is not allowed.
208                        if dotted && !sweet_child_of_mine.is_implicit() {
209                            let key_span = get_key_span(key);
210                            errors.report_error(
211                                ParseError::new("duplicate key").with_unexpected(key_span),
212                            );
213                            return None;
214                        }
215                        sweet_child_of_mine
216                    }
217                    item => {
218                        let key_span = get_key_span(key);
219                        errors.report_error(
220                            ParseError::new(format!(
221                                "cannot extend value of type {} with a dotted key",
222                                item.type_str()
223                            ))
224                            .with_unexpected(key_span),
225                        );
226                        return None;
227                    }
228                }
229            }
230        };
231    }
232    Some(table)
233}
234
235fn get_key_span(key: &Spanned<DeString<'_>>) -> toml_parser::Span {
236    let key_span = key.span();
237    toml_parser::Span::new_unchecked(key_span.start, key_span.end)
238}