parse/xml/
once.rs

1use roxmltree::{
2    Attribute,
3    Node,
4};
5use std::ops::Range;
6
7use super::{
8    missing_attribute,
9    missing_element,
10    Parsed,
11    ParseError,
12};
13
14pub enum Once<T> {
15    Missing {
16        name: &'static str,
17    },
18    Failure {
19        name_range: Range<usize>,
20        value_range: Range<usize>,
21    },
22    Success {
23        name_range: Range<usize>,
24        value_range: Range<usize>,
25        value: T,
26    },
27}
28
29impl<T> Once<T> {
30    pub fn new(name: &'static str) -> Self {
31        Once::Missing {
32            name,
33        }
34    }
35
36    pub fn attribute_failure<'input>(
37        &mut self,
38        attribute: Attribute<'input, 'input>,
39    ) {
40        *self = Once::Failure {
41            name_range: attribute.range_qname(),
42            value_range: attribute.range_value(),
43        };
44    }
45
46    pub fn attribute_success<'input>(
47        &mut self,
48        attribute: Attribute<'input, 'input>,
49        value: T,
50    ) {
51        *self = Once::Success {
52            name_range: attribute.range_qname(),
53            value_range: attribute.range_value(),
54            value,
55        }
56    }
57
58    pub fn default(self, default: T) -> T {
59        match self {
60            Once::Success { value, .. } =>
61                value,
62
63            _ =>
64                default,
65        }
66    }
67
68    pub fn default_with<W>(self, with: W) -> T
69    where
70        W: FnOnce() -> T,
71    {
72        match self {
73            Once::Success { value, .. } =>
74                value,
75
76            _ =>
77                with(),
78        }
79    }
80
81    pub fn element_failure<'input>(
82        &mut self,
83        element: Node<'input, 'input>,
84    ) {
85        *self = Once::Failure {
86            name_range: element.range(),
87            value_range: element.range(),
88        };
89    }
90
91    pub fn element_parsed_success<'input>(
92        &mut self,
93        element: Node<'input, 'input>,
94        parsed: Parsed<T>,
95    ) {
96        *self = Once::Success {
97            name_range: element.range(),
98            value_range: parsed.range,
99            value: parsed.value,
100        }
101    }
102
103    pub fn element_success<'input>(
104        &mut self,
105        element: Node<'input, 'input>,
106        value: T,
107    ) {
108        *self = Once::Success {
109            name_range: element.range(),
110            value_range: element.range(),
111            value,
112        }
113    }
114
115    pub fn exist(&self) -> bool {
116        match self {
117            Once::Success { .. } |
118            Once::Failure { .. } =>
119                true,
120
121            Once::Missing { .. } =>
122                false,
123        }
124    }
125
126    pub fn exist_value(self) -> Option<Option<T>> {
127        match self {
128            Once::Success { value, .. } =>
129                Some(Some(value)),
130
131            Once::Failure { .. } =>
132                Some(None),
133
134            Once::Missing { .. } =>
135                None,
136        }
137    }
138
139    pub fn optional(self) -> Option<Option<T>> {
140        match self {
141            Once::Success { value, .. } =>
142                Some(Some(value)),
143
144            Once::Failure { .. } =>
145                None,
146
147            Once::Missing { .. } =>
148                Some(None),
149        }
150    }
151
152    pub fn optional_parsed(self) -> Option<Option<Parsed<T>>> {
153        match self {
154            Once::Success { value, value_range, .. } =>
155                Some(Some(Parsed {
156                    range: value_range,
157                    value,
158                })),
159
160            Once::Failure { .. } =>
161                None,
162
163            Once::Missing { .. } =>
164                Some(None),
165        }
166    }
167
168    pub fn required_attribute<'input, E>(
169        self,
170        parent: &Node<'input, 'input>,
171        errors: &mut Vec<E>,
172    ) -> Option<T>
173    where
174        E: From<ParseError>,
175    {
176        match self {
177            Once::Success { value, .. } =>
178                Some(value),
179
180            Once::Failure { .. } =>
181                None,
182
183            Once::Missing { name } => {
184                missing_attribute(name, parent, errors);
185
186                None
187            }
188        }
189    }
190
191    /// Extract value of required element
192    ///
193    /// If it does not exist, raise an error
194    pub fn required_element<'input, E>(
195        self,
196        parent: &Node<'input, 'input>,
197        errors: &mut Vec<E>,
198    ) -> Option<T>
199    where
200        E: From<ParseError>,
201    {
202        match self {
203            Once::Success { value, .. } =>
204                Some(value),
205
206            Once::Failure { .. } =>
207                None,
208
209            Once::Missing { name } => {
210                missing_element(name, parent, errors);
211
212                None
213            }
214        }
215    }
216
217    pub fn required_parsed_attribute<'input, E>(
218        self,
219        parent: &Node<'input, 'input>,
220        errors: &mut Vec<E>,
221    ) -> Option<Parsed<T>>
222    where
223        E: From<ParseError>,
224    {
225        match self {
226            Once::Success { value, value_range, .. } =>
227                Some(Parsed {
228                    range: value_range,
229                    value,
230                }),
231
232            Once::Failure { .. } =>
233                None,
234
235            Once::Missing { name } => {
236                missing_attribute(name, parent, errors);
237
238                None
239            }
240        }
241    }
242
243    pub fn success_name_range(self) -> Option<Range<usize>> {
244        match self {
245            Once::Success { name_range, .. } =>
246                Some(name_range),
247
248            _ =>
249                None,
250        }
251    }
252
253    pub fn take(&mut self) -> Self {
254        std::mem::replace(self, Once::Missing { name: "Once::take" })
255    }
256}
257
258impl Once<bool> {
259    pub fn name_range_if_true(self) -> Option<Range<usize>> {
260        match self {
261            Once::Success { value: true, name_range, .. } =>
262                Some(name_range),
263
264            _ =>
265                None,
266        }
267    }
268
269    pub fn required_yes_attribute<'input, E>(
270        self,
271        parent: &Node<'input, 'input>,
272        errors: &mut Vec<E>,
273    ) -> bool
274    where
275        E: From<ParseError>,
276    {
277        match self {
278            Once::Success { value: true, .. } =>
279                true,
280
281            Once::Success { value: false, value_range, .. } => {
282                errors.push(ParseError::YesAttribute {
283                    value: value_range.into(),
284                }.into());
285
286                false
287            }
288
289            Once::Failure { .. } =>
290                false,
291
292            Once::Missing { name } => {
293                missing_attribute(name, parent, errors);
294
295                false
296            }
297        }
298    }
299}