xsd_parser/quick_xml/
error.rs1use std::error::Error as StdError;
2use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
3use std::mem::take;
4use std::str::Utf8Error;
5
6use quick_xml::events::attributes::AttrError;
7use quick_xml::{events::Event, Error as XmlError};
8use thiserror::Error;
9
10use crate::misc::RawByteStr;
11
12#[derive(Debug)]
14pub struct Error {
15 pub kind: Kind,
17
18 pub position: Option<u64>,
20
21 pub elements: Option<Vec<String>>,
23}
24
25#[derive(Debug, Error)]
27pub enum Kind {
28 #[error("XML Error: message={0}")]
30 XmlError(#[from] XmlError),
31
32 #[error("Attribute Error: message={0}")]
34 AttrError(#[from] AttrError),
35
36 #[error("UTF-8 Error: message={0}")]
38 InvalidUtf8(#[from] Utf8Error),
39
40 #[error("Duplicated attribute: name={0}")]
44 DuplicateAttribute(RawByteStr),
45
46 #[error("Duplicated element: name={0}")]
50 DuplicateElement(RawByteStr),
51
52 #[error("Unexpected attribute: name={0}")]
56 UnexpectedAttribute(RawByteStr),
57
58 #[error("Missing attribute: name={0}")]
62 MissingAttribute(RawByteStr),
63
64 #[error("Missing element: name={0}")]
68 MissingElement(RawByteStr),
69
70 #[error("Invalid data: `{0}`")]
72 InvalidData(RawByteStr),
73
74 #[error("Missing content")]
78 MissingContent,
79
80 #[error("Duplicate content")]
84 DuplicateContent,
85
86 #[error("Missing name")]
90 MissingName,
91
92 #[error("Unknown or invalid value: {0}")]
94 UnknownOrInvalidValue(RawByteStr),
95
96 #[error("Insufficient size (min={min}, max={max}, actual={actual})")]
100 InsufficientSize {
101 min: usize,
103
104 max: usize,
106
107 actual: usize,
109 },
110
111 #[error("Invalid union: {0}")]
113 InvalidUnion(UnionError),
114
115 #[error("Custom Error: message={0}")]
119 Custom(Box<dyn StdError + Send + Sync>),
120
121 #[error("Unexpected event: {0:#?}!")]
123 UnexpectedEvent(Event<'static>),
124
125 #[error("Unexpected EoF!")]
127 UnexpectedEof,
128}
129
130impl Error {
131 pub fn custom<E: StdError + Send + Sync + 'static>(error: E) -> Self {
133 Kind::Custom(Box::new(error)).into()
134 }
135
136 pub(super) fn new<E>(error: E) -> Self
137 where
138 Kind: From<E>,
139 {
140 Self {
141 kind: Kind::from(error),
142 position: None,
143 elements: None,
144 }
145 }
146
147 pub(super) fn with_pos(mut self, position: u64) -> Self {
148 self.position = Some(position);
149
150 self
151 }
152
153 pub(super) fn with_error_info(mut self, info: &ErrorInfo) -> Self {
154 self.elements = Some(info.elements.clone());
155
156 self
157 }
158}
159
160impl<E> From<E> for Error
161where
162 Kind: From<E>,
163{
164 fn from(error: E) -> Self {
165 Self::new(error)
166 }
167}
168
169impl Display for Error {
170 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
171 write!(f, "{}", &self.kind)?;
172
173 if let Some(pos) = &self.position {
174 write!(f, "; position={}", pos)?;
175 }
176
177 if let Some(elements) = &self.elements {
178 let mut first = true;
179
180 for element in elements {
181 if take(&mut first) {
182 write!(f, "; element={}", element)?;
183 } else {
184 write!(f, ">{}", element)?;
185 }
186 }
187 }
188
189 Ok(())
190 }
191}
192
193impl StdError for Error {}
194
195pub struct UnionError(Vec<Box<dyn StdError + Send + Sync + 'static>>);
197
198impl<X> From<X> for UnionError
199where
200 X: IntoIterator,
201 X::Item: StdError + Send + Sync + 'static,
202{
203 fn from(value: X) -> Self {
204 Self(
205 value
206 .into_iter()
207 .map(|err| -> Box<dyn StdError + Send + Sync + 'static> { Box::new(err) })
208 .collect(),
209 )
210 }
211}
212
213impl Debug for UnionError {
214 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
215 for err in &self.0 {
216 write!(f, "- {err}")?;
217 }
218
219 Ok(())
220 }
221}
222
223impl Display for UnionError {
224 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
225 for err in &self.0 {
226 write!(f, "- {err}")?;
227 }
228
229 Ok(())
230 }
231}
232
233#[derive(Default, Debug)]
234pub(super) struct ErrorInfo {
235 elements: Vec<String>,
236}
237
238impl ErrorInfo {
239 pub(super) fn update(&mut self, event: &Event<'_>) {
240 match event {
241 Event::Start(x) => {
242 self.elements
243 .push(String::from_utf8_lossy(x.name().0).to_string());
244 }
245 Event::End(_) => {
246 self.elements.pop();
247 }
248 _ => (),
249 }
250 }
251}