parse/xml/
map.rs

1use roxmltree::{
2    Node,
3};
4use std::collections::btree_map::{
5    BTreeMap,
6    OccupiedEntry,
7};
8use std::ops::Range;
9
10use crate::{
11    Map,
12};
13
14use super::{
15    duplicate_element,
16    Id,
17    missing_attribute,
18    Once,
19    ParseError,
20};
21
22pub struct ParsingMap<Name, Value, Index> {
23    index: Index,
24    map: BTreeMap<Name, Parsing<Value, Index>>,
25}
26
27pub struct Parsing<Value, Index> {
28    index: Index,
29    name_range: Range<usize>,
30    value_range: Range<usize>,
31    value: Option<Value>,
32}
33
34pub struct ParsingEntry<'a, Name, Value, Index> {
35    entry: OccupiedEntry<'a, Name, Parsing<Value, Index>>,
36}
37
38pub struct ParsedMap<Name, Value, Index> {
39    names: BTreeMap<Name, Index>,
40    vec: Vec<ParsedEntry<Name, Value, Index>>,
41}
42
43#[derive(Clone)]
44pub struct ParsedEntry<Name, Value, Index> {
45    pub index: Index,
46    pub name: Name,
47    pub range: Range<usize>,
48    pub value: Value,
49}
50
51impl<Name: Ord, Value, Index: Id> ParsingMap<Name, Value, Index> {
52    pub fn new() -> Self {
53        ParsingMap {
54            map: BTreeMap::new(),
55            index: Index::zero(),
56        }
57    }
58
59    pub fn builtin(
60        &mut self,
61        name: Name,
62        range: Range<usize>,
63        value: Value,
64    ) {
65        self.map.insert(name, Parsing {
66            index: self.index.clone(),
67            name_range: range.clone(),
68            value_range: range,
69            value: Some(value),
70        });
71
72        self.index.succ();
73    }
74
75    /// Insert *named* item into collection.
76    ///
77    /// Raise an error if the element is missing a name.
78    ///
79    /// Raise an error if there is a duplicate.
80    ///
81    /// Return a mutable reference to the inserted item's value.
82    /// The value is an `Option<T>` with a default of `None`.
83    pub fn insert<'input, 'a, E>(
84        &'a mut self,
85        name: Once<Name>,
86        element: &Node<'input, 'input>,
87        errors: &mut Vec<E>,
88    ) -> Option<ParsingEntry<'a, Name, Value, Index>>
89    where
90        E: From<ParseError>,
91    {
92        match name {
93            Once::Missing { name } => {
94                missing_attribute(name, element, errors);
95
96                None
97            }
98
99            Once::Failure { .. } =>
100                None,
101
102            Once::Success { value: name, value_range: name_range, .. } => {
103                use std::collections::btree_map::Entry::*;
104
105                match self.map.entry(name) {
106                    Vacant(entry) => {
107                        let entry = entry.insert_entry(Parsing {
108                            index: self.index.clone(),
109                            name_range,
110                            value_range: element.range(),
111                            value: None,
112                        });
113
114                        self.index.succ();
115
116                        Some(ParsingEntry {
117                            entry,
118                        })
119                    }
120
121                    Occupied(entry) => {
122                        let existing = entry.get();
123
124                        duplicate_element(
125                            element.tag_name().name(),
126                            name_range,
127                            existing.name_range.clone(),
128                            errors,
129                        );
130
131                        None
132                    }
133                }
134            }
135        }
136    }
137
138    /// Insert derived item into collection.
139    ///
140    /// Raise an error if there is a duplicate.
141    ///
142    /// Return a mutable reference to the inserted item's value.
143    /// The value is an `Option<T>` with a default of `None`.
144    pub fn insert_derived<'input, 'a, E>(
145        &'a mut self,
146        element_name: &str,
147        name: Name,
148        name_range: Range<usize>,
149        errors: &mut Vec<E>,
150    ) -> Option<ParsingEntry<'a, Name, Value, Index>>
151    where
152        E: From<ParseError>,
153    {
154        use std::collections::btree_map::Entry::*;
155
156        match self.map.entry(name) {
157            Vacant(entry) => {
158                let entry = entry.insert_entry(Parsing {
159                    index: self.index.clone(),
160                    name_range: name_range.clone(),
161                    value_range: name_range,
162                    value: None,
163                });
164
165                Some(ParsingEntry {
166                    entry,
167                })
168            }
169
170            Occupied(entry) => {
171                let existing = entry.get();
172
173                duplicate_element(element_name, name_range, existing.name_range.clone(), errors);
174
175                None
176            }
177        }
178    }
179
180    /// Collect all parsed items in collection
181    /// sorted by name.
182    ///
183    /// Return `None` if any where invalid.
184    pub fn collect(self) -> Option<ParsedMap<Name, Value, Index>>
185    where
186        Name: Clone,
187    {
188        let mut names = BTreeMap::new();
189        let mut vec = Vec::new();
190        let mut index = Index::zero();
191
192        for (name, parsing) in self.map {
193            if let Some(value) = parsing.value {
194                names.insert(name.clone(), index.clone());
195                vec.push(ParsedEntry {
196                    index: index.clone(),
197                    name: name,
198                    range: parsing.value_range,
199                    value,
200                });
201                index.succ();
202            } else {
203                return None;
204            }
205        }
206
207        Some(ParsedMap {
208            names,
209            vec,
210        })
211    }
212
213    /// Collect all parsed items in collection
214    /// sorted by occurance (index).
215    ///
216    /// Return `None` if any where invalid.
217    pub fn collect_by_index(mut self)
218        -> Option<ParsedMap<Name, Value, Index>>
219    where
220        Index: Ord,
221        Name: Clone,
222    {
223        let mut indexes = BTreeMap::new();
224        let mut names = BTreeMap::new();
225        let mut vec = Vec::new();
226
227        for (name, parsing) in &self.map {
228            if let Some(_) = parsing.value {
229                indexes.insert(parsing.index.clone(), name.clone());
230            } else {
231                return None;
232            }
233        }
234
235        for (index, name) in indexes {
236            let (parsed_name, parsing) = self.map.remove_entry(&name).unwrap();
237            names.insert(name, index);
238            vec.push(ParsedEntry {
239                index: parsing.index,
240                name: parsed_name,
241                range: parsing.value_range,
242                value: parsing.value.unwrap(),
243            });
244        }
245
246        Some(ParsedMap {
247            names,
248            vec,
249        })
250    }
251
252    /// Collect all parsed items in collection
253    /// sorted by function.
254    ///
255    /// Return `None` if any where invalid.
256    pub fn collect_by_key<Key, F>(mut self, key: F)
257        -> Option<ParsedMap<Name, Value, Index>>
258    where
259        Index: Ord,
260        Name: Clone,
261        Key: Ord,
262        F: Fn(&Value) -> Key,
263    {
264        let mut keys = BTreeMap::new();
265        let mut names = BTreeMap::new();
266        let mut vec = Vec::new();
267
268        for (name, parsing) in &self.map {
269            if let Some(value) = &parsing.value {
270                keys.insert(key(value), name.clone());
271            } else {
272                return None;
273            }
274        }
275
276        for (_key, name) in keys {
277            let (parsed_name, parsing) = self.map.remove_entry(&name).unwrap();
278            names.insert(name, parsing.index.clone());
279            vec.push(ParsedEntry {
280                index: parsing.index,
281                name: parsed_name,
282                range: parsing.value_range,
283                value: parsing.value.unwrap(),
284            });
285        }
286
287        Some(ParsedMap {
288            names,
289            vec,
290        })
291    }
292
293    /// Collect all parsed items in collection
294    /// to a b-tree
295    ///
296    /// Return `None` if any where invalid.
297    pub fn collect_to_btree(self) -> Option<BTreeMap<Name, Value>>
298    where
299        Name: Clone,
300    {
301        let mut map = BTreeMap::new();
302
303        for (name, parsing) in self.map {
304            if let Some(value) = parsing.value {
305                map.insert(name.clone(), value);
306            } else {
307                return None;
308            }
309        }
310
311        Some(map)
312    }
313}
314
315impl<'a, Name: Ord, Value, Index: Clone> ParsingEntry<'a, Name, Value, Index> {
316    pub fn index(&self) -> Index {
317        self.entry.get().index.clone()
318    }
319
320    pub fn name(&self) -> &Name {
321        self.entry.key()
322    }
323
324    pub fn name_range(&self) -> Range<usize> {
325        self.entry.get().name_range.clone()
326    }
327
328    pub fn value(mut self, value: Value) {
329        self.entry.get_mut().value = Some(value);
330    }
331}
332
333impl<Name: Ord, Value, Index: Id> ParsedMap<Name, Value, Index> {
334    pub fn get<Find>(&self, name: &Find) -> Option<(Index, &Value)>
335    where
336        Name: std::borrow::Borrow<Find> + Ord,
337        Find: Ord + ?Sized,
338    {
339        if let Some(id) = self.names.get(name) {
340            let parsed = self.vec.get(id.index())
341                .expect("Exist by construction");
342            Some((id.clone(), &parsed.value))
343        } else {
344            None
345        }
346    }
347
348    pub fn get_id<Find>(&self, name: &Find) -> Option<Index>
349    where
350        Name: std::borrow::Borrow<Find> + Ord,
351        Find: Ord + ?Sized,
352    {
353        self.names.get(name).cloned()
354    }
355
356    pub fn get_parsed<Find>(&self, name: &Find) -> Option<(Index, &ParsedEntry<Name, Value, Index>)>
357    where
358        Name: std::borrow::Borrow<Find> + Ord,
359        Find: Ord + ?Sized,
360    {
361        if let Some(id) = self.names.get(name) {
362            let parsed = self.vec.get(id.index())
363                .expect("Exist by construction");
364            Some((id.clone(), parsed))
365        } else {
366            None
367        }
368    }
369
370    pub fn iter(&self) -> std::slice::Iter<'_, ParsedEntry<Name, Value, Index>> {
371        self.vec.iter()
372    }
373
374    pub fn map<V, With, E>(
375        &self,
376        with: With,
377        errors: &mut Vec<E>,
378    ) -> Option<Map<Name, V, Index>>
379    where
380        Name: Clone,
381        With: Fn(&ParsedEntry<Name, Value, Index>, &mut Vec<E>) -> Option<V>,
382    {
383        let mut vec = Vec::new();
384
385        for parsed in &self.vec {
386            if let Some(value) = with(parsed, errors) {
387                vec.push(value);
388            } else {
389                return None;
390            }
391        }
392
393        Some(Map {
394            names: self.names.clone(),
395            vec,
396        })
397    }
398
399    pub fn map_cx<V, With, C, E>(
400        &self,
401        with: With,
402        cx: &C,
403        errors: &mut Vec<E>,
404    ) -> Option<Map<Name, V, Index>>
405    where
406        Name: Clone,
407        With: Fn(&ParsedEntry<Name, Value, Index>, &C, &mut Vec<E>) -> Option<V>,
408    {
409        let mut vec = Vec::new();
410
411        for parsed in &self.vec {
412            if let Some(value) = with(parsed, cx, errors) {
413                vec.push(value);
414            } else {
415                return None;
416            }
417        }
418
419        Some(Map {
420            names: self.names.clone(),
421            vec,
422        })
423    }
424
425    pub fn map_cx2<V, With, C, D, E>(
426        &self,
427        with: With,
428        cx: &C,
429        dx: &D,
430        errors: &mut Vec<E>,
431    ) -> Option<Map<Name, V, Index>>
432    where
433        Name: Clone,
434        With: Fn(&ParsedEntry<Name, Value, Index>, &C, &D, &mut Vec<E>) -> Option<V>,
435    {
436        let mut vec = Vec::new();
437
438        for parsed in &self.vec {
439            if let Some(value) = with(parsed, cx, dx, errors) {
440                vec.push(value);
441            } else {
442                return None;
443            }
444        }
445
446        Some(Map {
447            names: self.names.clone(),
448            vec,
449        })
450    }
451
452    pub fn map_cx_mut<V, With, C, D, E>(
453        &self,
454        with: With,
455        cx: &C,
456        dx: &mut D,
457        errors: &mut Vec<E>,
458    ) -> Option<Map<Name, V, Index>>
459    where
460        Name: Clone,
461        With: Fn(&ParsedEntry<Name, Value, Index>, &C, &mut D, &mut Vec<E>) -> Option<V>,
462    {
463        let mut vec = Vec::new();
464
465        for parsed in &self.vec {
466            if let Some(value) = with(parsed, cx, dx, errors) {
467                vec.push(value);
468            } else {
469                return None;
470            }
471        }
472
473        Some(Map {
474            names: self.names.clone(),
475            vec,
476        })
477    }
478
479    pub fn map_mut<V, With, C, E>(
480        &self,
481        with: With,
482        cx: &mut C,
483        errors: &mut Vec<E>,
484    ) -> Option<Map<Name, V, Index>>
485    where
486        Name: Clone,
487        With: Fn(&ParsedEntry<Name, Value, Index>, &mut C, &mut Vec<E>) -> Option<V>,
488    {
489        let mut vec = Vec::new();
490
491        for parsed in &self.vec {
492            if let Some(value) = with(parsed, cx, errors) {
493                vec.push(value);
494            } else {
495                return None;
496            }
497        }
498
499        Some(Map {
500            names: self.names.clone(),
501            vec,
502        })
503    }
504}