toml/de/parser/
inline_table.rs1use 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
13pub(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 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 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}