toml_edit/parser/
inline_table.rs1use crate::key::Key;
2use crate::parser::array::on_array;
3use crate::parser::key::on_key;
4use crate::parser::prelude::*;
5use crate::parser::value::on_scalar;
6use crate::repr::Decor;
7use crate::{InlineTable, Item, RawString, Value};
8
9use indexmap::map::Entry;
10
11pub(crate) fn on_inline_table(
17 open_event: &toml_parser::parser::Event,
18 input: &mut Input<'_>,
19 source: toml_parser::Source<'_>,
20 errors: &mut dyn ErrorSink,
21) -> Value {
22 #[cfg(feature = "debug")]
23 let _scope = TraceScope::new("inline_table::on_inline_table");
24 let mut result = InlineTable::new();
25
26 let mut state = State::default();
27 while let Some(event) = input.next_token() {
28 match event.kind() {
29 EventKind::StdTableOpen
30 | EventKind::ArrayTableOpen
31 | EventKind::StdTableClose
32 | EventKind::ArrayClose
33 | EventKind::ArrayTableClose
34 | EventKind::KeySep => {
35 #[cfg(feature = "debug")]
36 trace(
37 &format!("unexpected {event:?}"),
38 anstyle::AnsiColor::Red.on_default(),
39 );
40 break;
41 }
42 EventKind::Error => {
43 #[cfg(feature = "debug")]
44 trace(
45 &format!("unexpected {event:?}"),
46 anstyle::AnsiColor::Red.on_default(),
47 );
48 continue;
49 }
50 EventKind::SimpleKey => {
51 let (path, key) = on_key(event, input, source, errors);
52 state.capture_key(event, path, key);
53 }
54 EventKind::KeyValSep => {
55 state.finish_key(event);
56 }
57 EventKind::InlineTableOpen => {
58 let value = on_inline_table(event, input, source, errors);
59 state.capture_value(event, value);
60 }
61 EventKind::ArrayOpen => {
62 let value = on_array(event, input, source, errors);
63 state.capture_value(event, value);
64 }
65 EventKind::Scalar => {
66 let value = on_scalar(event, source, errors);
67 state.capture_value(event, value);
68 }
69 EventKind::ValueSep => {
70 state.finish_value(event, &mut result, errors);
71 }
72 EventKind::Whitespace | EventKind::Comment | EventKind::Newline => {
73 state.whitespace(event);
74 }
75 EventKind::InlineTableClose => {
76 state.finish_value(event, &mut result, errors);
77 state.close(open_event, event, &mut result);
78 break;
79 }
80 }
81 }
82
83 Value::InlineTable(result)
84}
85
86#[derive(Default)]
87struct State {
88 current_prefix: Option<toml_parser::Span>,
89 current_key: Option<(Vec<Key>, Key)>,
90 seen_keyval_sep: bool,
91 current_value: Option<Value>,
92 current_suffix: Option<toml_parser::Span>,
93}
94
95impl State {
96 fn whitespace(&mut self, event: &toml_parser::parser::Event) {
97 let decor = if self.is_prefix() {
98 self.current_prefix.get_or_insert(event.span())
99 } else {
100 self.current_suffix.get_or_insert(event.span())
101 };
102 *decor = decor.append(event.span());
103 }
104
105 fn is_prefix(&self) -> bool {
106 if self.seen_keyval_sep {
107 self.current_value.is_none()
108 } else {
109 self.current_key.is_none()
110 }
111 }
112
113 fn capture_key(
114 &mut self,
115 event: &toml_parser::parser::Event,
116 path: Vec<Key>,
117 key: Option<Key>,
118 ) {
119 self.current_prefix
120 .get_or_insert_with(|| event.span().before());
121 if let Some(key) = key {
122 self.current_key = Some((path, key));
123 }
124 }
125
126 fn finish_key(&mut self, event: &toml_parser::parser::Event) {
127 self.seen_keyval_sep = true;
128 if let Some(last_key) = self.current_key.as_mut().map(|(_, k)| k) {
129 let prefix = self
130 .current_prefix
131 .take()
132 .expect("setting a key should set a prefix");
133 let suffix = self
134 .current_suffix
135 .take()
136 .unwrap_or_else(|| event.span().before());
137 let prefix = RawString::with_span(prefix.start()..prefix.end());
138 let suffix = RawString::with_span(suffix.start()..suffix.end());
139 let leaf_decor = Decor::new(prefix, suffix);
140 *last_key.leaf_decor_mut() = leaf_decor;
141 }
142 }
143
144 fn capture_value(&mut self, event: &toml_parser::parser::Event, value: Value) {
145 self.current_prefix
146 .get_or_insert_with(|| event.span().before());
147 self.current_value = Some(value);
148 }
149
150 fn finish_value(
151 &mut self,
152 event: &toml_parser::parser::Event,
153 result: &mut InlineTable,
154 errors: &mut dyn ErrorSink,
155 ) {
156 #[cfg(feature = "debug")]
157 let _scope = TraceScope::new("inline_table::finish_value");
158 self.seen_keyval_sep = false;
159 if let (Some((path, key)), Some(mut value)) =
160 (self.current_key.take(), self.current_value.take())
161 {
162 let prefix = self
163 .current_prefix
164 .take()
165 .expect("setting a value should set a prefix");
166 let suffix = self
167 .current_suffix
168 .take()
169 .unwrap_or_else(|| event.span().before());
170 let Some(table) = descend_path(result, &path, true, errors) else {
171 return;
172 };
173
174 let decor = value.decor_mut();
175 decor.set_prefix(RawString::with_span(prefix.start()..prefix.end()));
176 decor.set_suffix(RawString::with_span(suffix.start()..suffix.end()));
177
178 let mixed_table_types = table.is_dotted() == path.is_empty();
180 if mixed_table_types {
181 let key_span = get_key_span(&key).unwrap_or_else(|| event.span());
182 errors.report_error(ParseError::new("duplicate key").with_unexpected(key_span));
183 } else {
184 let key_span = get_key_span(&key).unwrap_or_else(|| event.span());
185 match table.items.entry(key) {
186 Entry::Vacant(o) => {
187 o.insert(Item::Value(value));
188 }
189 Entry::Occupied(o) => {
190 let old_span = get_key_span(o.key()).unwrap_or_else(|| event.span());
191 errors.report_error(
192 ParseError::new("duplicate key")
193 .with_unexpected(key_span)
194 .with_context(old_span),
195 );
196 }
197 }
198 }
199 }
200 }
201
202 fn close(
203 &mut self,
204 open_event: &toml_parser::parser::Event,
205 close_event: &toml_parser::parser::Event,
206 result: &mut InlineTable,
207 ) {
208 #[cfg(feature = "debug")]
209 let _scope = TraceScope::new("inline_table::close");
210 let span = open_event.span().append(close_event.span());
211 let preamble = self
212 .current_prefix
213 .take()
214 .map(|prefix| RawString::with_span(prefix.start()..prefix.end()));
215
216 result.span = Some(span.start()..span.end());
217 if let Some(preamble) = preamble {
218 result.set_preamble(preamble);
219 }
220 }
221}
222
223fn descend_path<'a>(
224 mut table: &'a mut InlineTable,
225 path: &'a [Key],
226 dotted: bool,
227 errors: &mut dyn ErrorSink,
228) -> Option<&'a mut InlineTable> {
229 #[cfg(feature = "debug")]
230 let _scope = TraceScope::new("inline_table::descend_path");
231 #[cfg(feature = "debug")]
232 trace(
233 &format!("key={:?}", path.iter().map(|k| k.get()).collect::<Vec<_>>()),
234 anstyle::AnsiColor::Blue.on_default(),
235 );
236 for key in path.iter() {
237 table = match table.entry_format(key) {
238 crate::InlineEntry::Vacant(entry) => {
239 let mut new_table = InlineTable::new();
240 new_table.span = key.span();
241 new_table.set_implicit(true);
242 new_table.set_dotted(dotted);
243 entry
244 .insert(Value::InlineTable(new_table))
245 .as_inline_table_mut()
246 .unwrap()
247 }
248 crate::InlineEntry::Occupied(entry) => {
249 match entry.into_mut() {
250 Value::InlineTable(ref mut sweet_child_of_mine) => {
251 if dotted && !sweet_child_of_mine.is_implicit() {
255 let key_span = get_key_span(key).expect("all keys have spans");
256 errors.report_error(
257 ParseError::new("duplicate key").with_unexpected(key_span),
258 );
259 return None;
260 }
261 sweet_child_of_mine
262 }
263 item => {
264 let key_span = get_key_span(key).expect("all keys have spans");
265 errors.report_error(
266 ParseError::new(format!(
267 "cannot extend value of type {} with a dotted key",
268 item.type_name()
269 ))
270 .with_unexpected(key_span),
271 );
272 return None;
273 }
274 }
275 }
276 };
277 }
278 Some(table)
279}
280
281fn get_key_span(key: &Key) -> Option<toml_parser::Span> {
282 key.as_repr()
283 .and_then(|r| r.span())
284 .map(|s| toml_parser::Span::new_unchecked(s.start, s.end))
285}