1use alloc::boxed::Box;
16
17use crate::error::{Error, FromEventsError};
18use crate::{FromEventsBuilder, FromXml};
19
20pub struct OptionBuilder<T: FromEventsBuilder>(T);
22
23impl<T: FromEventsBuilder> FromEventsBuilder for OptionBuilder<T> {
24 type Output = Option<T::Output>;
25
26 fn feed(&mut self, ev: rxml::Event) -> Result<Option<Self::Output>, Error> {
27 self.0.feed(ev).map(|ok| ok.map(Some))
28 }
29}
30
31impl<T: FromXml> FromXml for Option<T> {
38 type Builder = OptionBuilder<T::Builder>;
39
40 fn from_events(
41 name: rxml::QName,
42 attrs: rxml::AttrMap,
43 ) -> Result<Self::Builder, FromEventsError> {
44 Ok(OptionBuilder(T::from_events(name, attrs)?))
45 }
46}
47
48pub struct BoxBuilder<T: FromEventsBuilder>(Box<T>);
50
51impl<T: FromEventsBuilder> FromEventsBuilder for BoxBuilder<T> {
52 type Output = Box<T::Output>;
53
54 fn feed(&mut self, ev: rxml::Event) -> Result<Option<Self::Output>, Error> {
55 self.0.feed(ev).map(|ok| ok.map(Box::new))
56 }
57}
58
59impl<T: FromXml> FromXml for Box<T> {
61 type Builder = BoxBuilder<T::Builder>;
62
63 fn from_events(
64 name: rxml::QName,
65 attrs: rxml::AttrMap,
66 ) -> Result<Self::Builder, FromEventsError> {
67 Ok(BoxBuilder(Box::new(T::from_events(name, attrs)?)))
68 }
69}
70
71#[derive(Debug)]
72enum FallibleBuilderInner<T: FromEventsBuilder, E> {
73 Processing { depth: usize, builder: T },
74 Failed { depth: usize, err: Option<E> },
75 Done,
76}
77
78#[derive(Debug)]
90pub struct FallibleBuilder<T: FromEventsBuilder, E>(FallibleBuilderInner<T, E>);
91
92impl<T: FromEventsBuilder, E: From<Error>> FromEventsBuilder for FallibleBuilder<T, E> {
93 type Output = Result<T::Output, E>;
94
95 fn feed(&mut self, ev: rxml::Event) -> Result<Option<Self::Output>, Error> {
96 match self.0 {
97 FallibleBuilderInner::Processing {
98 ref mut depth,
99 ref mut builder,
100 } => {
101 let new_depth = match ev {
102 rxml::Event::StartElement(..) => match depth.checked_add(1) {
103 None => {
115 self.0 = FallibleBuilderInner::Done;
116 return Err(Error::Other("maximum XML nesting depth exceeded"));
117 }
118 Some(v) => Some(v),
119 },
120 rxml::Event::EndElement(..) => depth.checked_sub(1),
127
128 rxml::Event::XmlDeclaration(..) | rxml::Event::Text(..) => Some(*depth),
131 };
132
133 match builder.feed(ev) {
134 Ok(Some(v)) => {
135 self.0 = FallibleBuilderInner::Done;
136 return Ok(Some(Ok(v)));
137 }
138 Ok(None) => {
139 }
141 Err(e) => {
142 match new_depth {
144 Some(depth) => {
147 self.0 = FallibleBuilderInner::Failed {
148 depth,
149 err: Some(e.into()),
150 };
151 return Ok(None);
152 }
153 None => {
156 self.0 = FallibleBuilderInner::Done;
157 return Ok(Some(Err(e.into())));
158 }
159 }
160 }
161 };
162
163 *depth = match new_depth {
164 Some(v) => v,
165 None => unreachable!("fallible parsing continued beyond end of element"),
166 };
167
168 Ok(None)
170 }
171 FallibleBuilderInner::Failed {
172 ref mut depth,
173 ref mut err,
174 } => {
175 *depth = match ev {
176 rxml::Event::StartElement(..) => match depth.checked_add(1) {
177 None => {
179 self.0 = FallibleBuilderInner::Done;
180 return Err(Error::Other("maximum XML nesting depth exceeded"));
181 }
182 Some(v) => v,
183 },
184 rxml::Event::EndElement(..) => match depth.checked_sub(1) {
185 Some(v) => v,
186 None => {
187 let err = err.take().expect("fallible parsing somehow lost its error");
190 self.0 = FallibleBuilderInner::Done;
191 return Ok(Some(Err(err)));
192 }
193 },
194
195 rxml::Event::XmlDeclaration(..) | rxml::Event::Text(..) => *depth,
198 };
199
200 Ok(None)
202 }
203 FallibleBuilderInner::Done => {
204 panic!("FromEventsBuilder called after it returned a value")
205 }
206 }
207 }
208}
209
210impl<T: FromXml, E: From<Error>> FromXml for Result<T, E> {
212 type Builder = FallibleBuilder<T::Builder, E>;
213
214 fn from_events(
215 name: rxml::QName,
216 attrs: rxml::AttrMap,
217 ) -> Result<Self::Builder, FromEventsError> {
218 match T::from_events(name, attrs) {
219 Ok(builder) => Ok(FallibleBuilder(FallibleBuilderInner::Processing {
220 depth: 0,
221 builder,
222 })),
223 Err(FromEventsError::Mismatch { name, attrs }) => {
224 Err(FromEventsError::Mismatch { name, attrs })
225 }
226 Err(FromEventsError::Invalid(e)) => Ok(FallibleBuilder(FallibleBuilderInner::Failed {
227 depth: 0,
228 err: Some(e.into()),
229 })),
230 }
231 }
232}
233
234#[derive(Debug, Default)]
237pub struct Discard {
238 depth: usize,
239}
240
241impl Discard {
242 pub fn new() -> Self {
244 Self::default()
245 }
246}
247
248impl FromEventsBuilder for Discard {
249 type Output = ();
250
251 fn feed(&mut self, ev: rxml::Event) -> Result<Option<Self::Output>, Error> {
252 match ev {
253 rxml::Event::StartElement(..) => {
254 self.depth = match self.depth.checked_add(1) {
255 Some(v) => v,
256 None => return Err(Error::Other("maximum XML nesting depth exceeded")),
257 };
258 Ok(None)
259 }
260 rxml::Event::EndElement(..) => match self.depth.checked_sub(1) {
261 None => Ok(Some(())),
262 Some(v) => {
263 self.depth = v;
264 Ok(None)
265 }
266 },
267 _ => Ok(None),
268 }
269 }
270}
271
272#[doc(hidden)]
277#[cfg(feature = "macros")]
278pub struct EmptyBuilder {
279 childerr: &'static str,
280 texterr: &'static str,
281}
282
283#[cfg(feature = "macros")]
284impl FromEventsBuilder for EmptyBuilder {
285 type Output = ();
286
287 fn feed(&mut self, ev: rxml::Event) -> Result<Option<Self::Output>, Error> {
288 match ev {
289 rxml::Event::EndElement(..) => Ok(Some(())),
290 rxml::Event::StartElement(..) => Err(Error::Other(self.childerr)),
291 rxml::Event::Text(..) => Err(Error::Other(self.texterr)),
292 _ => Err(Error::Other(
293 "unexpected content in supposed-to-be-empty element",
294 )),
295 }
296 }
297}
298
299#[doc(hidden)]
304#[cfg(feature = "macros")]
305pub struct Empty {
306 pub attributeerr: &'static str,
307 pub childerr: &'static str,
308 pub texterr: &'static str,
309}
310
311#[cfg(feature = "macros")]
312impl Empty {
313 pub fn start(self, attr: rxml::AttrMap) -> Result<EmptyBuilder, Error> {
314 if attr.len() > 0 {
315 return Err(Error::Other(self.attributeerr));
316 }
317 Ok(EmptyBuilder {
318 childerr: self.childerr,
319 texterr: self.texterr,
320 })
321 }
322}
323
324#[cfg(test)]
325mod tests {
326 use super::*;
327
328 use alloc::borrow::ToOwned;
329 use rxml::{parser::EventMetrics, Event, Namespace, NcName};
330
331 macro_rules! null_builder {
332 ($name:ident for $output:ident) => {
333 #[derive(Debug)]
334 enum $name {}
335
336 impl FromEventsBuilder for $name {
337 type Output = $output;
338
339 fn feed(&mut self, _: Event) -> Result<Option<Self::Output>, Error> {
340 unreachable!();
341 }
342 }
343 };
344 }
345
346 null_builder!(AlwaysMismatchBuilder for AlwaysMismatch);
347 null_builder!(InitialErrorBuilder for InitialError);
348
349 #[derive(Debug)]
350 struct AlwaysMismatch;
351
352 impl FromXml for AlwaysMismatch {
353 type Builder = AlwaysMismatchBuilder;
354
355 fn from_events(
356 name: rxml::QName,
357 attrs: rxml::AttrMap,
358 ) -> Result<Self::Builder, FromEventsError> {
359 Err(FromEventsError::Mismatch { name, attrs })
360 }
361 }
362
363 #[derive(Debug)]
364 struct InitialError;
365
366 impl FromXml for InitialError {
367 type Builder = InitialErrorBuilder;
368
369 fn from_events(_: rxml::QName, _: rxml::AttrMap) -> Result<Self::Builder, FromEventsError> {
370 Err(FromEventsError::Invalid(Error::Other("some error")))
371 }
372 }
373
374 #[derive(Debug)]
375 struct FailOnContentBuilder;
376
377 impl FromEventsBuilder for FailOnContentBuilder {
378 type Output = FailOnContent;
379
380 fn feed(&mut self, _: Event) -> Result<Option<Self::Output>, Error> {
381 Err(Error::Other("content error"))
382 }
383 }
384
385 #[derive(Debug)]
386 struct FailOnContent;
387
388 impl FromXml for FailOnContent {
389 type Builder = FailOnContentBuilder;
390
391 fn from_events(_: rxml::QName, _: rxml::AttrMap) -> Result<Self::Builder, FromEventsError> {
392 Ok(FailOnContentBuilder)
393 }
394 }
395
396 fn qname() -> rxml::QName {
397 (Namespace::NONE, NcName::try_from("test").unwrap())
398 }
399
400 fn attrs() -> rxml::AttrMap {
401 rxml::AttrMap::new()
402 }
403
404 #[test]
405 fn fallible_builder_mismatch_passthrough() {
406 match Result::<AlwaysMismatch, Error>::from_events(qname(), attrs()) {
407 Err(FromEventsError::Mismatch { .. }) => (),
408 other => panic!("unexpected result: {:?}", other),
409 }
410 }
411
412 #[test]
413 fn fallible_builder_initial_error_capture() {
414 let mut builder = match Result::<InitialError, Error>::from_events(qname(), attrs()) {
415 Ok(v) => v,
416 other => panic!("unexpected result: {:?}", other),
417 };
418 match builder.feed(Event::Text(EventMetrics::zero(), "hello world!".to_owned())) {
419 Ok(None) => (),
420 other => panic!("unexpected result: {:?}", other),
421 };
422 match builder.feed(Event::EndElement(EventMetrics::zero())) {
423 Ok(Some(Err(Error::Other("some error")))) => (),
424 other => panic!("unexpected result: {:?}", other),
425 };
426 }
427
428 #[test]
429 fn fallible_builder_initial_error_capture_allows_nested_stuff() {
430 let mut builder = match Result::<InitialError, Error>::from_events(qname(), attrs()) {
431 Ok(v) => v,
432 other => panic!("unexpected result: {:?}", other),
433 };
434 match builder.feed(Event::StartElement(EventMetrics::zero(), qname(), attrs())) {
435 Ok(None) => (),
436 other => panic!("unexpected result: {:?}", other),
437 };
438 match builder.feed(Event::Text(EventMetrics::zero(), "hello world!".to_owned())) {
439 Ok(None) => (),
440 other => panic!("unexpected result: {:?}", other),
441 };
442 match builder.feed(Event::EndElement(EventMetrics::zero())) {
443 Ok(None) => (),
444 other => panic!("unexpected result: {:?}", other),
445 };
446 match builder.feed(Event::Text(EventMetrics::zero(), "hello world!".to_owned())) {
447 Ok(None) => (),
448 other => panic!("unexpected result: {:?}", other),
449 };
450 match builder.feed(Event::StartElement(EventMetrics::zero(), qname(), attrs())) {
451 Ok(None) => (),
452 other => panic!("unexpected result: {:?}", other),
453 };
454 match builder.feed(Event::StartElement(EventMetrics::zero(), qname(), attrs())) {
455 Ok(None) => (),
456 other => panic!("unexpected result: {:?}", other),
457 };
458 match builder.feed(Event::Text(EventMetrics::zero(), "hello world!".to_owned())) {
459 Ok(None) => (),
460 other => panic!("unexpected result: {:?}", other),
461 };
462 match builder.feed(Event::EndElement(EventMetrics::zero())) {
463 Ok(None) => (),
464 other => panic!("unexpected result: {:?}", other),
465 };
466 match builder.feed(Event::EndElement(EventMetrics::zero())) {
467 Ok(None) => (),
468 other => panic!("unexpected result: {:?}", other),
469 };
470 match builder.feed(Event::EndElement(EventMetrics::zero())) {
471 Ok(Some(Err(Error::Other("some error")))) => (),
472 other => panic!("unexpected result: {:?}", other),
473 };
474 }
475
476 #[test]
477 fn fallible_builder_content_error_capture() {
478 let mut builder = match Result::<FailOnContent, Error>::from_events(qname(), attrs()) {
479 Ok(v) => v,
480 other => panic!("unexpected result: {:?}", other),
481 };
482 match builder.feed(Event::EndElement(EventMetrics::zero())) {
483 Ok(Some(Err(Error::Other("content error")))) => (),
484 other => panic!("unexpected result: {:?}", other),
485 };
486 }
487
488 #[test]
489 fn fallible_builder_content_error_capture_with_more_content() {
490 let mut builder = match Result::<FailOnContent, Error>::from_events(qname(), attrs()) {
491 Ok(v) => v,
492 other => panic!("unexpected result: {:?}", other),
493 };
494 match builder.feed(Event::Text(EventMetrics::zero(), "hello world!".to_owned())) {
495 Ok(None) => (),
496 other => panic!("unexpected result: {:?}", other),
497 };
498 match builder.feed(Event::EndElement(EventMetrics::zero())) {
499 Ok(Some(Err(Error::Other("content error")))) => (),
500 other => panic!("unexpected result: {:?}", other),
501 };
502 }
503
504 #[test]
505 fn fallible_builder_content_error_capture_with_nested_content() {
506 let mut builder = match Result::<FailOnContent, Error>::from_events(qname(), attrs()) {
507 Ok(v) => v,
508 other => panic!("unexpected result: {:?}", other),
509 };
510 match builder.feed(Event::StartElement(EventMetrics::zero(), qname(), attrs())) {
511 Ok(None) => (),
512 other => panic!("unexpected result: {:?}", other),
513 };
514 match builder.feed(Event::Text(EventMetrics::zero(), "hello world!".to_owned())) {
515 Ok(None) => (),
516 other => panic!("unexpected result: {:?}", other),
517 };
518 match builder.feed(Event::EndElement(EventMetrics::zero())) {
519 Ok(None) => (),
520 other => panic!("unexpected result: {:?}", other),
521 };
522 match builder.feed(Event::Text(EventMetrics::zero(), "hello world!".to_owned())) {
523 Ok(None) => (),
524 other => panic!("unexpected result: {:?}", other),
525 };
526 match builder.feed(Event::StartElement(EventMetrics::zero(), qname(), attrs())) {
527 Ok(None) => (),
528 other => panic!("unexpected result: {:?}", other),
529 };
530 match builder.feed(Event::StartElement(EventMetrics::zero(), qname(), attrs())) {
531 Ok(None) => (),
532 other => panic!("unexpected result: {:?}", other),
533 };
534 match builder.feed(Event::Text(EventMetrics::zero(), "hello world!".to_owned())) {
535 Ok(None) => (),
536 other => panic!("unexpected result: {:?}", other),
537 };
538 match builder.feed(Event::EndElement(EventMetrics::zero())) {
539 Ok(None) => (),
540 other => panic!("unexpected result: {:?}", other),
541 };
542 match builder.feed(Event::EndElement(EventMetrics::zero())) {
543 Ok(None) => (),
544 other => panic!("unexpected result: {:?}", other),
545 };
546 match builder.feed(Event::EndElement(EventMetrics::zero())) {
547 Ok(Some(Err(Error::Other("content error")))) => (),
548 other => panic!("unexpected result: {:?}", other),
549 };
550 }
551}