error.rs

  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}