error.rs

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