toml/de/parser/
key.rs

1use serde_spanned::Spanned;
2
3use crate::alloc_prelude::*;
4use crate::de::parser::prelude::*;
5use crate::de::DeString;
6
7/// ```bnf
8/// key = simple-key / dotted-key
9/// dotted-key = simple-key 1*( dot-sep simple-key )
10/// ```
11pub(crate) fn on_key<'i>(
12    key_event: &toml_parser::parser::Event,
13    input: &mut Input<'_>,
14    source: toml_parser::Source<'i>,
15    errors: &mut dyn ErrorSink,
16) -> (Vec<Spanned<DeString<'i>>>, Option<Spanned<DeString<'i>>>) {
17    #[cfg(feature = "debug")]
18    let _scope = TraceScope::new("key::on_key");
19    let mut result_path = Vec::new();
20    let mut result_key = None;
21
22    let mut state = State::new(key_event);
23    if more_key(input) {
24        while let Some(event) = input.next_token() {
25            match event.kind() {
26                EventKind::StdTableOpen
27                | EventKind::ArrayTableOpen
28                | EventKind::InlineTableOpen
29                | EventKind::InlineTableClose
30                | EventKind::ArrayOpen
31                | EventKind::ArrayClose
32                | EventKind::Scalar
33                | EventKind::ValueSep
34                | EventKind::Comment
35                | EventKind::Newline
36                | EventKind::KeyValSep
37                | EventKind::StdTableClose
38                | EventKind::ArrayTableClose
39                | EventKind::Error => {
40                    #[cfg(feature = "debug")]
41                    trace(
42                        &format!("unexpected {event:?}"),
43                        anstyle::AnsiColor::Red.on_default(),
44                    );
45                    continue;
46                }
47                EventKind::SimpleKey => {
48                    state.current_key = Some(*event);
49
50                    if !more_key(input) {
51                        break;
52                    }
53                }
54                EventKind::Whitespace => {
55                    state.whitespace(event);
56                }
57                EventKind::KeySep => {
58                    state.close_key(&mut result_path, &mut result_key, source, errors);
59                }
60            }
61        }
62    }
63
64    state.close_key(&mut result_path, &mut result_key, source, errors);
65
66    #[cfg(not(feature = "unbounded"))]
67    if super::LIMIT <= result_path.len() as u32 {
68        errors.report_error(ParseError::new("recursion limit"));
69        return (Vec::new(), None);
70    }
71
72    (result_path, result_key)
73}
74
75fn more_key(input: &Input<'_>) -> bool {
76    let first = input.get(0).map(|e| e.kind());
77    let second = input.get(1).map(|e| e.kind());
78    if first == Some(EventKind::KeySep) {
79        true
80    } else if first == Some(EventKind::Whitespace) && second == Some(EventKind::KeySep) {
81        true
82    } else {
83        false
84    }
85}
86
87struct State {
88    current_key: Option<toml_parser::parser::Event>,
89}
90
91impl State {
92    fn new(key_event: &toml_parser::parser::Event) -> Self {
93        Self {
94            current_key: Some(*key_event),
95        }
96    }
97
98    fn whitespace(&mut self, _event: &toml_parser::parser::Event) {}
99
100    fn close_key<'i>(
101        &mut self,
102        result_path: &mut Vec<Spanned<DeString<'i>>>,
103        result_key: &mut Option<Spanned<DeString<'i>>>,
104        source: toml_parser::Source<'i>,
105        errors: &mut dyn ErrorSink,
106    ) {
107        let Some(key) = self.current_key.take() else {
108            return;
109        };
110
111        let key_span = key.span();
112        let key_span = key_span.start()..key_span.end();
113
114        let raw = source.get(key).unwrap();
115        let mut decoded = alloc::borrow::Cow::Borrowed("");
116        raw.decode_key(&mut decoded, errors);
117
118        let key = Spanned::new(key_span, decoded);
119        if let Some(last_key) = result_key.replace(key) {
120            result_path.push(last_key);
121        }
122    }
123}