1use roxmltree::{
2 Attribute,
3 Node,
4};
5use std::ops::Range;
6
7use crate::{
8 DottedPath,
9 LowerName,
10 NameError,
11 PathError,
12 UpperName,
13};
14
15use super::{
16 Once,
17 ParseError,
18};
19
20impl Once<bool> {
21 pub fn boolean_attribute<'input, E>(
23 &mut self,
24 attribute: Attribute<'input, 'input>,
25 errors: &mut Vec<E>,
26 )
27 where
28 E: From<ParseError> + From<NameError>,
29 {
30 if self.is_duplicate_attribute(&attribute, errors) {
31 return;
32 }
33
34 match attribute.value() {
35 "yes" | "true" =>
36 self.attribute_success(attribute, true),
37
38 "no" | "false" =>
39 self.attribute_success(attribute, false),
40
41 _ => {
42 errors.push(ParseError::BooleanInvalid {
43 value: attribute.range_value().into(),
44 }.into());
45
46 self.attribute_failure(attribute);
47 }
48 }
49 }
50}
51
52impl Once<DottedPath> {
53 pub fn dotted_path_attribute<'input, E>(
55 &mut self,
56 attribute: Attribute<'input, 'input>,
57 errors: &mut Vec<E>,
58 )
59 where
60 E: From<ParseError> + From<PathError>,
61 {
62 if self.is_duplicate_attribute(&attribute, errors) {
63 return;
64 }
65
66 match DottedPath::try_from(attribute) {
67 Ok(value) =>
68 self.attribute_success(attribute, value),
69
70 Err(error) => {
71 errors.push(error.into());
72
73 self.attribute_failure(attribute);
74 }
75 }
76 }
77}
78
79pub fn duplicate_attribute<E: From<ParseError>>(
81 attribute_name: &str,
82 duplicate_range: Range<usize>,
83 existing_range: Range<usize>,
84 errors: &mut Vec<E>,
85) {
86 errors.push(ParseError::DuplicateAttribute {
87 attribute: attribute_name.to_owned(),
88 duplicate: duplicate_range.into(),
89 existing: existing_range.into(),
90 }.into());
91}
92
93impl<T: Clone> Once<T> {
94 pub fn enum_attribute<'input, E>(
96 &mut self,
97 values: &'static [(&'static str, T)],
98 attribute: Attribute<'input, 'input>,
99 errors: &mut Vec<E>,
100 )
101 where
102 E: From<ParseError> + From<NameError>,
103 {
104 if self.is_duplicate_attribute(&attribute, errors) {
105 return;
106 }
107
108 for (name, value) in values {
109 if *name == attribute.value() {
110 self.attribute_success(attribute, value.clone());
111
112 return;
113 }
114 }
115
116 let last = values.len() - 1;
117 let mut message = format!(
118 "Expecting one of `{}",
119 values[0].0,
120 );
121 for (name, _) in &values[1..last] {
122 message.push_str("`, `");
123 message.push_str(name);
124 }
125 message.push_str("` or `");
126 message.push_str(values[last].0);
127 message.push_str("`");
128 errors.push(ParseError::EnumValue {
129 message,
130 value: attribute.range_value().into(),
131 }.into());
132
133 self.attribute_failure(attribute);
134 }
135}
136
137impl<T> Once<T> {
138 pub fn is_duplicate_attribute<'input, E>(
142 &self,
143 attribute: &Attribute<'input, 'input>,
144 errors: &mut Vec<E>,
145 ) -> bool
146 where
147 E: From<ParseError>,
148 {
149 match self {
150 Once::Success { name_range, .. } |
151 Once::Failure { name_range, .. } => {
152 duplicate_attribute(
153 attribute.name(),
154 attribute.range_qname(),
155 name_range.clone(),
156 errors,
157 );
158
159 true
160 }
161
162 Once::Missing { .. } =>
163 false,
164 }
165 }
166}
167
168impl Once<usize> {
169 pub fn length_attribute<'input, E>(
172 &mut self,
173 range: std::ops::RangeInclusive<usize>,
174 attribute: Attribute<'input, 'input>,
175 errors: &mut Vec<E>,
176 )
177 where
178 E: From<ParseError>,
179 {
180 if self.is_duplicate_attribute(&attribute, errors) {
181 return;
182 }
183
184 if let Ok(value) = usize::from_str_radix(attribute.value(), 10) {
185 if range.contains(&value) {
186 self.attribute_success(attribute, value);
187 } else {
188 errors.push(ParseError::LengthRange {
189 min: *range.start(),
190 max: *range.end(),
191 value: attribute.range_value().into(),
192 }.into());
193
194 self.attribute_failure(attribute);
195 }
196 } else {
197 errors.push(ParseError::LengthInvalid {
198 value: attribute.range_value().into(),
199 }.into());
200
201 self.attribute_failure(attribute);
202 }
203 }
204}
205
206impl Once<LowerName> {
207 pub fn lower_name_attribute<'input, E>(
209 &mut self,
210 attribute: Attribute<'input, 'input>,
211 errors: &mut Vec<E>,
212 )
213 where
214 E: From<ParseError> + From<NameError>,
215 {
216 if self.is_duplicate_attribute(&attribute, errors) {
217 return;
218 }
219
220 match LowerName::try_from(attribute) {
221 Ok(value) =>
222 self.attribute_success(attribute, value),
223
224 Err(error) => {
225 errors.push(error.into());
226
227 self.attribute_failure(attribute);
228 }
229 }
230 }
231}
232
233pub fn missing_attribute<'input, E>(
235 name: &str,
236 parent: &Node<'input, 'input>,
237 errors: &mut Vec<E>,
238)
239where
240 E: From<ParseError>,
241{
242 errors.push(ParseError::MissingAttribute {
243 element: parent.tag_name().name().to_owned(),
244 attribute: name.to_owned(),
245 parent: parent.range().into(),
246 }.into());
247}
248
249impl Once<usize> {
250 pub fn number_attribute<'input, E>(
253 &mut self,
254 attribute: Attribute<'input, 'input>,
255 errors: &mut Vec<E>,
256 )
257 where
258 E: From<ParseError>,
259 {
260 if self.is_duplicate_attribute(&attribute, errors) {
261 return;
262 }
263
264 if let Ok(value) = usize::from_str_radix(attribute.value(), 10) {
265 self.attribute_success(attribute, value);
266 } else {
267 errors.push(ParseError::NumberValue {
268 value: attribute.range_value().into(),
269 }.into());
270
271 self.attribute_failure(attribute);
272 }
273 }
274}
275
276impl Once<String> {
277 pub fn string_attribute<'input, E>(
279 &mut self,
280 attribute: Attribute<'input, 'input>,
281 errors: &mut Vec<E>,
282 )
283 where
284 E: From<ParseError>,
285 {
286 if self.is_duplicate_attribute(&attribute, errors) {
287 return;
288 }
289
290 let value = attribute.value().trim_ascii();
291
292 if value.is_empty() {
293 errors.push(ParseError::StringEmpty {
294 value: attribute.range().into(),
295 }.into());
296
297 self.attribute_failure(attribute);
298 } else {
299 self.attribute_success(attribute, value.to_owned());
300 }
301 }
302}
303
304impl Once<UpperName> {
305 pub fn upper_name_attribute<'input, E>(
307 &mut self,
308 attribute: Attribute<'input, 'input>,
309 errors: &mut Vec<E>,
310 )
311 where
312 E: From<ParseError> + From<NameError>,
313 {
314 if self.is_duplicate_attribute(&attribute, errors) {
315 return;
316 }
317
318 match UpperName::try_from(attribute) {
319 Ok(value) =>
320 self.attribute_success(attribute, value),
321
322 Err(error) => {
323 errors.push(error.into());
324
325 self.attribute_failure(attribute);
326 }
327 }
328 }
329}
330
331pub fn unexpected_attribute<'input, E>(
333 attribute: Attribute<'input, 'input>,
334 errors: &mut Vec<E>,
335)
336where
337 E: From<ParseError>,
338{
339 errors.push(ParseError::UnexpectedAttribute {
340 unexpected: attribute.range_qname().into(),
341 }.into());
342}