1use alloc::boxed::Box;
16
17use crate::error::{Error, FromEventsError};
18use crate::{FromEventsBuilder, FromXml};
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub enum XmlNameMatcher<'x> {
23 Any,
25
26 InNamespace(&'x str),
28
29 Specific(&'x str, &'x str),
31}
32
33impl<'x> XmlNameMatcher<'x> {
34 pub const fn superset(self, other: Self) -> Self {
36 match self {
37 Self::Any => Self::Any,
38 Self::InNamespace(my_namespace) => match other {
39 Self::Any => Self::Any,
40 Self::InNamespace(other_namespace) | Self::Specific(other_namespace, _) => {
41 if crate::util::const_str_eq(my_namespace, other_namespace) {
42 Self::InNamespace(my_namespace)
43 } else {
44 Self::Any
45 }
46 }
47 },
48 Self::Specific(my_namespace, my_name) => match other {
49 Self::Any => Self::Any,
50 Self::InNamespace(other_namespace) => {
51 if crate::util::const_str_eq(my_namespace, other_namespace) {
52 Self::InNamespace(my_namespace)
53 } else {
54 Self::Any
55 }
56 }
57 Self::Specific(other_namespace, other_name) => {
58 if crate::util::const_str_eq(my_namespace, other_namespace) {
59 if crate::util::const_str_eq(my_name, other_name) {
60 Self::Specific(my_name, other_name)
61 } else {
62 Self::InNamespace(my_namespace)
63 }
64 } else {
65 Self::Any
66 }
67 }
68 },
69 }
70 }
71
72 pub fn matches(&self, qname: &rxml::QName) -> bool {
74 match self {
75 Self::Any => true,
76 Self::InNamespace(ns) => qname.0.as_str() == *ns,
77 Self::Specific(ns, name) => qname.0.as_str() == *ns && qname.1.as_str() == *name,
78 }
79 }
80}
81
82#[derive(Debug)]
93#[doc(hidden)]
94pub struct Context<'x> {
95 language: Option<&'x str>,
96}
97
98impl<'x> Context<'x> {
99 pub fn empty() -> Self {
103 Self { language: None }
104 }
105
106 pub fn with_language(mut self, language: Option<&'x str>) -> Self {
108 self.language = language;
109 self
110 }
111
112 pub fn language(&self) -> Option<&str> {
115 self.language.as_deref()
116 }
117}
118
119pub struct OptionBuilder<T: FromEventsBuilder>(T);
121
122impl<T: FromEventsBuilder> FromEventsBuilder for OptionBuilder<T> {
123 type Output = Option<T::Output>;
124
125 fn feed(&mut self, ev: rxml::Event, ctx: &Context<'_>) -> Result<Option<Self::Output>, Error> {
126 self.0.feed(ev, ctx).map(|ok| ok.map(Some))
127 }
128}
129
130impl<T: FromXml> FromXml for Option<T> {
137 type Builder = OptionBuilder<T::Builder>;
138
139 fn from_events(
140 name: rxml::QName,
141 attrs: rxml::AttrMap,
142 ctx: &Context<'_>,
143 ) -> Result<Self::Builder, FromEventsError> {
144 Ok(OptionBuilder(T::from_events(name, attrs, ctx)?))
145 }
146}
147
148pub struct BoxBuilder<T: FromEventsBuilder + ?Sized>(Box<T>);
150
151impl<T: FromEventsBuilder + ?Sized> FromEventsBuilder for BoxBuilder<T> {
152 type Output = Box<T::Output>;
153
154 fn feed(&mut self, ev: rxml::Event, ctx: &Context<'_>) -> Result<Option<Self::Output>, Error> {
155 self.0.feed(ev, ctx).map(|ok| ok.map(Box::new))
156 }
157}
158
159impl<T: FromXml + ?Sized> FromXml for Box<T> {
161 type Builder = BoxBuilder<T::Builder>;
162
163 fn from_events(
164 name: rxml::QName,
165 attrs: rxml::AttrMap,
166 ctx: &Context<'_>,
167 ) -> Result<Self::Builder, FromEventsError> {
168 Ok(BoxBuilder(Box::new(T::from_events(name, attrs, ctx)?)))
169 }
170}
171
172impl<T: FromEventsBuilder + ?Sized> FromEventsBuilder for Box<T> {
173 type Output = T::Output;
174
175 fn feed(&mut self, ev: rxml::Event, ctx: &Context<'_>) -> Result<Option<Self::Output>, Error> {
176 (**self).feed(ev, ctx)
177 }
178}
179
180#[derive(Debug)]
181enum FallibleBuilderInner<T: FromEventsBuilder, E> {
182 Processing { depth: usize, builder: T },
183 Failed { depth: usize, err: Option<E> },
184 Done,
185}
186
187#[derive(Debug)]
199pub struct FallibleBuilder<T: FromEventsBuilder, E>(FallibleBuilderInner<T, E>);
200
201impl<T: FromEventsBuilder, E: From<Error>> FromEventsBuilder for FallibleBuilder<T, E> {
202 type Output = Result<T::Output, E>;
203
204 fn feed(&mut self, ev: rxml::Event, ctx: &Context<'_>) -> Result<Option<Self::Output>, Error> {
205 match self.0 {
206 FallibleBuilderInner::Processing {
207 ref mut depth,
208 ref mut builder,
209 } => {
210 let new_depth = match ev {
211 rxml::Event::StartElement(..) => match depth.checked_add(1) {
212 None => {
224 self.0 = FallibleBuilderInner::Done;
225 return Err(Error::Other("maximum XML nesting depth exceeded"));
226 }
227 Some(v) => Some(v),
228 },
229 rxml::Event::EndElement(..) => depth.checked_sub(1),
236
237 rxml::Event::XmlDeclaration(..) | rxml::Event::Text(..) => Some(*depth),
240 };
241
242 match builder.feed(ev, ctx) {
243 Ok(Some(v)) => {
244 self.0 = FallibleBuilderInner::Done;
245 return Ok(Some(Ok(v)));
246 }
247 Ok(None) => {
248 }
250 Err(e) => {
251 match new_depth {
253 Some(depth) => {
256 self.0 = FallibleBuilderInner::Failed {
257 depth,
258 err: Some(e.into()),
259 };
260 return Ok(None);
261 }
262 None => {
265 self.0 = FallibleBuilderInner::Done;
266 return Ok(Some(Err(e.into())));
267 }
268 }
269 }
270 };
271
272 *depth = match new_depth {
273 Some(v) => v,
274 None => unreachable!("fallible parsing continued beyond end of element"),
275 };
276
277 Ok(None)
279 }
280 FallibleBuilderInner::Failed {
281 ref mut depth,
282 ref mut err,
283 } => {
284 *depth = match ev {
285 rxml::Event::StartElement(..) => match depth.checked_add(1) {
286 None => {
288 self.0 = FallibleBuilderInner::Done;
289 return Err(Error::Other("maximum XML nesting depth exceeded"));
290 }
291 Some(v) => v,
292 },
293 rxml::Event::EndElement(..) => match depth.checked_sub(1) {
294 Some(v) => v,
295 None => {
296 let err = err.take().expect("fallible parsing somehow lost its error");
299 self.0 = FallibleBuilderInner::Done;
300 return Ok(Some(Err(err)));
301 }
302 },
303
304 rxml::Event::XmlDeclaration(..) | rxml::Event::Text(..) => *depth,
307 };
308
309 Ok(None)
311 }
312 FallibleBuilderInner::Done => {
313 panic!("FromEventsBuilder called after it returned a value")
314 }
315 }
316 }
317}
318
319impl<T: FromXml, E: From<Error>> FromXml for Result<T, E> {
321 type Builder = FallibleBuilder<T::Builder, E>;
322
323 fn from_events(
324 name: rxml::QName,
325 attrs: rxml::AttrMap,
326 ctx: &Context<'_>,
327 ) -> Result<Self::Builder, FromEventsError> {
328 match T::from_events(name, attrs, ctx) {
329 Ok(builder) => Ok(FallibleBuilder(FallibleBuilderInner::Processing {
330 depth: 0,
331 builder,
332 })),
333 Err(FromEventsError::Mismatch { name, attrs }) => {
334 Err(FromEventsError::Mismatch { name, attrs })
335 }
336 Err(FromEventsError::Invalid(e)) => Ok(FallibleBuilder(FallibleBuilderInner::Failed {
337 depth: 0,
338 err: Some(e.into()),
339 })),
340 }
341 }
342}
343
344#[derive(Debug, Default)]
347pub struct Discard {
348 depth: usize,
349}
350
351impl Discard {
352 pub fn new() -> Self {
354 Self::default()
355 }
356}
357
358impl FromEventsBuilder for Discard {
359 type Output = ();
360
361 fn feed(&mut self, ev: rxml::Event, _ctx: &Context<'_>) -> Result<Option<Self::Output>, Error> {
362 match ev {
363 rxml::Event::StartElement(..) => {
364 self.depth = match self.depth.checked_add(1) {
365 Some(v) => v,
366 None => return Err(Error::Other("maximum XML nesting depth exceeded")),
367 };
368 Ok(None)
369 }
370 rxml::Event::EndElement(..) => match self.depth.checked_sub(1) {
371 None => Ok(Some(())),
372 Some(v) => {
373 self.depth = v;
374 Ok(None)
375 }
376 },
377 _ => Ok(None),
378 }
379 }
380}
381
382#[doc(hidden)]
387#[cfg(feature = "macros")]
388pub struct EmptyBuilder {
389 childerr: &'static str,
390 texterr: &'static str,
391}
392
393#[cfg(feature = "macros")]
394impl FromEventsBuilder for EmptyBuilder {
395 type Output = ();
396
397 fn feed(&mut self, ev: rxml::Event, _ctx: &Context<'_>) -> Result<Option<Self::Output>, Error> {
398 match ev {
399 rxml::Event::EndElement(..) => Ok(Some(())),
400 rxml::Event::StartElement(..) => Err(Error::Other(self.childerr)),
401 rxml::Event::Text(..) => Err(Error::Other(self.texterr)),
402 _ => Err(Error::Other(
403 "unexpected content in supposed-to-be-empty element",
404 )),
405 }
406 }
407}
408
409#[doc(hidden)]
414#[cfg(feature = "macros")]
415pub struct Empty {
416 pub attributeerr: &'static str,
417 pub childerr: &'static str,
418 pub texterr: &'static str,
419}
420
421#[cfg(feature = "macros")]
422impl Empty {
423 pub fn start(self, attr: rxml::AttrMap) -> Result<EmptyBuilder, Error> {
424 if !attr.is_empty() {
425 return Err(Error::Other(self.attributeerr));
426 }
427 Ok(EmptyBuilder {
428 childerr: self.childerr,
429 texterr: self.texterr,
430 })
431 }
432}
433
434#[cfg(test)]
435mod tests {
436 use super::*;
437
438 use alloc::borrow::ToOwned;
439 use rxml::{parser::EventMetrics, Event, Namespace, NcName};
440
441 macro_rules! null_builder {
442 ($name:ident for $output:ident) => {
443 #[derive(Debug)]
444 enum $name {}
445
446 impl FromEventsBuilder for $name {
447 type Output = $output;
448
449 fn feed(
450 &mut self,
451 _: Event,
452 _: &Context<'_>,
453 ) -> Result<Option<Self::Output>, Error> {
454 unreachable!();
455 }
456 }
457 };
458 }
459
460 null_builder!(AlwaysMismatchBuilder for AlwaysMismatch);
461 null_builder!(InitialErrorBuilder for InitialError);
462
463 #[derive(Debug)]
464 struct AlwaysMismatch;
465
466 impl FromXml for AlwaysMismatch {
467 type Builder = AlwaysMismatchBuilder;
468
469 fn from_events(
470 name: rxml::QName,
471 attrs: rxml::AttrMap,
472 _ctx: &Context<'_>,
473 ) -> Result<Self::Builder, FromEventsError> {
474 Err(FromEventsError::Mismatch { name, attrs })
475 }
476 }
477
478 #[derive(Debug)]
479 struct InitialError;
480
481 impl FromXml for InitialError {
482 type Builder = InitialErrorBuilder;
483
484 fn from_events(
485 _: rxml::QName,
486 _: rxml::AttrMap,
487 _: &Context<'_>,
488 ) -> Result<Self::Builder, FromEventsError> {
489 Err(FromEventsError::Invalid(Error::Other("some error")))
490 }
491 }
492
493 #[derive(Debug)]
494 struct FailOnContentBuilder;
495
496 impl FromEventsBuilder for FailOnContentBuilder {
497 type Output = FailOnContent;
498
499 fn feed(&mut self, _: Event, _: &Context<'_>) -> Result<Option<Self::Output>, Error> {
500 Err(Error::Other("content error"))
501 }
502 }
503
504 #[derive(Debug)]
505 struct FailOnContent;
506
507 impl FromXml for FailOnContent {
508 type Builder = FailOnContentBuilder;
509
510 fn from_events(
511 _: rxml::QName,
512 _: rxml::AttrMap,
513 _: &Context<'_>,
514 ) -> Result<Self::Builder, FromEventsError> {
515 Ok(FailOnContentBuilder)
516 }
517 }
518
519 fn qname() -> rxml::QName {
520 (Namespace::NONE, NcName::try_from("test").unwrap())
521 }
522
523 fn attrs() -> rxml::AttrMap {
524 rxml::AttrMap::new()
525 }
526
527 #[test]
528 fn fallible_builder_mismatch_passthrough() {
529 match Result::<AlwaysMismatch, Error>::from_events(qname(), attrs(), &Context::empty()) {
530 Err(FromEventsError::Mismatch { .. }) => (),
531 other => panic!("unexpected result: {:?}", other),
532 }
533 }
534
535 #[test]
536 fn fallible_builder_initial_error_capture() {
537 let ctx = Context::empty();
538 let mut builder = match Result::<InitialError, Error>::from_events(qname(), attrs(), &ctx) {
539 Ok(v) => v,
540 other => panic!("unexpected result: {:?}", other),
541 };
542 match builder.feed(
543 Event::Text(EventMetrics::zero(), "hello world!".to_owned()),
544 &ctx,
545 ) {
546 Ok(None) => (),
547 other => panic!("unexpected result: {:?}", other),
548 };
549 match builder.feed(Event::EndElement(EventMetrics::zero()), &ctx) {
550 Ok(Some(Err(Error::Other("some error")))) => (),
551 other => panic!("unexpected result: {:?}", other),
552 };
553 }
554
555 #[test]
556 fn fallible_builder_initial_error_capture_allows_nested_stuff() {
557 let ctx = Context::empty();
558 let mut builder = match Result::<InitialError, Error>::from_events(qname(), attrs(), &ctx) {
559 Ok(v) => v,
560 other => panic!("unexpected result: {:?}", other),
561 };
562 match builder.feed(
563 Event::StartElement(EventMetrics::zero(), qname(), attrs()),
564 &ctx,
565 ) {
566 Ok(None) => (),
567 other => panic!("unexpected result: {:?}", other),
568 };
569 match builder.feed(
570 Event::Text(EventMetrics::zero(), "hello world!".to_owned()),
571 &ctx,
572 ) {
573 Ok(None) => (),
574 other => panic!("unexpected result: {:?}", other),
575 };
576 match builder.feed(Event::EndElement(EventMetrics::zero()), &ctx) {
577 Ok(None) => (),
578 other => panic!("unexpected result: {:?}", other),
579 };
580 match builder.feed(
581 Event::Text(EventMetrics::zero(), "hello world!".to_owned()),
582 &ctx,
583 ) {
584 Ok(None) => (),
585 other => panic!("unexpected result: {:?}", other),
586 };
587 match builder.feed(
588 Event::StartElement(EventMetrics::zero(), qname(), attrs()),
589 &ctx,
590 ) {
591 Ok(None) => (),
592 other => panic!("unexpected result: {:?}", other),
593 };
594 match builder.feed(
595 Event::StartElement(EventMetrics::zero(), qname(), attrs()),
596 &ctx,
597 ) {
598 Ok(None) => (),
599 other => panic!("unexpected result: {:?}", other),
600 };
601 match builder.feed(
602 Event::Text(EventMetrics::zero(), "hello world!".to_owned()),
603 &ctx,
604 ) {
605 Ok(None) => (),
606 other => panic!("unexpected result: {:?}", other),
607 };
608 match builder.feed(Event::EndElement(EventMetrics::zero()), &ctx) {
609 Ok(None) => (),
610 other => panic!("unexpected result: {:?}", other),
611 };
612 match builder.feed(Event::EndElement(EventMetrics::zero()), &ctx) {
613 Ok(None) => (),
614 other => panic!("unexpected result: {:?}", other),
615 };
616 match builder.feed(Event::EndElement(EventMetrics::zero()), &ctx) {
617 Ok(Some(Err(Error::Other("some error")))) => (),
618 other => panic!("unexpected result: {:?}", other),
619 };
620 }
621
622 #[test]
623 fn fallible_builder_content_error_capture() {
624 let ctx = Context::empty();
625 let mut builder = match Result::<FailOnContent, Error>::from_events(qname(), attrs(), &ctx)
626 {
627 Ok(v) => v,
628 other => panic!("unexpected result: {:?}", other),
629 };
630 match builder.feed(Event::EndElement(EventMetrics::zero()), &ctx) {
631 Ok(Some(Err(Error::Other("content error")))) => (),
632 other => panic!("unexpected result: {:?}", other),
633 };
634 }
635
636 #[test]
637 fn fallible_builder_content_error_capture_with_more_content() {
638 let ctx = Context::empty();
639 let mut builder = match Result::<FailOnContent, Error>::from_events(qname(), attrs(), &ctx)
640 {
641 Ok(v) => v,
642 other => panic!("unexpected result: {:?}", other),
643 };
644 match builder.feed(
645 Event::Text(EventMetrics::zero(), "hello world!".to_owned()),
646 &ctx,
647 ) {
648 Ok(None) => (),
649 other => panic!("unexpected result: {:?}", other),
650 };
651 match builder.feed(Event::EndElement(EventMetrics::zero()), &ctx) {
652 Ok(Some(Err(Error::Other("content error")))) => (),
653 other => panic!("unexpected result: {:?}", other),
654 };
655 }
656
657 #[test]
658 fn fallible_builder_content_error_capture_with_nested_content() {
659 let ctx = Context::empty();
660 let mut builder = match Result::<FailOnContent, Error>::from_events(qname(), attrs(), &ctx)
661 {
662 Ok(v) => v,
663 other => panic!("unexpected result: {:?}", other),
664 };
665 match builder.feed(
666 Event::StartElement(EventMetrics::zero(), qname(), attrs()),
667 &ctx,
668 ) {
669 Ok(None) => (),
670 other => panic!("unexpected result: {:?}", other),
671 };
672 match builder.feed(
673 Event::Text(EventMetrics::zero(), "hello world!".to_owned()),
674 &ctx,
675 ) {
676 Ok(None) => (),
677 other => panic!("unexpected result: {:?}", other),
678 };
679 match builder.feed(Event::EndElement(EventMetrics::zero()), &ctx) {
680 Ok(None) => (),
681 other => panic!("unexpected result: {:?}", other),
682 };
683 match builder.feed(
684 Event::Text(EventMetrics::zero(), "hello world!".to_owned()),
685 &ctx,
686 ) {
687 Ok(None) => (),
688 other => panic!("unexpected result: {:?}", other),
689 };
690 match builder.feed(
691 Event::StartElement(EventMetrics::zero(), qname(), attrs()),
692 &ctx,
693 ) {
694 Ok(None) => (),
695 other => panic!("unexpected result: {:?}", other),
696 };
697 match builder.feed(
698 Event::StartElement(EventMetrics::zero(), qname(), attrs()),
699 &ctx,
700 ) {
701 Ok(None) => (),
702 other => panic!("unexpected result: {:?}", other),
703 };
704 match builder.feed(
705 Event::Text(EventMetrics::zero(), "hello world!".to_owned()),
706 &ctx,
707 ) {
708 Ok(None) => (),
709 other => panic!("unexpected result: {:?}", other),
710 };
711 match builder.feed(Event::EndElement(EventMetrics::zero()), &ctx) {
712 Ok(None) => (),
713 other => panic!("unexpected result: {:?}", other),
714 };
715 match builder.feed(Event::EndElement(EventMetrics::zero()), &ctx) {
716 Ok(None) => (),
717 other => panic!("unexpected result: {:?}", other),
718 };
719 match builder.feed(Event::EndElement(EventMetrics::zero()), &ctx) {
720 Ok(Some(Err(Error::Other("content error")))) => (),
721 other => panic!("unexpected result: {:?}", other),
722 };
723 }
724}