From bfe723cf46876d1b1704b2a50325fc0fd19cc5e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Sch=C3=A4fer?= Date: Sun, 18 Aug 2024 15:06:59 +0200 Subject: [PATCH] parsers: make stream errors more ergonomic for error processing --- parsers/src/stream_error.rs | 81 +++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/parsers/src/stream_error.rs b/parsers/src/stream_error.rs index 85ee13b4986fe283f08751b8d99a10ba68b16055..af9881db2d5beec6a771a7ac94fa4b08d469c6de 100644 --- a/parsers/src/stream_error.rs +++ b/parsers/src/stream_error.rs @@ -4,6 +4,9 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use core::fmt; +use std::error::Error; + use minidom::Element; use xso::{AsXml, FromXml}; @@ -262,6 +265,39 @@ pub enum DefinedCondition { UnsupportedVersion, } +impl fmt::Display for DefinedCondition { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s = match self { + Self::BadFormat => "bad-format", + Self::BadNamespacePrefix => "bad-namespace-prefix", + Self::Conflict => "conflict", + Self::ConnectionTimeout => "connection-timeout", + Self::HostGone => "host-gone", + Self::HostUnknown => "host-unknown", + Self::ImproperAddressing => "improper-addressing", + Self::InternalServerError => "internal-server-error", + Self::InvalidFrom => "invalid-from", + Self::InvalidNamespace => "invalid-namespace", + Self::InvalidXml => "invalid-xml", + Self::NotAuthorized => "not-authorized", + Self::NotWellFormed => "not-well-formed", + Self::PolicyViolation => "policy-violation", + Self::RemoteConnectionFailed => "remote-connection-failed", + Self::Reset => "reset", + Self::ResourceConstraint => "resource-constraint", + Self::RestrictedXml => "restricted-xml", + Self::SeeOtherHost(ref host) => return write!(f, "see-other-host: {}", host), + Self::SystemShutdown => "system-shutdown", + Self::UndefinedCondition => "undefined-condition", + Self::UnsupportedEncoding => "unsupported-encoding", + Self::UnsupportedFeature => "unsupported-feature", + Self::UnsupportedStanzaType => "unsupported-stanza-type", + Self::UnsupportedVersion => "unsupported-version", + }; + f.write_str(s) + } +} + /// Stream error as specified in RFC 6120. #[derive(FromXml, AsXml, PartialEq, Debug, Clone)] #[xml(namespace = ns::STREAM, name = "error")] @@ -281,3 +317,48 @@ pub struct StreamError { #[xml(element(n = ..))] pub application_specific: Vec, } + +impl fmt::Display for StreamError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + ::fmt(&self.condition, f)?; + match self.text { + Some((_, ref text)) => write!(f, " ({:?})", text)?, + None => (), + }; + match self.application_specific.get(0) { + Some(cond) => { + f.write_str(&String::from(cond))?; + } + None => (), + } + Ok(()) + } +} + +/// Wrapper around [`StreamError`] which implements [`std::error::Error`] +/// with an appropriate error message. +#[derive(FromXml, AsXml, Debug)] +#[xml(transparent)] +pub struct ReceivedStreamError(pub StreamError); + +impl fmt::Display for ReceivedStreamError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "received stream error: {}", self.0) + } +} + +impl Error for ReceivedStreamError {} + +/// Wrapper around [`StreamError`] which implements [`std::error::Error`] +/// with an appropriate error message. +#[derive(FromXml, AsXml, Debug)] +#[xml(transparent)] +pub struct SentStreamError(pub StreamError); + +impl fmt::Display for SentStreamError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "sent stream error: {}", self.0) + } +} + +impl Error for SentStreamError {}