diff --git a/minidom/Cargo.toml b/minidom/Cargo.toml index 0779ef1f7bb36553be38983ed328645eef98d8cb..b42f5d12644df51c4fc258a5c9d209a0b380dbd6 100644 --- a/minidom/Cargo.toml +++ b/minidom/Cargo.toml @@ -22,6 +22,7 @@ gitlab = { repository = "xmpp-rs/xmpp-rs" } [dependencies] rxml = { version = "0.13.1", default-features = false, features = ["compact_str"] } +thiserror = "2.0" [features] default = [ "std" ] diff --git a/minidom/src/error.rs b/minidom/src/error.rs index 0ac47947105715926ab6f4fa63a1b920734590bf..e0e79c1ccff4aff23eb5df1d0c983711c74276cf 100644 --- a/minidom/src/error.rs +++ b/minidom/src/error.rs @@ -13,13 +13,14 @@ use std::io; -use core::{error::Error as StdError, fmt}; +use thiserror::Error; /// Our main error type. -#[derive(Debug)] +#[derive(Debug, Error)] pub enum Error { /// Error from rxml parsing or writing - XmlError(rxml::Error), + #[error("XML error: {0}")] + XmlError(#[from] rxml::Error), /// I/O error from accessing the source or destination. /// @@ -27,35 +28,27 @@ pub enum Error { /// [`io::Error`] when using it with [`BufRead`][`io::BufRead`], /// any rxml errors will still be reported through the /// [`XmlError`][`Self::XmlError`] variant. + #[error("I/O error: {0}")] Io(io::Error), /// An error which is returned when the end of the document was reached prematurely. + #[error("the end of the document has been reached prematurely")] EndOfDocument, /// An error which is returned when an element being serialized doesn't contain a prefix /// (be it None or Some(_)). + #[error("the prefix is invalid")] InvalidPrefix, /// An error which is returned when an element doesn't contain a namespace + #[error("the XML element is missing a namespace")] MissingNamespace, /// An error which is returned when a prefixed is defined twice + #[error("the prefix is already defined")] DuplicatePrefix, } -impl StdError for Error { - fn cause(&self) -> Option<&dyn StdError> { - match self { - Error::XmlError(e) => Some(e), - Error::Io(e) => Some(e), - Error::EndOfDocument - | Error::InvalidPrefix - | Error::MissingNamespace - | Error::DuplicatePrefix => None, - } - } -} - impl From for Error { fn from(other: io::Error) -> Self { match other.downcast::() { @@ -65,27 +58,6 @@ impl From for Error { } } -impl fmt::Display for Error { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::XmlError(e) => write!(fmt, "XML error: {e}"), - Error::Io(e) => write!(fmt, "I/O error: {e}"), - Error::EndOfDocument => { - write!(fmt, "the end of the document has been reached prematurely") - } - Error::InvalidPrefix => write!(fmt, "the prefix is invalid"), - Error::MissingNamespace => write!(fmt, "the XML element is missing a namespace",), - Error::DuplicatePrefix => write!(fmt, "the prefix is already defined"), - } - } -} - -impl From for Error { - fn from(err: rxml::Error) -> Error { - Error::XmlError(err) - } -} - impl From for Error { fn from(err: rxml::strings::Error) -> Error { rxml::error::Error::from(err).into() diff --git a/tokio-xmpp/Cargo.toml b/tokio-xmpp/Cargo.toml index e27c8580a7b84739e455b9c3ae87c06cc8e87c33..b298a0a96498ed9405b24db8b6b42b76b06da694 100644 --- a/tokio-xmpp/Cargo.toml +++ b/tokio-xmpp/Cargo.toml @@ -23,6 +23,7 @@ rxml = { version = "0.13.1", features = ["compact_str"] } rand = "0.9" syntect = { version = "5", optional = true } pin-project-lite = { version = "0.2" } +thiserror = "2.0" # same repository dependencies sasl = { version = "0.5", path = "../sasl" } xmpp-parsers = { version = "0.21", path = "../parsers", features = [ "log" ] } diff --git a/tokio-xmpp/src/error.rs b/tokio-xmpp/src/error.rs index 181a1732ec377301e199a84f413abdce4cf6a317..6d68c7b65b78f075937cd32e8733ed3a32a492d8 100644 --- a/tokio-xmpp/src/error.rs +++ b/tokio-xmpp/src/error.rs @@ -1,8 +1,9 @@ -use core::{error::Error as StdError, fmt, net::AddrParseError, str::Utf8Error}; +use core::{fmt, net::AddrParseError, str::Utf8Error}; #[cfg(feature = "dns")] use hickory_resolver::{proto::ProtoError as DnsProtoError, ResolveError as DnsResolveError}; use sasl::client::MechanismError as SaslMechanismError; use std::io; +use thiserror::Error; use xmpp_parsers::stream_error::ReceivedStreamError; @@ -12,110 +13,62 @@ use crate::{ }; /// Top-level error type -#[derive(Debug)] +#[derive(Debug, Error)] pub enum Error { /// I/O error - Io(io::Error), + #[error("I/O error: {0}")] + Io(#[from] io::Error), /// Error parsing Jabber-Id - JidParse(jid::Error), + #[error("JID parse error: {0}")] + JidParse(#[from] jid::Error), /// Protocol-level error - Protocol(ProtocolError), + #[error("protocol error: {0}")] + Protocol(#[from] ProtocolError), /// Authentication error - Auth(AuthError), + #[error("authentication error: {0}")] + Auth(#[from] AuthError), /// Connection closed + #[error("disconnected")] Disconnected, /// Should never happen + #[error("invalid state")] InvalidState, /// Fmt error - Fmt(fmt::Error), + #[error("fmt error: {0}")] + Fmt(#[from] fmt::Error), /// Utf8 error - Utf8(Utf8Error), + #[error("UTF-8 error: {0}")] + Utf8(#[from] Utf8Error), /// Error specific to ServerConnector impl + #[error("connection error: {0}")] Connection(Box), /// DNS protocol error #[cfg(feature = "dns")] - Dns(DnsProtoError), + #[error("{0:?}")] + Dns(#[from] DnsProtoError), /// DNS resolution error #[cfg(feature = "dns")] - Resolve(DnsResolveError), + #[error("{0:?}")] + Resolve(#[from] DnsResolveError), /// DNS label conversion error, no details available from module /// `idna` #[cfg(feature = "dns")] + #[error("IDNA error")] Idna, /// Invalid IP/Port address - Addr(AddrParseError), + #[error("wrong network address: {0}")] + Addr(#[from] AddrParseError), /// Received a stream error + #[error("{0}")] StreamError(ReceivedStreamError), } -impl fmt::Display for Error { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::Io(e) => write!(fmt, "IO error: {}", e), - Error::Connection(e) => write!(fmt, "connection error: {}", e), - Error::JidParse(e) => write!(fmt, "jid parse error: {}", e), - Error::Protocol(e) => write!(fmt, "protocol error: {}", e), - Error::Auth(e) => write!(fmt, "authentication error: {}", e), - Error::Disconnected => write!(fmt, "disconnected"), - Error::InvalidState => write!(fmt, "invalid state"), - Error::Fmt(e) => write!(fmt, "Fmt error: {}", e), - Error::Utf8(e) => write!(fmt, "Utf8 error: {}", e), - #[cfg(feature = "dns")] - Error::Dns(e) => write!(fmt, "{:?}", e), - #[cfg(feature = "dns")] - Error::Resolve(e) => write!(fmt, "{:?}", e), - #[cfg(feature = "dns")] - Error::Idna => write!(fmt, "IDNA error"), - Error::Addr(e) => write!(fmt, "Wrong network address: {e}"), - Error::StreamError(e) => write!(fmt, "{e}"), - } - } -} - -impl StdError for Error {} - -impl From for Error { - fn from(e: io::Error) -> Self { - Error::Io(e) - } -} - impl From for Error { fn from(e: T) -> Self { Error::Connection(Box::new(e)) } } -impl From for Error { - fn from(e: jid::Error) -> Self { - Error::JidParse(e) - } -} - -impl From for Error { - fn from(e: ProtocolError) -> Self { - Error::Protocol(e) - } -} - -impl From for Error { - fn from(e: AuthError) -> Self { - Error::Auth(e) - } -} - -impl From for Error { - fn from(e: fmt::Error) -> Self { - Error::Fmt(e) - } -} - -impl From for Error { - fn from(e: Utf8Error) -> Self { - Error::Utf8(e) - } -} - #[cfg(feature = "dns")] impl From for Error { fn from(_e: idna::Errors) -> Self { @@ -123,26 +76,6 @@ impl From for Error { } } -#[cfg(feature = "dns")] -impl From for Error { - fn from(e: DnsResolveError) -> Error { - Error::Resolve(e) - } -} - -#[cfg(feature = "dns")] -impl From for Error { - fn from(e: DnsProtoError) -> Error { - Error::Dns(e) - } -} - -impl From for Error { - fn from(e: AddrParseError) -> Error { - Error::Addr(e) - } -} - impl From for Error { fn from(e: RecvFeaturesError) -> Self { match e { @@ -153,87 +86,47 @@ impl From for Error { } /// XMPP protocol-level error -#[derive(Debug)] +#[derive(Debug, Error)] pub enum ProtocolError { /// XML parser error - Parser(minidom::Error), + #[error("XML parser error: {0}")] + Parser(#[from] minidom::Error), /// Error with expected stanza schema - Parsers(xso::error::Error), + #[error("error with expected stanza schema: {0}")] + Parsers(#[from] xso::error::Error), /// No TLS available + #[error("no TLS available")] NoTls, /// Invalid response to resource binding + #[error("invalid response to resource binding")] InvalidBindResponse, /// No xmlns attribute in + #[error("no xmlns attribute in ")] NoStreamNamespace, /// No id attribute in + #[error("no id attribute in ")] NoStreamId, /// Encountered an unexpected XML token + #[error("encountered an unexpected XML token")] InvalidToken, /// Unexpected (shouldn't occur) + #[error("unexpected ")] InvalidStreamStart, } -impl fmt::Display for ProtocolError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match self { - ProtocolError::Parser(e) => write!(fmt, "XML parser error: {}", e), - ProtocolError::Parsers(e) => write!(fmt, "error with expected stanza schema: {}", e), - ProtocolError::NoTls => write!(fmt, "no TLS available"), - ProtocolError::InvalidBindResponse => { - write!(fmt, "invalid response to resource binding") - } - ProtocolError::NoStreamNamespace => { - write!(fmt, "no xmlns attribute in ") - } - ProtocolError::NoStreamId => write!(fmt, "no id attribute in "), - ProtocolError::InvalidToken => write!(fmt, "encountered an unexpected XML token"), - ProtocolError::InvalidStreamStart => write!(fmt, "unexpected "), - } - } -} - -impl StdError for ProtocolError {} - -impl From for ProtocolError { - fn from(e: minidom::Error) -> Self { - ProtocolError::Parser(e) - } -} - -impl From for Error { - fn from(e: minidom::Error) -> Self { - ProtocolError::Parser(e).into() - } -} - -impl From for ProtocolError { - fn from(e: xso::error::Error) -> Self { - ProtocolError::Parsers(e) - } -} - /// Authentication error -#[derive(Debug)] +#[derive(Debug, Error)] pub enum AuthError { /// No matching SASL mechanism available + #[error("no matching SASL mechanism available")] NoMechanism, /// Local SASL implementation error + #[error("local SASL implementation error: {0}")] Sasl(SaslMechanismError), /// Failure from server + #[error("failure from the server: {0:?}")] Fail(SaslDefinedCondition), /// Component authentication failure + #[error("component authentication failure")] ComponentFail, } - -impl StdError for AuthError {} - -impl fmt::Display for AuthError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match self { - AuthError::NoMechanism => write!(fmt, "no matching SASL mechanism available"), - AuthError::Sasl(s) => write!(fmt, "local SASL implementation error: {}", s), - AuthError::Fail(c) => write!(fmt, "failure from the server: {:?}", c), - AuthError::ComponentFail => write!(fmt, "component authentication failure"), - } - } -}