xsd_parser/quick_xml/
error.rsuse std::error::Error as StdError;
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
use std::mem::take;
use std::str::Utf8Error;
use quick_xml::events::attributes::AttrError;
use quick_xml::{events::Event, Error as XmlError};
use thiserror::Error;
use crate::misc::RawByteStr;
#[derive(Debug)]
pub struct Error {
pub kind: Kind,
pub position: Option<u64>,
pub elements: Option<Vec<String>>,
}
#[derive(Debug, Error)]
pub enum Kind {
#[error("XML Error: message={0}")]
XmlError(#[from] XmlError),
#[error("Attribute Error: message={0}")]
AttrError(#[from] AttrError),
#[error("UTF-8 Error: message={0}")]
InvalidUtf8(#[from] Utf8Error),
#[error("Duplicated attribute: name={0}")]
DuplicateAttribute(RawByteStr),
#[error("Duplicated element: name={0}")]
DuplicateElement(RawByteStr),
#[error("Unexpected attribute: name={0}")]
UnexpectedAttribute(RawByteStr),
#[error("Missing attribute: name={0}")]
MissingAttribute(RawByteStr),
#[error("Missing element: name={0}")]
MissingElement(RawByteStr),
#[error("Invalid data: `{0}`")]
InvalidData(RawByteStr),
#[error("Missing content")]
MissingContent,
#[error("Missing name")]
MissingName,
#[error("Unknown or invalid value: {0}")]
UnknownOrInvalidValue(RawByteStr),
#[error("Insufficient size (min={min}, max={max}, actual={actual})")]
InsufficientSize {
min: usize,
max: usize,
actual: usize,
},
#[error("Invalid union: {0}")]
InvalidUnion(UnionError),
#[error("Custom Error: message={0}")]
Custom(Box<dyn StdError + Send + Sync>),
#[error("Unexpected event: {0:#?}!")]
UnexpectedEvent(Event<'static>),
#[error("Unexpected EoF!")]
UnexpectedEof,
}
impl Error {
pub fn custom<E: StdError + Send + Sync + 'static>(error: E) -> Self {
Kind::Custom(Box::new(error)).into()
}
pub(super) fn new<E>(error: E) -> Self
where
Kind: From<E>,
{
Self {
kind: Kind::from(error),
position: None,
elements: None,
}
}
pub(super) fn with_pos(mut self, position: u64) -> Self {
self.position = Some(position);
self
}
pub(super) fn with_error_info(mut self, info: &ErrorInfo) -> Self {
self.elements = Some(info.elements.clone());
self
}
}
impl<E> From<E> for Error
where
Kind: From<E>,
{
fn from(error: E) -> Self {
Self::new(error)
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "{}", &self.kind)?;
if let Some(pos) = &self.position {
write!(f, "; position={}", pos)?;
}
if let Some(elements) = &self.elements {
let mut first = true;
for element in elements {
if take(&mut first) {
write!(f, "; element={}", element)?;
} else {
write!(f, ">{}", element)?;
}
}
}
Ok(())
}
}
impl StdError for Error {}
pub struct UnionError(Vec<Box<dyn StdError + Send + Sync + 'static>>);
impl<X> From<X> for UnionError
where
X: IntoIterator,
X::Item: StdError + Send + Sync + 'static,
{
fn from(value: X) -> Self {
Self(
value
.into_iter()
.map(|err| -> Box<dyn StdError + Send + Sync + 'static> { Box::new(err) })
.collect(),
)
}
}
impl Debug for UnionError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
for err in &self.0 {
write!(f, "- {err}")?;
}
Ok(())
}
}
impl Display for UnionError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
for err in &self.0 {
write!(f, "- {err}")?;
}
Ok(())
}
}
#[derive(Default, Debug)]
pub(super) struct ErrorInfo {
elements: Vec<String>,
}
impl ErrorInfo {
pub(super) fn update(&mut self, event: &Event<'_>) {
match event {
Event::Start(x) => {
self.elements
.push(String::from_utf8_lossy(x.name().0).to_string());
}
Event::End(_) => {
self.elements.pop();
}
_ => (),
}
}
}