error.rs

  1// Copyright (c) 2017-2018 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
  2//
  3// This Source Code Form is subject to the terms of the Mozilla Public
  4// License, v. 2.0. If a copy of the MPL was not distributed with this
  5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6
  7use std::error::Error as StdError;
  8use std::fmt;
  9
 10/// Contains one of the potential errors triggered while parsing an
 11/// [Element](../struct.Element.html) into a specialised struct.
 12#[derive(Debug)]
 13pub enum Error {
 14    /// The usual error when parsing something.
 15    ///
 16    /// TODO: use a structured error so the user can report it better, instead
 17    /// of a freeform string.
 18    ParseError(&'static str),
 19
 20    /// Element local-name/namespace mismatch
 21    ///
 22    /// Returns the original element unaltered, as well as the expected ns and
 23    /// local-name.
 24    TypeMismatch(&'static str, &'static str, crate::Element),
 25
 26    /// Generated when some base64 content fails to decode, usually due to
 27    /// extra characters.
 28    Base64Error(base64::DecodeError),
 29
 30    /// Generated when text which should be an integer fails to parse.
 31    ParseIntError(std::num::ParseIntError),
 32
 33    /// Generated when text which should be a string fails to parse.
 34    ParseStringError(std::string::ParseError),
 35
 36    /// Generated when text which should be an IP address (IPv4 or IPv6) fails
 37    /// to parse.
 38    ParseAddrError(std::net::AddrParseError),
 39
 40    /// Generated when text which should be a [JID](../../jid/struct.Jid.html)
 41    /// fails to parse.
 42    JidParseError(jid::Error),
 43
 44    /// Generated when text which should be a
 45    /// [DateTime](../date/struct.DateTime.html) fails to parse.
 46    ChronoParseError(chrono::ParseError),
 47}
 48
 49impl Error {
 50    /// Converts the TypeMismatch error to a generic ParseError
 51    ///
 52    /// This must be used when TryFrom is called on children to avoid confusing
 53    /// user code which assumes that TypeMismatch refers to the top level
 54    /// element only.
 55    pub(crate) fn hide_type_mismatch(self) -> Self {
 56        match self {
 57            Error::TypeMismatch(..) => Error::ParseError("Unexpected child element"),
 58            other => other,
 59        }
 60    }
 61}
 62
 63impl StdError for Error {
 64    fn cause(&self) -> Option<&dyn StdError> {
 65        match self {
 66            Error::ParseError(_) | Error::TypeMismatch(..) => None,
 67            Error::Base64Error(e) => Some(e),
 68            Error::ParseIntError(e) => Some(e),
 69            Error::ParseStringError(e) => Some(e),
 70            Error::ParseAddrError(e) => Some(e),
 71            Error::JidParseError(e) => Some(e),
 72            Error::ChronoParseError(e) => Some(e),
 73        }
 74    }
 75}
 76
 77impl fmt::Display for Error {
 78    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 79        match self {
 80            Error::ParseError(s) => write!(fmt, "parse error: {}", s),
 81            Error::TypeMismatch(ns, localname, element) => write!(
 82                fmt,
 83                "element type mismatch: expected {{{}}}{}, got {{{}}}{}",
 84                ns,
 85                localname,
 86                element.ns(),
 87                element.name()
 88            ),
 89            Error::Base64Error(e) => write!(fmt, "base64 error: {}", e),
 90            Error::ParseIntError(e) => write!(fmt, "integer parsing error: {}", e),
 91            Error::ParseStringError(e) => write!(fmt, "string parsing error: {}", e),
 92            Error::ParseAddrError(e) => write!(fmt, "IP address parsing error: {}", e),
 93            Error::JidParseError(e) => write!(fmt, "JID parsing error: {}", e),
 94            Error::ChronoParseError(e) => write!(fmt, "time parsing error: {}", e),
 95        }
 96    }
 97}
 98
 99impl From<base64::DecodeError> for Error {
100    fn from(err: base64::DecodeError) -> Error {
101        Error::Base64Error(err)
102    }
103}
104
105impl From<std::num::ParseIntError> for Error {
106    fn from(err: std::num::ParseIntError) -> Error {
107        Error::ParseIntError(err)
108    }
109}
110
111impl From<std::string::ParseError> for Error {
112    fn from(err: std::string::ParseError) -> Error {
113        Error::ParseStringError(err)
114    }
115}
116
117impl From<std::net::AddrParseError> for Error {
118    fn from(err: std::net::AddrParseError) -> Error {
119        Error::ParseAddrError(err)
120    }
121}
122
123impl From<jid::Error> for Error {
124    fn from(err: jid::Error) -> Error {
125        Error::JidParseError(err)
126    }
127}
128
129impl From<chrono::ParseError> for Error {
130    fn from(err: chrono::ParseError) -> Error {
131        Error::ChronoParseError(err)
132    }
133}