kefta_core/structs/
map.rs

1use std::collections::BTreeMap;
2use crate::error::{KeftaError, KeftaResult};
3use crate::node::{AttrNode, AttrTree};
4use crate::parse::AttrValue;
5use crate::structs::AttrStruct;
6
7const _EMPTY: Vec<AttrNode> = Vec::new();
8const _EMPTY_REF: &Vec<AttrNode> = &_EMPTY;
9
10/// map for parsing an array of attribute nodes
11pub struct AttrMap {
12    map: BTreeMap<String, Vec<AttrNode>>
13}
14
15impl AttrMap {
16    /// Create a new `AttrMap` from an array of attribute nodes
17    pub fn new(nodes: Vec<AttrNode>) -> Self {
18        let mut map: BTreeMap<String, Vec<AttrNode>> = BTreeMap::new();
19
20        for node in nodes {
21            let name = node.ident.to_string();
22
23            if let Some(array) = map.get_mut(&name) {
24                array.push(node);
25            } else {
26                map.insert(name, vec![node]);
27            }
28        }
29
30        Self { map }
31    }
32
33    /// compare a list of keys/names and return the first occurring.
34    /// if no match is found, return `None`
35    pub fn alias<'a>(&self, names: &[&'a str]) -> Option<&'a str> {
36        for name in names {
37            if self.map.contains_key(*name) {
38                return Some(name)
39            }
40        }
41        None
42    }
43
44    /// compare a list of keys/names and return the first occurring.
45    /// if no match is found return the first key.
46    pub fn alias_otherwise<'a>(&self, names: &[&'a str]) -> &'a str {
47        for name in names {
48            if self.map.contains_key(*name) {
49                return name
50            }
51        }
52        names[0]
53    }
54
55    /// peek (without removing) the nodes with a given key
56    pub fn peek_nodes(&self, key: &str) -> &Vec<AttrNode> {
57        match self.map.get(key) {
58            None => &_EMPTY_REF,
59            Some(nodes) => &nodes
60        }
61    }
62
63    /// get (removing from map) the nodes with a given key
64    pub fn get_nodes(&mut self, key: &str) -> Option<Vec<AttrNode>> {
65        match self.map.remove(key) {
66            None => None,
67            Some(nodes) => Some(nodes)
68        }
69    }
70
71    /// peek (without removing) the first matching node with the given key
72    pub fn peek_node(&self, key: &str) -> Option<&AttrNode> {
73        match self.map.get(key) {
74            None => None,
75            Some(nodes) => if nodes.len() == 1 {
76                nodes.first()
77            } else {
78                None
79            }
80        }
81    }
82
83    /// get (removing from map) the first matching node with the given key
84    ///
85    /// the parameter `error` controls duplicate behaviour
86    /// - when set to `true` - if multiple with the same key are found,
87    ///  a `KeftaError::Multiple` error will be returned
88    /// - when set to `false` - multiple nodes will be ignored.
89    pub fn get_node(&mut self, key: &str, error: bool) -> KeftaResult<Option<AttrNode>> {
90        match self.map.remove(key) {
91            None => Ok(None),
92            Some(mut nodes) => if nodes.len() == 1 {
93                Ok(Some(nodes.remove(0)))
94            } else {
95                if error {
96                    Err(KeftaError::Multiple {
97                        key: key.to_string(),
98                        count: nodes.len(),
99                        span: nodes.first().unwrap().ident.span()
100                    })
101                } else {
102                    Ok(None)
103                }
104            }
105        }
106    }
107
108    /// gather nodes (removing from map) with an array of keys
109    pub fn gather_nodes(&mut self, keys: &[&str])  -> KeftaResult<Vec<AttrNode>> {
110        let mut build = Vec::new();
111
112        for key in keys {
113            if let Some(nodes) = self.get_nodes(key) {
114                for node in nodes {
115                    build.push(node);
116                }
117            }
118        }
119
120        Ok(build)
121    }
122
123
124    /* parse functions */
125
126    /// parse a single node from an array of keys,
127    /// returning `Default::default()` if not present.
128    pub fn parse_one<T: AttrValue + Default>(&mut self, keys: &[&str])  -> KeftaResult<T> {
129        for key in keys {
130            if let Some(node) = self.get_node(key, false)? {
131                return <T as AttrValue>::parse(node);
132            }
133        }
134        Ok(<T as Default>::default())
135    }
136
137    /// parse an optional single node from an array of keys
138    pub fn parse_optional<T: AttrValue>(&mut self, keys: &[&str])  -> KeftaResult<Option<T>> {
139        for key in keys {
140            if let Some(node) = self.get_node(key, false)? {
141                return <T as AttrValue>::parse(node).map(|x| Some(x));
142            }
143        }
144        Ok(None)
145    }
146
147    /// parse an single node from an array of keys,
148    /// returning an `KeftaError::Required` error if not present.
149    pub fn parse_required<T: AttrValue>(&mut self, keys: &[&str])  -> KeftaResult<T> {
150        for key in keys {
151            if let Some(node) = self.get_node(key, false)? {
152                return <T as AttrValue>::parse(node);
153            }
154        }
155        Err(KeftaError::Required {
156            key: keys[0].to_string(),
157            multiple: false
158        })
159    }
160
161    /// parse an array of nodes, from an array of keys.
162    pub fn parse_array<T: AttrValue>(&mut self, keys: &[&str])  -> KeftaResult<Vec<T>> {
163        let mut build = Vec::new();
164
165        for key in keys {
166            if let Some(nodes) = self.get_nodes(key) {
167                for node in nodes {
168                    build.push(T::parse(node)?);
169                }
170            }
171        }
172
173        Ok(build)
174    }
175
176    /// parse an array of nodes, from an array of keys.
177    /// returns `None` if no matching nodes are found
178    pub fn parse_array_optional<T: AttrValue>(&mut self, keys: &[&str])  -> KeftaResult<Option<Vec<T>>> {
179        let array = self.parse_array(&keys)?;
180        if array.is_empty() { Ok(None) } else { Ok(Some(array)) }
181    }
182
183    /// parse an array of nodes, from an array of keys.
184    /// returns an `KeftaError::Required` error if no matching nodes are found
185    pub fn parse_array_required<T: AttrValue>(&mut self, keys: &[&str])  -> KeftaResult<Vec<T>> {
186        let array = self.parse_array(&keys)?;
187        if array.is_empty() {
188            Err(KeftaError::Required {
189                key: keys[0].to_string(),
190                multiple: true
191            })
192        } else {
193            Ok(array)
194        }
195    }
196
197    /// parse a `AttrStruct` from an array of keys.
198    ///
199    /// this inspects the nodes and gathers the contents of `AttrTree::Container`.
200    /// returns `KeftaError::ExpectedContainer` if a non-container is found
201    pub fn parse_container<T: AttrStruct>(&mut self, keys: &[&str])  -> KeftaResult<T> {
202        let mut build = Vec::new();
203
204        for node in self.gather_nodes(&keys)? {
205            match node.data {
206                AttrTree::Container { nodes, .. } => build.extend(nodes),
207                _ => return Err(KeftaError::ExpectedContainer { ident: node.ident })
208            }
209        }
210
211        T::parse(build)
212    }
213
214    /// parse an array of nodes with a given function
215    pub fn parse_with<T>(&mut self, keys: &[&str], func: fn(nodes: Vec<AttrNode>) -> KeftaResult<T>) -> KeftaResult<T> {
216        (func)(self.gather_nodes(&keys)?)
217    }
218}