1use roxmltree::{
2 Node,
3 NodeType,
4};
5use std::ops::Range;
6
7use crate::{
8 LowerName,
9 NameError,
10};
11
12use super::{
13 Once,
14 Parsed,
15 ParseError,
16 missing_attribute,
17 unexpected_attribute,
18};
19
20pub fn duplicate_element<E>(
22 element_name: &str,
23 duplicate_range: Range<usize>,
24 existing_range: Range<usize>,
25 errors: &mut Vec<E>,
26)
27where
28 E: From<ParseError>,
29{
30 errors.push(ParseError::DuplicateElement {
31 element: element_name.to_owned(),
32 duplicate: duplicate_range.into(),
33 existing: existing_range.into(),
34 }.into());
35}
36
37pub fn element_name<'input, E>(
62 child: &Node<'input, 'input>,
63 errors: &mut Vec<E>,
64) -> Option<&'input str>
65where
66 E: From<ParseError>,
67{
68 match child.node_type() {
69 NodeType::Element =>
70 return Some(child.tag_name().name()),
71
72 NodeType::Text =>
73 if let Some(text) = child.text() {
74 if text.split_ascii_whitespace().next().is_some() {
75 errors.push(
76 ParseError::UnexpectedElement {
77 unexpected: child.range().into(),
78 }.into(),
79 );
80 }
81 },
82
83 NodeType::Comment =>
84 (),
85
86 _ =>
87 errors.push(
88 ParseError::UnexpectedElement {
89 unexpected: child.range().into(),
90 }.into(),
91 ),
92 }
93
94 None
95}
96
97impl<T> Once<T> {
98 pub fn is_duplicate_element<'input, E>(
105 &self,
106 element: &Node<'input, 'input>,
107 errors: &mut Vec<E>,
108 ) -> bool
109 where
110 E: From<ParseError>,
111 {
112 match self {
113 Once::Success { name_range, .. } |
114 Once::Failure { name_range, .. } => {
115 duplicate_element(
116 element.tag_name().name(),
117 element.range(),
118 name_range.clone(),
119 errors,
120 );
121
122 true
123 }
124
125 Once::Missing { .. } =>
126 false,
127 }
128 }
129}
130
131impl Once<usize> {
132 pub fn length_element<'input, E>(
135 &mut self,
136 attribute_name: &'static str,
137 range: std::ops::RangeInclusive<usize>,
138 element: Node<'input, 'input>,
139 errors: &mut Vec<E>,
140 )
141 where
142 E: From<ParseError>,
143 {
144 if self.is_duplicate_element(&element, errors) {
145 return;
146 }
147
148 let mut value = Once::new(attribute_name);
149
150 for attribute in element.attributes() {
151 if attribute.name() == attribute_name {
152 value.length_attribute(range.clone(), attribute, errors);
153 } else {
154 unexpected_attribute(attribute, errors);
155 }
156 }
157
158 for child in element.children() {
159 unexpected_element(child, errors);
160 }
161
162 match value {
163 Once::Success { value, .. } =>
164 self.element_success(element, value),
165
166 Once::Failure { .. } =>
167 self.element_failure(element),
168
169 Once::Missing { name } => {
170 missing_attribute(name, &element, errors);
171
172 self.element_failure(element);
173 }
174 }
175 }
176}
177
178pub fn lower_name_attribute_in_element<'input, E>(
181 attribute_name: &'static str,
182 element: &Node<'input, 'input>,
183 errors: &mut Vec<E>,
184) -> Option<Parsed<LowerName>>
185where
186 E: From<NameError> + From<ParseError>,
187{
188 let mut found = Once::new(attribute_name);
189
190 for attribute in element.attributes() {
191 if attribute.name() == attribute_name {
192 found.lower_name_attribute(attribute, errors);
193 } else {
194 unexpected_attribute(attribute, errors);
195 }
196 }
197
198 for child in element.children() {
199 unexpected_element(child, errors);
200 }
201
202 found.required_parsed_attribute(element, errors)
203}
204
205pub fn missing_element<'input, E>(
207 name: &str,
208 parent: &Node<'input, 'input>,
209 errors: &mut Vec<E>,
210)
211where
212 E: From<ParseError>,
213{
214 errors.push(ParseError::MissingElement {
215 element: name.to_owned(),
216 parent: parent.range().into(),
217 }.into());
218}
219
220pub fn missing_element_range<E>(
222 name: &str,
223 range: Range<usize>,
224 errors: &mut Vec<E>,
225)
226where
227 E: From<ParseError>,
228{
229 errors.push(ParseError::MissingElement {
230 element: name.to_owned(),
231 parent: range.into(),
232 }.into());
233}
234
235impl Once<String> {
236 pub fn string_element<'input, E>(
238 &mut self,
239 element: Node<'input, 'input>,
240 errors: &mut Vec<E>,
241 )
242 where
243 E: From<ParseError>,
244 {
245 if self.is_duplicate_element(&element, errors) {
246 return;
247 }
248
249 if let Some(value) = string_in_element(&element, errors) {
250 self.element_parsed_success(element, value);
251 } else {
252 self.element_failure(element);
253 }
254 }
255
256 pub fn string_element_ignore_attributes<'input, E>(
260 &mut self,
261 element: Node<'input, 'input>,
262 errors: &mut Vec<E>,
263 )
264 where
265 E: From<ParseError>,
266 {
267 if self.is_duplicate_element(&element, errors) {
268 return;
269 }
270
271 if let Some(value) = string_in_element_ignore_attributes(&element, errors) {
272 self.element_parsed_success(element, value);
273 } else {
274 self.element_failure(element);
275 }
276 }
277}
278
279pub fn string_in_element<'input, E>(
281 element: &Node<'input, 'input>,
282 errors: &mut Vec<E>,
283) -> Option<Parsed<String>>
284where
285 E: From<ParseError>,
286{
287 for attribute in element.attributes() {
288 unexpected_attribute(attribute, errors);
289 }
290
291 string_in_element_ignore_attributes(element, errors)
292}
293
294pub fn string_in_element_ignore_attributes<'input, E>(
296 element: &Node<'input, 'input>,
297 errors: &mut Vec<E>,
298) -> Option<Parsed<String>>
299where
300 E: From<ParseError>,
301{
302 let mut parsed = None;
303
304 for child in element.children() {
305 if child.is_text() && parsed.is_none() {
306 if let Some(value) = child.text() {
307 parsed = Some(Parsed {
308 range: child.range(),
309 value,
310 });
311 }
312 } else {
313 unexpected_element(child, errors);
314 }
315 }
316
317 if let Some(parsed) = parsed {
318 let value = parsed.value.trim_ascii();
319
320 if value.is_empty() {
321 errors.push(ParseError::StringEmpty {
322 value: element.range().into(),
323 }.into());
324
325 None
326 } else {
327 Some(Parsed {
328 range: parsed.range,
329 value: value.to_owned(),
330 })
331 }
332 } else {
333 errors.push(ParseError::StringEmpty {
334 value: element.range().into(),
335 }.into());
336
337 None
338 }
339}
340
341pub fn unexpected_element<'input, E>(
343 element: Node<'input, 'input>,
344 errors: &mut Vec<E>,
345)
346where
347 E: From<ParseError>,
348{
349 errors.push(ParseError::UnexpectedElement {
350 unexpected: element.range().into(),
351 }.into());
352}
353
354pub fn unexpected_element_range<E>(
356 range: Range<usize>,
357 errors: &mut Vec<E>,
358)
359where
360 E: From<ParseError>,
361{
362 errors.push(ParseError::UnexpectedElement {
363 unexpected: range.into(),
364 }.into());
365}