parsers: make stream errors more ergonomic for error processing

This commit is contained in:
Jonas Schäfer 2024-08-18 15:06:59 +02:00 committed by Link Mauve
commit bfe723cf46

View file

@ -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<Element>,
}
impl fmt::Display for StreamError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<DefinedCondition as fmt::Display>::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 {}