1/*!
2# Error types for XML parsing
3
4This module contains the error types used throughout the `xso` crate.
5*/
6
7// Copyright (c) 2024 Jonas Schäfer <jonas@zombofant.net>
8//
9// This Source Code Form is subject to the terms of the Mozilla Public
10// License, v. 2.0. If a copy of the MPL was not distributed with this
11// file, You can obtain one at http://mozilla.org/MPL/2.0/.
12use core::fmt;
13
14use rxml::error::XmlError;
15
16/// Error variants generated while parsing or serialising XML data.
17#[derive(Debug)]
18pub enum Error {
19 /// Invalid XML data encountered
20 XmlError(XmlError),
21
22 /// Attempt to parse text data failed with the provided nested error.
23 TextParseError(Box<dyn std::error::Error + Send + Sync + 'static>),
24
25 /// Generic, unspecified other error.
26 Other(Box<str>),
27
28 /// An element header did not match an expected element.
29 ///
30 /// This is only rarely generated: most of the time, a mismatch of element
31 /// types is reported as either an unexpected or a missing child element,
32 /// errors which are generally more specific.
33 TypeMismatch,
34}
35
36impl fmt::Display for Error {
37 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38 match self {
39 Self::XmlError(ref e) => write!(f, "xml parse error: {}", e),
40 Self::TextParseError(ref e) => write!(f, "text parse error: {}", e),
41 Self::TypeMismatch => f.write_str("mismatch between expected and actual XML data"),
42 Self::Other(msg) => f.write_str(msg),
43 }
44 }
45}
46
47impl std::error::Error for Error {
48 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
49 match self {
50 Self::XmlError(ref e) => Some(e),
51 Self::TextParseError(ref e) => Some(&**e),
52 _ => None,
53 }
54 }
55}
56
57impl From<rxml::error::XmlError> for Error {
58 fn from(other: rxml::error::XmlError) -> Error {
59 Error::XmlError(other)
60 }
61}
62
63impl From<rxml::strings::Error> for Error {
64 fn from(other: rxml::strings::Error) -> Error {
65 Error::XmlError(other.into())
66 }
67}
68
69impl From<core::convert::Infallible> for Error {
70 fn from(other: core::convert::Infallible) -> Self {
71 match other {}
72 }
73}
74
75/// Error returned from
76/// [`FromXml::from_events`][`crate::FromXml::from_events`].
77#[derive(Debug)]
78pub enum FromEventsError {
79 /// The `name` and/or `attrs` passed to `FromXml::from_events` did not
80 /// match the element's type.
81 Mismatch {
82 /// The `name` passed to `from_events`.
83 name: rxml::QName,
84
85 /// The `attrs` passed to `from_events`.
86 attrs: rxml::AttrMap,
87 },
88
89 /// The `name` and `attrs` passed to `FromXml::from_events` matched the
90 /// element's type, but the data was invalid. Details are in the inner
91 /// error.
92 Invalid(Error),
93}
94
95impl From<Error> for FromEventsError {
96 fn from(other: Error) -> Self {
97 Self::Invalid(other)
98 }
99}
100
101impl From<core::convert::Infallible> for FromEventsError {
102 fn from(other: core::convert::Infallible) -> Self {
103 match other {}
104 }
105}
106
107impl fmt::Display for FromEventsError {
108 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109 match self {
110 Self::Mismatch { .. } => f.write_str("element header did not match"),
111 Self::Invalid(ref e) => fmt::Display::fmt(e, f),
112 }
113 }
114}
115
116impl std::error::Error for FromEventsError {
117 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
118 match self {
119 Self::Mismatch { .. } => None,
120 Self::Invalid(ref e) => Some(e),
121 }
122 }
123}