1use serde_spanned::Spanned;
2
3use crate::alloc_prelude::*;
4use crate::de::DeString;
5use crate::de::DeTable;
6use crate::de::DeValue;
7use crate::de::parser::array::on_array;
8use crate::de::parser::key::on_key;
9use crate::de::parser::prelude::*;
10use crate::de::parser::value::on_scalar;
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 #[cfg(feature = "debug")]
110 let _scope = TraceScope::new("inline_table::capture_key");
111 if let Some(key) = key {
112 self.current_key = Some((path, key));
113 }
114 }
115
116 fn finish_key(&mut self, _event: &toml_parser::parser::Event) {
117 #[cfg(feature = "debug")]
118 let _scope = TraceScope::new("inline_table::finish_key");
119 self.seen_keyval_sep = true;
120 }
121
122 fn capture_value(&mut self, _event: &toml_parser::parser::Event, value: Spanned<DeValue<'i>>) {
123 #[cfg(feature = "debug")]
124 let _scope = TraceScope::new("inline_table::capture_value");
125 self.current_value = Some(value);
126 }
127
128 fn finish_value(
129 &mut self,
130 _event: &toml_parser::parser::Event,
131 result: &mut DeTable<'i>,
132 errors: &mut dyn ErrorSink,
133 ) {
134 #[cfg(feature = "debug")]
135 let _scope = TraceScope::new("inline_table::finish_value");
136 self.seen_keyval_sep = false;
137 if let (Some((path, key)), Some(value)) =
138 (self.current_key.take(), self.current_value.take())
139 {
140 let Some(table) = descend_path(result, &path, true, errors) else {
141 return;
142 };
143
144 let mixed_table_types = table.is_dotted() == path.is_empty();
146 if mixed_table_types {
147 #[cfg(feature = "debug")]
148 trace(
149 &format!("table.dotted={}", table.is_dotted()),
150 anstyle::AnsiColor::Red.on_default(),
151 );
152 #[cfg(feature = "debug")]
153 trace(
154 &format!("path.is_empty={}", path.is_empty()),
155 anstyle::AnsiColor::Red.on_default(),
156 );
157 let key_span = get_key_span(&key);
158 errors.report_error(ParseError::new("duplicate key").with_unexpected(key_span));
159 } else {
160 let key_span = get_key_span(&key);
161 match table.entry(key) {
162 Entry::Vacant(o) => {
163 o.insert(value);
164 }
165 Entry::Occupied(o) => {
166 let old_span = get_key_span(o.key());
167 errors.report_error(
168 ParseError::new("duplicate key")
169 .with_unexpected(key_span)
170 .with_context(old_span),
171 );
172 }
173 }
174 }
175 }
176 }
177
178 fn close(
179 &mut self,
180 _open_event: &toml_parser::parser::Event,
181 _close_event: &toml_parser::parser::Event,
182 _result: &mut DeTable<'i>,
183 ) {
184 #[cfg(feature = "debug")]
185 let _scope = TraceScope::new("inline_table::close");
186 }
187}
188
189fn descend_path<'a, 'i>(
190 mut table: &'a mut DeTable<'i>,
191 path: &'a [Spanned<DeString<'i>>],
192 dotted: bool,
193 errors: &mut dyn ErrorSink,
194) -> Option<&'a mut DeTable<'i>> {
195 #[cfg(feature = "debug")]
196 let _scope = TraceScope::new("inline_table::descend_path");
197 #[cfg(feature = "debug")]
198 trace(
199 &format!(
200 "path={:?}",
201 path.iter().map(|k| k.get_ref()).collect::<Vec<_>>()
202 ),
203 anstyle::AnsiColor::Blue.on_default(),
204 );
205 for key in path.iter() {
206 #[cfg(feature = "debug")]
207 trace(
208 &format!("path[_]={:?}", key.get_ref()),
209 anstyle::AnsiColor::Blue.on_default(),
210 );
211 table = match table.entry(key.clone()) {
212 Entry::Vacant(entry) => {
213 let mut new_table = DeTable::new();
214 new_table.set_implicit(true);
215 new_table.set_dotted(dotted);
216 new_table.set_inline(true);
217 let value = DeValue::Table(new_table);
218 let value = Spanned::new(key.span(), value);
219 let value = entry.insert(value);
220 value.as_mut().as_table_mut().unwrap()
221 }
222 Entry::Occupied(entry) => {
223 let spanned = entry.into_mut();
224 let old_span = spanned.span();
225 match spanned.as_mut() {
226 DeValue::Table(sweet_child_of_mine) => {
227 let mixed_table_types = dotted && !sweet_child_of_mine.is_implicit();
231 if mixed_table_types {
232 #[cfg(feature = "debug")]
233 trace(
234 &format!("dotted={dotted}"),
235 anstyle::AnsiColor::Red.on_default(),
236 );
237 #[cfg(feature = "debug")]
238 trace(
239 &format!(
240 "sweet_child_of_mine.is_implicit={}",
241 sweet_child_of_mine.is_implicit()
242 ),
243 anstyle::AnsiColor::Red.on_default(),
244 );
245 let key_span = get_key_span(key);
246 errors.report_error(
247 ParseError::new("duplicate key").with_unexpected(key_span),
248 );
249 return None;
250 }
251 sweet_child_of_mine
252 }
253 existing => {
254 let old_span =
255 toml_parser::Span::new_unchecked(old_span.start, old_span.end);
256 let key_span = get_key_span(key);
257 errors.report_error(
258 ParseError::new(format!(
259 "cannot extend value of type {} with a dotted key",
260 existing.type_str()
261 ))
262 .with_unexpected(key_span)
263 .with_context(old_span),
264 );
265 return None;
266 }
267 }
268 }
269 };
270 }
271 Some(table)
272}
273
274fn get_key_span(key: &Spanned<DeString<'_>>) -> toml_parser::Span {
275 let key_span = key.span();
276 toml_parser::Span::new_unchecked(key_span.start, key_span.end)
277}