1use serde_spanned::Spanned;
2
3use crate::alloc_prelude::*;
4use crate::de::parser::key::on_key;
5use crate::de::parser::prelude::*;
6use crate::de::parser::value::value;
7use crate::de::DeString;
8use crate::de::DeValue;
9use crate::de::{DeArray, DeTable};
10use crate::map::Entry;
11
12pub(crate) fn document<'i>(
23 input: &mut Input<'_>,
24 source: toml_parser::Source<'i>,
25 errors: &mut dyn ErrorSink,
26) -> Spanned<DeTable<'i>> {
27 #[cfg(feature = "debug")]
28 let _scope = TraceScope::new("document::document");
29 let mut state = State::default();
30 while let Some(event) = input.next_token() {
31 match event.kind() {
32 EventKind::InlineTableOpen
33 | EventKind::InlineTableClose
34 | EventKind::ArrayOpen
35 | EventKind::ArrayClose
36 | EventKind::Scalar
37 | EventKind::ValueSep
38 | EventKind::Error
39 | EventKind::KeySep
40 | EventKind::KeyValSep
41 | EventKind::StdTableClose
42 | EventKind::ArrayTableClose => {
43 #[cfg(feature = "debug")]
44 trace(
45 &format!("unexpected {event:?}"),
46 anstyle::AnsiColor::Red.on_default(),
47 );
48 continue;
49 }
50 EventKind::StdTableOpen | EventKind::ArrayTableOpen => {
51 state.finish_table(errors);
52
53 let header = on_table(event, input, source, errors);
54
55 state.start_table(header, errors);
56 }
57 EventKind::SimpleKey => {
58 let (path, key) = on_key(event, input, source, errors);
59 let Some(key) = key else {
60 break;
61 };
62 let Some(next_event) = input.next_token() else {
63 break;
64 };
65 let keyval_event = if next_event.kind() == EventKind::Whitespace {
66 let Some(next_event) = input.next_token() else {
67 break;
68 };
69 next_event
70 } else {
71 next_event
72 };
73 if keyval_event.kind() != EventKind::KeyValSep {
74 break;
75 }
76
77 if input
78 .first()
79 .map(|e| e.kind() == EventKind::Whitespace)
80 .unwrap_or(false)
81 {
82 let _ = input.next_token();
83 }
84 let value = value(input, source, errors);
85
86 state.capture_key_value(path, key, value, errors);
87 }
88 EventKind::Whitespace | EventKind::Comment | EventKind::Newline => {
89 state.capture_trailing(event);
90 }
91 }
92 }
93
94 state.finish_table(errors);
95
96 let span = Default::default();
97 Spanned::new(span, state.root)
98}
99
100fn on_table<'i>(
110 open_event: &toml_parser::parser::Event,
111 input: &mut Input<'_>,
112 source: toml_parser::Source<'i>,
113 errors: &mut dyn ErrorSink,
114) -> TableHeader<'i> {
115 #[cfg(feature = "debug")]
116 let _scope = TraceScope::new("document::on_table");
117 let is_array = open_event.kind() == EventKind::ArrayTableOpen;
118 let mut current_path = None;
119 let mut current_key = None;
120 let mut current_span = open_event.span();
121 let mut current_prefix = None;
122 let mut current_suffix = None;
123
124 while let Some(event) = input.next_token() {
125 match event.kind() {
126 EventKind::InlineTableOpen
127 | EventKind::InlineTableClose
128 | EventKind::ArrayOpen
129 | EventKind::ArrayClose
130 | EventKind::Scalar
131 | EventKind::ValueSep
132 | EventKind::Error
133 | EventKind::KeySep
134 | EventKind::KeyValSep
135 | EventKind::StdTableOpen
136 | EventKind::ArrayTableOpen
137 | EventKind::Comment
138 | EventKind::Newline => {
139 #[cfg(feature = "debug")]
140 trace(
141 &format!("unexpected {event:?}"),
142 anstyle::AnsiColor::Red.on_default(),
143 );
144 continue;
145 }
146 EventKind::ArrayTableClose | EventKind::StdTableClose => {
147 current_span = current_span.append(event.span());
148 break;
149 }
150 EventKind::SimpleKey => {
151 current_prefix.get_or_insert_with(|| event.span().before());
152 let (path, key) = on_key(event, input, source, errors);
153 current_path = Some(path);
154 current_key = key;
155 current_suffix.get_or_insert_with(|| event.span().after());
156 }
157 EventKind::Whitespace => {
158 if current_key.is_some() {
159 current_suffix = Some(event.span());
160 } else {
161 current_prefix = Some(event.span());
162 }
163 }
164 }
165 }
166
167 TableHeader {
168 path: current_path.unwrap_or_default(),
169 key: current_key,
170 span: current_span,
171 is_array,
172 }
173}
174
175struct TableHeader<'i> {
176 path: Vec<Spanned<DeString<'i>>>,
177 key: Option<Spanned<DeString<'i>>>,
178 span: toml_parser::Span,
179 is_array: bool,
180}
181
182#[derive(Default)]
183struct State<'i> {
184 root: DeTable<'i>,
185 current_table: DeTable<'i>,
186 current_header: Option<TableHeader<'i>>,
187 current_position: usize,
188}
189
190impl<'i> State<'i> {
191 fn capture_trailing(&mut self, _event: &toml_parser::parser::Event) {}
192
193 fn capture_key_value(
194 &mut self,
195 path: Vec<Spanned<DeString<'i>>>,
196 key: Spanned<DeString<'i>>,
197 value: Spanned<DeValue<'i>>,
198 errors: &mut dyn ErrorSink,
199 ) {
200 #[cfg(feature = "debug")]
201 let _scope = TraceScope::new("document::capture_key_value");
202 #[cfg(feature = "debug")]
203 trace(
204 &format!(
205 "path={:?}",
206 path.iter().map(|k| k.get_ref()).collect::<Vec<_>>()
207 ),
208 anstyle::AnsiColor::Blue.on_default(),
209 );
210 #[cfg(feature = "debug")]
211 trace(
212 &format!("key={key}",),
213 anstyle::AnsiColor::Blue.on_default(),
214 );
215 #[cfg(feature = "debug")]
216 trace(
217 &format!("value={value:?}",),
218 anstyle::AnsiColor::Blue.on_default(),
219 );
220
221 let dotted = true;
222 let Some(parent_table) = descend_path(&mut self.current_table, &path, dotted, errors)
223 else {
224 return;
225 };
226 let mixed_table_types = parent_table.is_dotted() == path.is_empty();
228 if mixed_table_types {
229 let key_span = get_key_span(&key);
230 errors.report_error(ParseError::new("duplicate key").with_unexpected(key_span));
231 return;
232 }
233 let key_span = get_key_span(&key);
234 match parent_table.entry(key) {
235 Entry::Vacant(o) => {
236 o.insert(value);
237 }
238 Entry::Occupied(existing) => {
239 let old_span = get_key_span(existing.key());
241 errors.report_error(
242 ParseError::new("duplicate key")
243 .with_unexpected(key_span)
244 .with_context(old_span),
245 );
246 }
247 }
248 }
249
250 fn finish_table(&mut self, errors: &mut dyn ErrorSink) {
251 #[cfg(feature = "debug")]
252 let _scope = TraceScope::new("document::finish_table");
253 let prev_table = core::mem::take(&mut self.current_table);
254 if let Some(header) = self.current_header.take() {
255 let Some(key) = &header.key else {
256 return;
257 };
258 let header_span = header.span.start()..header.span.end();
259 let prev_table = Spanned::new(header_span.clone(), DeValue::Table(prev_table));
260
261 let parent_key = &header.path;
262 let dotted = false;
263 let Some(parent_table) = descend_path(&mut self.root, parent_key, dotted, errors)
264 else {
265 return;
266 };
267 #[cfg(feature = "debug")]
268 trace(
269 &format!("key={key}",),
270 anstyle::AnsiColor::Blue.on_default(),
271 );
272 if header.is_array {
273 let entry = parent_table.entry(key.clone()).or_insert_with(|| {
274 let mut array = DeArray::new();
275 array.set_array_of_tables(true);
276 Spanned::new(header_span, DeValue::Array(array))
277 });
278 let Some(array) = entry
279 .as_mut()
280 .as_array_mut()
281 .filter(|a| a.is_array_of_tables())
282 else {
283 let key_span = get_key_span(key);
284 let old_span = entry.span();
285 let old_span = toml_parser::Span::new_unchecked(old_span.start, old_span.end);
286 errors.report_error(
287 ParseError::new("duplicate key")
288 .with_unexpected(key_span)
289 .with_context(old_span),
290 );
291 return;
292 };
293 array.push(prev_table);
294 } else {
295 let existing = parent_table.insert(key.clone(), prev_table);
296 debug_assert!(existing.is_none());
297 }
298 } else {
299 self.root = prev_table;
300 }
301 }
302
303 fn start_table(&mut self, header: TableHeader<'i>, errors: &mut dyn ErrorSink) {
304 if !header.is_array {
305 let root = &mut self.root;
308 if let (Some(parent_table), Some(key)) =
309 (descend_path(root, &header.path, false, errors), &header.key)
310 {
311 if let Some((old_key, old_value)) = parent_table.remove_entry(key) {
312 match old_value.into_inner() {
313 DeValue::Table(t) if t.is_implicit() && !t.is_dotted() => {
314 self.current_table = t;
315 }
316 old_value => {
318 let old_span = get_key_span(&old_key);
319 let key_span = get_key_span(key);
320 errors.report_error(
321 ParseError::new("duplicate key")
322 .with_unexpected(key_span)
323 .with_context(old_span),
324 );
325
326 if let DeValue::Table(t) = old_value {
327 self.current_table = t;
328 }
329 }
330 }
331 }
332 }
333 }
334
335 self.current_position += 1;
336 self.current_table.set_implicit(false);
337 self.current_table.set_dotted(false);
338 self.current_header = Some(header);
339 }
340}
341
342fn descend_path<'t, 'i>(
343 mut table: &'t mut DeTable<'i>,
344 path: &[Spanned<DeString<'i>>],
345 dotted: bool,
346 errors: &mut dyn ErrorSink,
347) -> Option<&'t mut DeTable<'i>> {
348 #[cfg(feature = "debug")]
349 let _scope = TraceScope::new("document::descend_path");
350 #[cfg(feature = "debug")]
351 trace(
352 &format!(
353 "path={:?}",
354 path.iter().map(|k| k.get_ref()).collect::<Vec<_>>()
355 ),
356 anstyle::AnsiColor::Blue.on_default(),
357 );
358 for key in path.iter() {
359 table = match table.entry(key.clone()) {
360 Entry::Vacant(entry) => {
361 let mut new_table = DeTable::new();
362 new_table.set_implicit(true);
363 new_table.set_dotted(dotted);
364
365 let value = DeValue::Table(new_table);
366 let value = Spanned::new(key.span(), value);
367 let value = entry.insert(value);
368 value.as_mut().as_table_mut().unwrap()
369 }
370 Entry::Occupied(entry) => {
371 let spanned = entry.into_mut();
372 let old_span = spanned.span();
373 match spanned.as_mut() {
374 DeValue::Array(ref mut array) => {
375 if !array.is_array_of_tables() {
376 let old_span =
377 toml_parser::Span::new_unchecked(old_span.start, old_span.end);
378 let key_span = get_key_span(key);
379 errors.report_error(
380 ParseError::new(
381 "cannot extend value of type array with a dotted key",
382 )
383 .with_unexpected(key_span)
384 .with_context(old_span),
385 );
386 return None;
387 }
388
389 debug_assert!(!array.is_empty());
390
391 let index = array.len() - 1;
392 let last_child = array.get_mut(index).unwrap();
393
394 match last_child.as_mut() {
395 DeValue::Table(table) => table,
396 existing => {
397 let old_span =
398 toml_parser::Span::new_unchecked(old_span.start, old_span.end);
399 let key_span = get_key_span(key);
400 errors.report_error(
401 ParseError::new(format!(
402 "cannot extend value of type {} with a dotted key",
403 existing.type_str()
404 ))
405 .with_unexpected(key_span)
406 .with_context(old_span),
407 );
408 return None;
409 }
410 }
411 }
412 DeValue::Table(ref mut sweet_child_of_mine) => {
413 if sweet_child_of_mine.is_inline() {
414 let key_span = get_key_span(key);
415 errors.report_error(
416 ParseError::new(
417 "cannot extend value of type inline table with a dotted key",
418 )
419 .with_unexpected(key_span),
420 );
421 return None;
422 }
423 if dotted && !sweet_child_of_mine.is_implicit() {
427 let key_span = get_key_span(key);
428 errors.report_error(
429 ParseError::new("duplicate key").with_unexpected(key_span),
430 );
431 return None;
432 }
433 sweet_child_of_mine
434 }
435 existing => {
436 let old_span =
437 toml_parser::Span::new_unchecked(old_span.start, old_span.end);
438 let key_span = get_key_span(key);
439 errors.report_error(
440 ParseError::new(format!(
441 "cannot extend value of type {} with a dotted key",
442 existing.type_str()
443 ))
444 .with_unexpected(key_span)
445 .with_context(old_span),
446 );
447 return None;
448 }
449 }
450 }
451 };
452 }
453 Some(table)
454}
455
456fn get_key_span(key: &Spanned<DeString<'_>>) -> toml_parser::Span {
457 let key_span = key.span();
458 toml_parser::Span::new_unchecked(key_span.start, key_span.end)
459}