1 use crate::key::Key;
2 use crate::parser::error::CustomError;
3 use crate::repr::Decor;
4 use crate::table::TableKeyValue;
5 use crate::{ArrayOfTables, Document, InternalString, Item, RawString, Table};
6 
7 pub(crate) struct ParseState {
8     document: Document,
9     trailing: Option<std::ops::Range<usize>>,
10     current_table_position: usize,
11     current_table: Table,
12     current_is_array: bool,
13     current_table_path: Vec<Key>,
14 }
15 
16 impl ParseState {
into_document(mut self) -> Result<Document, CustomError>17     pub(crate) fn into_document(mut self) -> Result<Document, CustomError> {
18         self.finalize_table()?;
19         let trailing = self.trailing.map(RawString::with_span);
20         self.document.trailing = trailing.unwrap_or_default();
21         Ok(self.document)
22     }
23 
on_ws(&mut self, span: std::ops::Range<usize>)24     pub(crate) fn on_ws(&mut self, span: std::ops::Range<usize>) {
25         if let Some(old) = self.trailing.take() {
26             self.trailing = Some(old.start..span.end);
27         } else {
28             self.trailing = Some(span);
29         }
30     }
31 
on_comment(&mut self, span: std::ops::Range<usize>)32     pub(crate) fn on_comment(&mut self, span: std::ops::Range<usize>) {
33         if let Some(old) = self.trailing.take() {
34             self.trailing = Some(old.start..span.end);
35         } else {
36             self.trailing = Some(span);
37         }
38     }
39 
on_keyval( &mut self, path: Vec<Key>, mut kv: TableKeyValue, ) -> Result<(), CustomError>40     pub(crate) fn on_keyval(
41         &mut self,
42         path: Vec<Key>,
43         mut kv: TableKeyValue,
44     ) -> Result<(), CustomError> {
45         {
46             let mut prefix = self.trailing.take();
47             let prefix = match (
48                 prefix.take(),
49                 kv.key.leaf_decor.prefix().and_then(|d| d.span()),
50             ) {
51                 (Some(p), Some(k)) => Some(p.start..k.end),
52                 (Some(p), None) | (None, Some(p)) => Some(p),
53                 (None, None) => None,
54             };
55             kv.key
56                 .leaf_decor
57                 .set_prefix(prefix.map(RawString::with_span).unwrap_or_default());
58         }
59 
60         if let (Some(existing), Some(value)) = (self.current_table.span(), kv.value.span()) {
61             self.current_table.span = Some((existing.start)..(value.end));
62         }
63         let table = &mut self.current_table;
64         let table = Self::descend_path(table, &path, true)?;
65 
66         // "Likewise, using dotted keys to redefine tables already defined in [table] form is not allowed"
67         let mixed_table_types = table.is_dotted() == path.is_empty();
68         if mixed_table_types {
69             return Err(CustomError::DuplicateKey {
70                 key: kv.key.get().into(),
71                 table: None,
72             });
73         }
74 
75         let key: InternalString = kv.key.get_internal().into();
76         match table.items.entry(key) {
77             indexmap::map::Entry::Vacant(o) => {
78                 o.insert(kv);
79             }
80             indexmap::map::Entry::Occupied(o) => {
81                 // "Since tables cannot be defined more than once, redefining such tables using a [table] header is not allowed"
82                 return Err(CustomError::DuplicateKey {
83                     key: o.key().as_str().into(),
84                     table: Some(self.current_table_path.clone()),
85                 });
86             }
87         }
88 
89         Ok(())
90     }
91 
start_array_table( &mut self, path: Vec<Key>, decor: Decor, span: std::ops::Range<usize>, ) -> Result<(), CustomError>92     pub(crate) fn start_array_table(
93         &mut self,
94         path: Vec<Key>,
95         decor: Decor,
96         span: std::ops::Range<usize>,
97     ) -> Result<(), CustomError> {
98         debug_assert!(!path.is_empty());
99         debug_assert!(self.current_table.is_empty());
100         debug_assert!(self.current_table_path.is_empty());
101 
102         // Look up the table on start to ensure the duplicate_key error points to the right line
103         let root = self.document.as_table_mut();
104         let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?;
105         let key = &path[path.len() - 1];
106         let entry = parent_table
107             .entry_format(key)
108             .or_insert(Item::ArrayOfTables(ArrayOfTables::new()));
109         entry
110             .as_array_of_tables()
111             .ok_or_else(|| CustomError::duplicate_key(&path, path.len() - 1))?;
112 
113         self.current_table_position += 1;
114         self.current_table.decor = decor;
115         self.current_table.set_implicit(false);
116         self.current_table.set_dotted(false);
117         self.current_table.set_position(self.current_table_position);
118         self.current_table.span = Some(span);
119         self.current_is_array = true;
120         self.current_table_path = path;
121 
122         Ok(())
123     }
124 
start_table( &mut self, path: Vec<Key>, decor: Decor, span: std::ops::Range<usize>, ) -> Result<(), CustomError>125     pub(crate) fn start_table(
126         &mut self,
127         path: Vec<Key>,
128         decor: Decor,
129         span: std::ops::Range<usize>,
130     ) -> Result<(), CustomError> {
131         debug_assert!(!path.is_empty());
132         debug_assert!(self.current_table.is_empty());
133         debug_assert!(self.current_table_path.is_empty());
134 
135         // 1. Look up the table on start to ensure the duplicate_key error points to the right line
136         // 2. Ensure any child tables from an implicit table are preserved
137         let root = self.document.as_table_mut();
138         let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?;
139         let key = &path[path.len() - 1];
140         if let Some(entry) = parent_table.remove(key.get()) {
141             match entry {
142                 Item::Table(t) if t.implicit && !t.is_dotted() => {
143                     self.current_table = t;
144                 }
145                 // Since tables cannot be defined more than once, redefining such tables using a [table] header is not allowed. Likewise, using dotted keys to redefine tables already defined in [table] form is not allowed.
146                 _ => return Err(CustomError::duplicate_key(&path, path.len() - 1)),
147             }
148         }
149 
150         self.current_table_position += 1;
151         self.current_table.decor = decor;
152         self.current_table.set_implicit(false);
153         self.current_table.set_dotted(false);
154         self.current_table.set_position(self.current_table_position);
155         self.current_table.span = Some(span);
156         self.current_is_array = false;
157         self.current_table_path = path;
158 
159         Ok(())
160     }
161 
finalize_table(&mut self) -> Result<(), CustomError>162     pub(crate) fn finalize_table(&mut self) -> Result<(), CustomError> {
163         let mut table = std::mem::take(&mut self.current_table);
164         let path = std::mem::take(&mut self.current_table_path);
165 
166         let root = self.document.as_table_mut();
167         if path.is_empty() {
168             assert!(root.is_empty());
169             std::mem::swap(&mut table, root);
170         } else if self.current_is_array {
171             let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?;
172             let key = &path[path.len() - 1];
173 
174             let entry = parent_table
175                 .entry_format(key)
176                 .or_insert(Item::ArrayOfTables(ArrayOfTables::new()));
177             let array = entry
178                 .as_array_of_tables_mut()
179                 .ok_or_else(|| CustomError::duplicate_key(&path, path.len() - 1))?;
180             array.push(table);
181             let span = if let (Some(first), Some(last)) = (
182                 array.values.first().and_then(|t| t.span()),
183                 array.values.last().and_then(|t| t.span()),
184             ) {
185                 Some((first.start)..(last.end))
186             } else {
187                 None
188             };
189             array.span = span;
190         } else {
191             let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?;
192             let key = &path[path.len() - 1];
193 
194             let entry = parent_table.entry_format(key);
195             match entry {
196                 crate::Entry::Occupied(entry) => {
197                     match entry.into_mut() {
198                         // if [a.b.c] header preceded [a.b]
199                         Item::Table(ref mut t) if t.implicit => {
200                             std::mem::swap(t, &mut table);
201                         }
202                         _ => return Err(CustomError::duplicate_key(&path, path.len() - 1)),
203                     }
204                 }
205                 crate::Entry::Vacant(entry) => {
206                     let item = Item::Table(table);
207                     entry.insert(item);
208                 }
209             }
210         }
211 
212         Ok(())
213     }
214 
descend_path<'t>( mut table: &'t mut Table, path: &[Key], dotted: bool, ) -> Result<&'t mut Table, CustomError>215     pub(crate) fn descend_path<'t>(
216         mut table: &'t mut Table,
217         path: &[Key],
218         dotted: bool,
219     ) -> Result<&'t mut Table, CustomError> {
220         for (i, key) in path.iter().enumerate() {
221             let entry = table.entry_format(key).or_insert_with(|| {
222                 let mut new_table = Table::new();
223                 new_table.set_implicit(true);
224                 new_table.set_dotted(dotted);
225 
226                 Item::Table(new_table)
227             });
228             match *entry {
229                 Item::Value(ref v) => {
230                     return Err(CustomError::extend_wrong_type(path, i, v.type_name()));
231                 }
232                 Item::ArrayOfTables(ref mut array) => {
233                     debug_assert!(!array.is_empty());
234 
235                     let index = array.len() - 1;
236                     let last_child = array.get_mut(index).unwrap();
237 
238                     table = last_child;
239                 }
240                 Item::Table(ref mut sweet_child_of_mine) => {
241                     // Since tables cannot be defined more than once, redefining such tables using a
242                     // [table] header is not allowed. Likewise, using dotted keys to redefine tables
243                     // already defined in [table] form is not allowed.
244                     if dotted && !sweet_child_of_mine.is_implicit() {
245                         return Err(CustomError::DuplicateKey {
246                             key: key.get().into(),
247                             table: None,
248                         });
249                     }
250                     table = sweet_child_of_mine;
251                 }
252                 _ => unreachable!(),
253             }
254         }
255         Ok(table)
256     }
257 
on_std_header( &mut self, path: Vec<Key>, trailing: std::ops::Range<usize>, span: std::ops::Range<usize>, ) -> Result<(), CustomError>258     pub(crate) fn on_std_header(
259         &mut self,
260         path: Vec<Key>,
261         trailing: std::ops::Range<usize>,
262         span: std::ops::Range<usize>,
263     ) -> Result<(), CustomError> {
264         debug_assert!(!path.is_empty());
265 
266         self.finalize_table()?;
267         let leading = self
268             .trailing
269             .take()
270             .map(RawString::with_span)
271             .unwrap_or_default();
272         self.start_table(
273             path,
274             Decor::new(leading, RawString::with_span(trailing)),
275             span,
276         )?;
277 
278         Ok(())
279     }
280 
on_array_header( &mut self, path: Vec<Key>, trailing: std::ops::Range<usize>, span: std::ops::Range<usize>, ) -> Result<(), CustomError>281     pub(crate) fn on_array_header(
282         &mut self,
283         path: Vec<Key>,
284         trailing: std::ops::Range<usize>,
285         span: std::ops::Range<usize>,
286     ) -> Result<(), CustomError> {
287         debug_assert!(!path.is_empty());
288 
289         self.finalize_table()?;
290         let leading = self
291             .trailing
292             .take()
293             .map(RawString::with_span)
294             .unwrap_or_default();
295         self.start_array_table(
296             path,
297             Decor::new(leading, RawString::with_span(trailing)),
298             span,
299         )?;
300 
301         Ok(())
302     }
303 }
304 
305 impl Default for ParseState {
default() -> Self306     fn default() -> Self {
307         let mut root = Table::new();
308         root.span = Some(0..0);
309         Self {
310             document: Document::new(),
311             trailing: None,
312             current_table_position: 0,
313             current_table: root,
314             current_is_array: false,
315             current_table_path: Vec::new(),
316         }
317     }
318 }
319