1use std::{borrow::Cow, collections::HashMap};
2
3use quick_xml::{
4 NsReader, XmlVersion,
5 escape::unescape,
6 events::{BytesStart, Event},
7 name::{QName, ResolveResult},
8};
9
10use crate::{
11 MultipleEMLErrors,
12 error::{EMLError, EMLErrorKind, EMLResultExt},
13 io::QualifiedName,
14 utils::{StringValue, StringValueData},
15};
16
17pub trait EMLRead {
19 fn parse_eml(input: &str, parsing_mode: EMLParsingMode) -> EMLReadResult<Self>
28 where
29 Self: Sized;
30}
31
32#[must_use]
34pub enum EMLReadResult<T> {
35 Ok(T, Vec<EMLError>),
37 Err(EMLError),
39}
40
41impl<T> EMLReadResult<T> {
42 pub fn errors(&self) -> &[EMLError] {
44 match self {
45 EMLReadResult::Ok(_, errors) => errors,
46 EMLReadResult::Err(EMLError::Multiple(MultipleEMLErrors { errors })) => errors,
47 EMLReadResult::Err(err) => std::slice::from_ref(err),
48 }
49 }
50
51 pub fn ok(self) -> Result<T, EMLError> {
54 self.into()
55 }
56
57 pub fn ok_with_errors(self) -> Result<(T, Vec<EMLError>), EMLError> {
60 self.into()
61 }
62
63 pub fn unwrap(self) -> T {
65 self.ok().unwrap()
66 }
67
68 pub fn expect(self, msg: &str) -> T {
70 self.ok().expect(msg)
71 }
72}
73
74impl<T> From<EMLReadResult<T>> for Result<T, EMLError> {
75 fn from(value: EMLReadResult<T>) -> Self {
76 match value {
77 EMLReadResult::Ok(doc, _) => Ok(doc),
78 EMLReadResult::Err(e) => Err(e),
79 }
80 }
81}
82
83impl<T> From<EMLReadResult<T>> for Result<(T, Vec<EMLError>), EMLError> {
84 fn from(value: EMLReadResult<T>) -> Self {
85 match value {
86 EMLReadResult::Ok(doc, errors) => Ok((doc, errors)),
87 EMLReadResult::Err(e) => Err(e),
88 }
89 }
90}
91
92impl<T> EMLRead for T
93where
94 T: EMLReadElement + 'static,
95{
96 fn parse_eml(input: &str, parsing_mode: EMLParsingMode) -> EMLReadResult<Self>
97 where
98 Self: Sized + 'static,
99 {
100 let mut reader = EMLReader::init_from_str(input, parsing_mode);
101 let res = reader.with_next_element(|r| T::read_eml_element(r));
102
103 let e = match res {
104 Ok(doc) => return EMLReadResult::Ok(doc, reader.errors),
105 Err(e) => e,
106 };
107
108 if reader.errors.is_empty() {
109 EMLReadResult::Err(e)
110 } else {
111 EMLReadResult::Err(EMLError::from_vec_with_additional(reader.errors, e))
112 }
113 }
114}
115
116pub(crate) trait EMLReadElement {
118 fn read_eml_element<'a, 'b>(elem: &mut EMLElementReader<'a, 'b>) -> Result<Self, EMLError>
119 where
120 Self: Sized + 'static;
121}
122
123#[derive(Debug, Clone, Copy, PartialEq, Eq)]
125pub struct Span {
126 pub start: u64,
128 pub end: u64,
130}
131
132impl Span {
133 pub fn new(start: u64, end: u64) -> Span {
135 Span { start, end }
136 }
137}
138
139impl std::fmt::Display for Span {
140 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141 write!(f, "{} until {}", self.start, self.end)
142 }
143}
144
145#[derive(Debug, Clone, Copy, PartialEq, Eq)]
156pub enum EMLParsingMode {
157 Strict,
159
160 StrictFallback,
164
165 Loose,
167}
168
169impl EMLParsingMode {
170 pub fn is_strict(&self) -> bool {
172 matches!(self, EMLParsingMode::Strict)
173 }
174}
175
176pub(crate) struct EMLReader<'a> {
181 inner: NsReader<&'a [u8]>,
182 xml_version: XmlVersion,
183 parsing_mode: EMLParsingMode,
184 errors: Vec<EMLError>,
185}
186
187impl<'a> EMLReader<'a> {
188 pub fn init_from_str(data: &'a str, parsing_mode: EMLParsingMode) -> EMLReader<'a> {
190 Self::from_reader(NsReader::from_str(data), parsing_mode)
191 }
192
193 pub fn from_reader(reader: NsReader<&'a [u8]>, parsing_mode: EMLParsingMode) -> EMLReader<'a> {
194 EMLReader {
195 inner: reader,
196 xml_version: XmlVersion::default(),
197 parsing_mode,
198 errors: Vec::new(),
199 }
200 }
201
202 fn next(&mut self) -> Result<(Event<'a>, Span), EMLError> {
203 let span_start = self.inner.buffer_position();
204 let event = self.inner.read_event();
205 let event = match event {
206 Ok(evt) => evt,
207 Err(xml_err) => {
208 let error_pos = self.inner.error_position();
209 if error_pos == 0 {
210 return Err(xml_err)
215 .with_span(Span::new(span_start, self.inner.buffer_position()));
216 } else {
217 return Err(xml_err).with_span(Span::new(error_pos, error_pos));
218 }
219 }
220 };
221 let span = Span::new(span_start, self.inner.buffer_position());
222
223 if let Event::Decl(d) = &event {
225 self.xml_version = d.xml_version().with_span(span)?;
226 }
227
228 Ok((event, span))
229 }
230
231 pub fn next_element<'tmp>(&'tmp mut self) -> Result<EMLElementReader<'tmp, 'a>, EMLError> {
232 loop {
233 match self.next()? {
234 (Event::Start(start), span) => {
235 return Ok(EMLElementReader::from_start(self, start, false, span));
236 }
237 (Event::Empty(start), span) => {
238 return Ok(EMLElementReader::from_start(self, start, true, span));
239 }
240 (Event::Eof, span) => {
241 return Err(EMLErrorKind::UnexpectedEof).with_span(span);
242 }
243 _other => {
244 }
246 }
247 }
248 }
249
250 pub fn with_next_element<R>(
251 &mut self,
252 f: impl for<'d, 'e> FnOnce(&mut EMLElementReader<'d, 'e>) -> Result<R, EMLError>,
253 ) -> Result<R, EMLError> {
254 let mut root = self.next_element()?;
255 f(&mut root)
256 }
257}
258
259pub(crate) struct EMLElementReader<'r, 'input> {
265 reader: &'r mut EMLReader<'input>,
266 start: BytesStart<'input>,
267 depth: usize,
268 found_matching_end: bool,
269 is_empty: bool,
270 span: Span,
271 last_span: Span,
272}
273
274impl<'r, 'input> EMLElementReader<'r, 'input> {
275 pub fn from_start(
282 reader: &'r mut EMLReader<'input>,
283 start: BytesStart<'input>,
284 is_empty: bool,
285 span: Span,
286 ) -> EMLElementReader<'r, 'input> {
287 EMLElementReader {
288 reader,
289 start,
290 depth: 1,
291 found_matching_end: is_empty,
292 is_empty,
293 span,
294 last_span: span,
295 }
296 }
297
298 pub fn name(&self) -> Result<QualifiedName<'_, '_>, EMLError> {
301 self.get_resolved_name(self.start.name(), self.span, false)
302 }
303
304 pub fn has_name<'a, 'b>(
306 &self,
307 name: impl Into<QualifiedName<'a, 'b>>,
308 ) -> Result<bool, EMLError> {
309 self.is_resolved_name(self.start.name(), self.span, name, false)
310 }
311
312 pub fn next_child(&mut self) -> Result<Option<EMLElementReader<'_, 'input>>, EMLError> {
317 loop {
318 match self.next()? {
319 Some((Event::Start(start), span)) => {
320 self.depth -= 1; return Ok(Some(EMLElementReader::from_start(
322 self.reader,
323 start,
324 false,
325 span,
326 )));
327 }
328 Some((Event::Empty(start), span)) => {
329 return Ok(Some(EMLElementReader::from_start(
330 self.reader,
331 start,
332 true,
333 span,
334 )));
335 }
336 None => return Ok(None),
337 _other => {
338 }
340 }
341 }
342 }
343
344 pub fn attribute_value_req<'a, 'b>(
347 &self,
348 name: impl Into<QualifiedName<'a, 'b>>,
349 ) -> Result<Cow<'_, str>, EMLError> {
350 let name = name.into();
351 self.attribute_value(name.clone())?
352 .ok_or_else(|| EMLErrorKind::MissingAttribute(name.as_owned()))
353 .with_span(self.span)
354 }
355
356 pub fn attribute_value<'a, 'b>(
359 &self,
360 name: impl Into<QualifiedName<'a, 'b>>,
361 ) -> Result<Option<Cow<'_, str>>, EMLError> {
362 let name = name.into();
363 for attr in self.start.attributes() {
365 let attr = attr.with_span(self.span)?;
366 if self.is_resolved_name(attr.key, self.span, name.clone(), true)? {
367 return Ok(Some(
368 attr.decoded_and_normalized_value(
369 self.reader.xml_version,
370 self.reader.inner.decoder(),
371 )
372 .with_span(self.span)?,
373 ));
374 }
375 }
376 Ok(None)
377 }
378
379 #[expect(unused)]
381 pub fn attributes(&self) -> Result<HashMap<QualifiedName<'_, '_>, Cow<'_, str>>, EMLError> {
382 let mut attributes = HashMap::new();
383 for attr in self.start.attributes() {
385 let attr = attr.with_span(self.span)?;
386 let name = self.get_resolved_name(attr.key, self.span, true)?;
387 let value = attr
388 .decoded_and_normalized_value(self.reader.xml_version, self.reader.inner.decoder())
389 .with_span(self.span)?;
390 attributes.insert(name, value);
391 }
392 Ok(attributes)
393 }
394
395 pub fn text_without_children_opt(&mut self) -> Result<Option<Box<str>>, EMLError> {
398 if self.is_empty {
399 Ok(None)
400 } else {
401 let text = self.text_without_children()?;
402 if text.is_empty() {
403 Ok(None)
404 } else {
405 Ok(Some(text))
406 }
407 }
408 }
409
410 pub fn text_without_children(&mut self) -> Result<Box<str>, EMLError> {
414 let mut text = String::new();
415 loop {
416 match self.next()? {
417 Some((Event::Text(t), span)) => {
418 let decoded = t.xml_content(self.reader.xml_version).with_span(span)?;
419 text.push_str(decoded.as_ref());
420 }
421 Some((Event::CData(t), span)) => {
422 let decoded = t.xml_content(self.reader.xml_version).with_span(span)?;
423 text.push_str(decoded.as_ref());
424 }
425 Some((Event::GeneralRef(r), span)) => {
426 let ref_name = r.decode().with_span(span)?;
427 let formatted_entity = format!("&{};", ref_name);
428
429 text.push_str(unescape(&formatted_entity).with_span(span)?.as_ref());
430 }
431 Some((Event::Comment(_), _)) => {
432 }
434 None => break,
435 Some((_other, span)) => {
436 return Err(EMLErrorKind::UnexpectedEvent).with_span(span);
437 }
438 }
439 }
440 Ok(text.into())
441 }
442
443 pub fn skip(&mut self) -> Result<(), EMLError> {
446 while let Some(_evt) = self.next()? {
447 }
449 Ok(())
450 }
451
452 pub fn span(&self) -> Span {
454 self.span
455 }
456
457 pub fn last_span(&self) -> Span {
459 self.last_span
460 }
461
462 pub fn full_span(&self) -> Span {
466 Span::new(self.span.start, self.last_span.end)
467 }
468
469 pub fn inner_span(&self) -> Span {
474 Span::new(self.span.end, self.last_span.start)
475 }
476
477 pub fn parsing_mode(&self) -> EMLParsingMode {
479 self.reader.parsing_mode
480 }
481
482 pub fn push_err(&mut self, err: EMLError) {
484 if let EMLError::Multiple(MultipleEMLErrors { errors }) = err {
485 self.reader.errors.extend(errors);
486 } else {
487 self.reader.errors.push(err);
488 }
489 }
490
491 fn map_value_error<'a, 'b, T: StringValueData>(
493 &self,
494 parsing_error: Result<StringValue<T>, T::Error>,
495 name: QualifiedName<'a, 'b>,
496 span: Span,
497 ) -> Result<StringValue<T>, EMLError> {
498 parsing_error.map_err(|e| EMLError::invalid_value(name.as_owned(), e, Some(span)))
499 }
500
501 pub(crate) fn string_value_from_text<'a, 'b, T: StringValueData>(
505 &mut self,
506 text: Box<str>,
507 name: Option<QualifiedName<'a, 'b>>,
508 span: Span,
509 ) -> Result<StringValue<T>, EMLError> {
510 let name = name.map_or_else(|| self.name(), Ok)?;
511 match self.parsing_mode() {
512 EMLParsingMode::Strict => {
513 self.map_value_error(StringValue::<T>::from_raw_parsed(&text), name, span)
514 }
515 EMLParsingMode::StrictFallback => {
516 match self.map_value_error(StringValue::<T>::from_raw_parsed(&text), name, span) {
517 Ok(v) => Ok(v),
518 Err(e) => {
519 self.push_err(e);
520 Ok(StringValue::<T>::Raw(text))
521 }
522 }
523 }
524 EMLParsingMode::Loose => Ok(StringValue::Raw(text)),
525 }
526 }
527
528 pub fn string_value<T: StringValueData>(&mut self) -> Result<StringValue<T>, EMLError> {
537 let text = self.text_without_children()?;
538 self.string_value_from_text(text, None, self.inner_span())
539 }
540
541 pub fn string_value_opt<T: StringValueData>(
551 &mut self,
552 ) -> Result<Option<StringValue<T>>, EMLError> {
553 self.text_without_children_opt()?
554 .map(|v| self.string_value_from_text(v, None, self.inner_span()))
555 .transpose()
556 }
557
558 pub fn string_value_attr_opt<'a, 'b, T: StringValueData>(
564 &mut self,
565 attr_name: impl Into<QualifiedName<'a, 'b>>,
566 ) -> Result<Option<StringValue<T>>, EMLError> {
567 let attr_name = attr_name.into();
568 match self.attribute_value(attr_name.clone())? {
569 Some(value) => Ok(Some(self.string_value_from_text(
570 value.into(),
571 Some(attr_name),
572 self.span(),
573 )?)),
574 None => Ok(None),
575 }
576 }
577
578 pub fn string_value_attr<'a, 'b, T: StringValueData>(
584 &mut self,
585 attr_name: impl Into<QualifiedName<'a, 'b>>,
586 default_value: Option<&str>,
587 ) -> Result<StringValue<T>, EMLError> {
588 let attr_name = attr_name.into();
589 let value = self
590 .attribute_value(attr_name.clone())?
591 .or_else(|| default_value.map(Cow::Borrowed));
592 match value {
593 Some(value) => self.string_value_from_text(value.into(), Some(attr_name), self.span()),
594 None => {
595 Err(EMLErrorKind::MissingAttribute(attr_name.as_owned())).with_span(self.span())
596 }
597 }
598 }
599
600 fn namespace_name<'a>(
602 &self,
603 resolve_result: ResolveResult<'a>,
604 span: Span,
605 ) -> Result<Option<Cow<'a, str>>, EMLError> {
606 match resolve_result {
607 ResolveResult::Bound(namespace) => Ok(Some(
608 self.reader
609 .inner
610 .decoder()
611 .decode(namespace.into_inner())
612 .with_span(span)?,
613 )),
614 ResolveResult::Unbound => Ok(None),
615 ResolveResult::Unknown(scope) => Err(EMLErrorKind::UnknownNamespace(
616 self.reader
617 .inner
618 .decoder()
619 .decode(&scope)
620 .with_span(span)?
621 .into_owned(),
622 ))
623 .with_span(span),
624 }
625 }
626
627 fn is_resolved_name<'a, 'b, 'c>(
630 &self,
631 name: QName<'a>,
632 span: Span,
633 expected_name: impl Into<QualifiedName<'b, 'c>>,
634 is_attribute: bool,
635 ) -> Result<bool, EMLError> {
636 let expected_name = expected_name.into();
637 let resolved_name = self.get_resolved_name(name, span, is_attribute)?;
638 let matches_local = resolved_name.local_name.as_ref() == expected_name.local_name.as_ref();
639 let matches_namespace = match (
640 expected_name.namespace.as_deref(),
641 resolved_name.namespace.as_deref(),
642 ) {
643 (Some(expected), Some(found)) => expected == found,
644 (None, None) => true,
645 _ => false,
646 };
647 Ok(matches_local && matches_namespace)
648 }
649
650 fn get_resolved_name<'a>(
654 &'a self,
655 name: QName<'a>,
656 span: Span,
657 is_attribute: bool,
658 ) -> Result<QualifiedName<'a, 'a>, EMLError> {
659 let (resolved, local_name) = if is_attribute {
660 self.reader.inner.resolver().resolve_attribute(name)
661 } else {
662 self.reader.inner.resolver().resolve_element(name)
663 };
664 let namespace = self.namespace_name(resolved, span)?;
665 let local_name = self
666 .reader
667 .inner
668 .decoder()
669 .decode(local_name.into_inner())
670 .with_span(span)?;
671
672 Ok(QualifiedName::new(local_name, namespace))
673 }
674
675 fn next(&mut self) -> Result<Option<(Event<'input>, Span)>, EMLError> {
678 if self.found_matching_end {
679 return Ok(None);
680 }
681
682 let (evt, span) = self.reader.next()?;
683 self.last_span = span;
684 if matches!(evt, Event::Start(_)) {
685 self.depth += 1;
686 }
687
688 if matches!(evt, Event::End(_)) {
689 self.depth -= 1;
690 }
691
692 if matches!(evt, Event::Eof) {
693 return Err(EMLErrorKind::UnexpectedEof).with_span(span);
694 }
695
696 if self.depth == 0
697 && let Event::End(e) = &evt
698 {
699 if e.name() == self.start.name() {
700 self.found_matching_end = true;
701 return Ok(None);
702 } else {
703 return Err(EMLErrorKind::UnexpectedEndElement).with_span(span);
704 }
705 }
706
707 Ok(Some((evt, span)))
708 }
709
710 pub fn is_empty(&self) -> bool {
712 self.is_empty
713 }
714}
715
716impl Drop for EMLElementReader<'_, '_> {
717 fn drop(&mut self) {
718 let _ = self.skip();
720 }
721}
722
723macro_rules! collect_struct {
724 ( $root:expr, $ty:ident { $($rest:tt)* }) => {
741 collect_struct!(@expand [$root] [$ty] [] $($rest)* )
742 };
743
744 ( @expand [$root:expr] [$ty:ident] [$($items:tt ; )*]
746 $field:ident: $namespaced_name:expr => |$var:ident| $map:expr ,
747 $($tail:tt)*
748 ) => {
749 collect_struct!(@expand [$root] [$ty] [
750 $($items ; )*
751 (@field [$field] [$namespaced_name] [$var] [$map]) ;
752 ] $($tail)*)
753 };
754
755 ( @expand [$root:expr] [$ty:ident] [$($items:tt ; )*]
757 $field:ident as None: $namespaced_name:expr => |$var:ident| $map:expr ,
758 $($tail:tt)*
759 ) => {
760 collect_struct!(@expand [$root] [$ty] [
761 $($items ; )*
762 (@parse_only [$field] [$namespaced_name] [$var] [$map]) ;
763 ] $($tail)*)
764 };
765
766 ( @expand [$root:expr] [$ty:ident] [$($items:tt ; )*]
768 $field:ident as Option: $namespaced_name:expr => |$var:ident| $map:expr ,
769 $($tail:tt)*
770 ) => {
771 collect_struct!(@expand [$root] [$ty] [
772 $($items ; )*
773 (@optional [$field] [$namespaced_name] [$var] [$map]) ;
774 ] $($tail)*)
775 };
776
777 ( @expand [$root:expr] [$ty:ident] [$($items:tt ; )*]
779 $field:ident as BTreeMap: $namespaced_name:expr => |$var:ident| $map:expr,
780 $($tail:tt)*
781 ) => {
782 collect_struct!(@expand [$root] [$ty] [
783 $($items ; )*
784 (@btreemap [$field] [$namespaced_name] [$var] [$map]) ;
785 ] $($tail)*)
786 };
787
788 ( @expand [$root:expr] [$ty:ident] [$($items:tt ; )*]
790 $field:ident as Vec: $namespaced_name:expr => |$var:ident| $map:expr ,
791 $($tail:tt)*
792 ) => {
793 collect_struct!(@expand [$root] [$ty] [
794 $($items ; )*
795 (@vec [$field] [$namespaced_name] [$var] [$map]) ;
796 ] $($tail)*)
797 };
798
799 ( @expand [$root:expr] [$ty:ident] [$($items:tt ; )*]
801 $field:ident: $value:expr ,
802 $($tail:tt)*
803 ) => {
804 collect_struct!(@expand [$root] [$ty] [
805 $($items ; )*
806 (@direct [$field] [$value]) ;
807 ] $($tail)*)
808 };
809
810 ( @expand [$root:expr] [$ty:ident] [$($items:tt ; )*] ) => {
812 collect_struct!(@emit [$root] [$ty] [$($items ; )*])
813 };
814
815 ( @emit [$root:expr] [$ty:ident] [$($items:tt ; )*] ) => {{
817 $( collect_struct!(@decl $items); )*
818
819 let elem_name = $root.name()?.as_owned();
820 while let Some(mut next_child) = $root.next_child()? {
821 let name = next_child.name()?.as_owned().into_inner();
822 #[allow(unused_mut)]
823 let mut handled = false;
824
825 $( collect_struct!(@matcher next_child, name, handled, $items); )*
826
827 if !handled {
828 next_child.push_err($crate::error::EMLError::Positioned {
829 kind: $crate::error::EMLErrorKind::UnexpectedElement(name.as_owned(), elem_name.clone()),
830 span: next_child.span(),
831 });
832 next_child.skip()?;
834 }
835 }
836
837 $( collect_struct!(@process $root, $items); )*
838
839 collect_struct!(@assign $root, $ty, [], $($items ; )*)
840 }};
841
842 (@decl (@parse_only [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {
844 let mut $field: Option<_> = None;
845 };
846 (@decl (@direct [$field:ident] [$value:expr])) => {};
847 (@decl (@optional [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {
848 let mut $field: Option<_> = None;
849 };
850 (@decl (@btreemap [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {
851 let mut $field: std::collections::BTreeMap<_, _> = std::collections::BTreeMap::new();
852 };
853 (@decl (@field [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {
854 let mut $field: Option<_> = None;
855 };
856 (@decl (@vec [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {
857 let mut $field: Vec<_> = Vec::new();
858 };
859
860 (@matcher $next_child:ident, $name:ident, $handled:ident, (@direct [$field:ident] [$value:expr])) => {};
862 (@matcher $next_child:ident, $name:ident, $handled:ident, (@optional [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {
863 collect_struct!(@matcher $next_child, $name, $handled, (@field [$field] [$namespaced_name] [$var] [$map]));
864 };
865 (@matcher $next_child:ident, $name:ident, $handled:ident, (@parse_only [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {
866 collect_struct!(@matcher $next_child, $name, $handled, (@field [$field] [$namespaced_name] [$var] [$map]));
867 };
868 (@matcher $next_child:ident, $name:ident, $handled:ident, (@field [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {
869 if !$handled &&
870 &$name == $crate::io::IntoQualifiedNameCow::into_qname_cow($namespaced_name).as_ref()
871 {
872 let $var = &mut $next_child;
873 $field = Some($map);
874 $var.skip()?;
875 $handled = true;
876 }
877 };
878 (@matcher $next_child:ident, $name:ident, $handled:ident, (@vec [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {
879 if !$handled &&
880 &$name == $crate::io::IntoQualifiedNameCow::into_qname_cow($namespaced_name).as_ref()
881 {
882 let $var = &mut $next_child;
883 $field.push($map);
884 $var.skip()?;
885 $handled = true;
886 }
887 };
888 (@matcher $next_child:ident, $name:ident, $handled:ident, (@btreemap [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {
889 if !$handled &&
890 &$name == $crate::io::IntoQualifiedNameCow::into_qname_cow($namespaced_name).as_ref()
891 {
892 let $var = &mut $next_child;
893 let (k, v) = $map;
894 $field.insert(k, v);
895 $var.skip()?;
896 $handled = true;
897 }
898 };
899
900 (@process $root:expr, (@parse_only [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {
902 $crate::error::EMLResultExt::with_span(
903 $field.ok_or_else(|| $crate::error::EMLErrorKind::MissingElement(
904 $crate::io::QualifiedName::from($namespaced_name).as_owned()
905 )),
906 $root.last_span()
907 )?;
908 };
909 (@process $root:expr, (@direct [$field:ident] [$value:expr])) => {};
910 (@process $root:expr, (@optional [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {};
911 (@process $root:expr, (@btreemap [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {};
912 (@process $root:expr, (@field [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {};
913 (@process $root:expr, (@vec [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr])) => {};
914
915 (@build_struct $root:expr, $ty:ident, $($items:tt ; )* ) => {
917 $ty {
918 collect_struct!(@assign $root, $($items ; )*)
919 }
920 };
921
922 (@assign $root:expr, $ty:ident, [$($out:tt)*], (@direct [$field:ident] [$value:expr]) ; $($tail:tt)*) => {
924 collect_struct!(@assign $root, $ty, [
925 $($out)*
926 $field: $value,
927 ], $($tail)*)
928 };
929 (@assign $root:expr, $ty:ident, [$($out:tt)*], (@parse_only [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr]) ; $($tail:tt)*) => {
930 collect_struct!(@assign $root, $ty, [
931 $($out)*
932 ], $($tail)*)
933 };
934 (@assign $root:expr, $ty:ident, [$($out:tt)*], (@optional [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr]) ; $($tail:tt)*) => {
935 collect_struct!(@assign $root, $ty, [
936 $($out)*
937 $field: $field,
938 ], $($tail)*)
939 };
940 (@assign $root:expr, $ty:ident, [$($out:tt)*], (@vec [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr]) ; $($tail:tt)*) => {
941 collect_struct!(@assign $root, $ty, [
942 $($out)*
943 $field: $field,
944 ], $($tail)*)
945 };
946 (@assign $root:expr, $ty:ident, [$($out:tt)*], (@btreemap [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr]) ; $($tail:tt)*) => {
947 collect_struct!(@assign $root, $ty, [
948 $($out)*
949 $field: $field,
950 ], $($tail)*)
951 };
952 (@assign $root:expr, $ty:ident, [$($out:tt)*], (@field [$field:ident] [$namespaced_name:expr] [$var:ident] [$map:expr]) ; $($tail:tt)*) => {
953 collect_struct!(@assign $root, $ty, [
954 $($out)*
955 $field: $crate::error::EMLResultExt::with_span(
956 $field.ok_or_else(|| $crate::error::EMLErrorKind::MissingElement(
957 $crate::io::QualifiedName::from($namespaced_name).as_owned()
958 )),
959 $root.last_span()
960 )?,
961 ], $($tail)*)
962 };
963 (@assign $root:expr, $ty:ident, [$($out:tt)*], ) => {
964 $ty {
965 $($out)*
966 }
967 };
968}
969pub(crate) use collect_struct;
970
971#[cfg(test)]
972mod tests {
973 use super::*;
974
975 #[test]
976 fn test_unknown_namespace() {
977 let document = r#"<eml:UnknownElement />"#;
978 let mut reader = EMLReader::init_from_str(document, EMLParsingMode::Strict);
979 let root = reader.next_element().unwrap();
980 let error = root.name().unwrap_err();
981 assert!(matches!(
982 error.kind(),
983 EMLErrorKind::UnknownNamespace(ns) if ns == "eml"
984 ));
985 }
986
987 #[test]
990 fn test_input_without_element_returns_unexpected_eof() {
991 for document in [
992 "",
993 "5738 d520 a7f2 89b8 8875 ebfe cfc8 6012 d7b6 f65f 3271 d0e1 180b ccdd 8134 cd5d\n",
994 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
995 ] {
996 let mut reader = EMLReader::init_from_str(document, EMLParsingMode::Strict);
997 let Err(error) = reader.next_element() else {
998 panic!("expected an error for input {document:?}");
999 };
1000 assert!(matches!(error.kind(), EMLErrorKind::UnexpectedEof));
1001 }
1002 }
1003}