#[cfg(feature = "embedded")]
use crate::xml_input_shared as xml_sec_xml_input;
use super::{AccessDenialReason, BudgetKind, ResourceIdentity};
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum ErrorKind {
Xml,
Static,
Dynamic,
Resource,
Resolver,
Policy,
Budget,
Serialization,
Unsupported,
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[error("XML input is not well formed: {0}")]
Xml(String),
#[error("stylesheet static error: {0}")]
Static(String),
#[error("XSLT dynamic error: {0}")]
Dynamic(String),
#[error("resource {identity:?} changed during XSLT processing")]
StaleResource { identity: ResourceIdentity },
#[error("resource not found: {uri}")]
ResourceNotFound { uri: String },
#[error("resource resolution failed for {uri}: {message}")]
Resolver { uri: String, message: String },
#[error("resource access denied for {resource}: {reason:?}")]
ResourceAccessDenied {
resource: String,
reason: AccessDenialReason,
},
#[error("{kind:?} budget exceeded: limit {limit}, attempted {actual}")]
Budget {
kind: BudgetKind,
limit: usize,
actual: usize,
},
#[error("serialization failed: {0}")]
Serialization(String),
#[error("unsupported XSLT feature: {0}")]
Unsupported(String),
}
impl Error {
#[must_use]
pub const fn kind(&self) -> ErrorKind {
match self {
Self::Xml(_) => ErrorKind::Xml,
Self::Static(_) => ErrorKind::Static,
Self::Dynamic(_) => ErrorKind::Dynamic,
Self::StaleResource { .. } | Self::ResourceNotFound { .. } => ErrorKind::Resource,
Self::Resolver { .. } => ErrorKind::Resolver,
Self::ResourceAccessDenied { .. } => ErrorKind::Policy,
Self::Budget { .. } => ErrorKind::Budget,
Self::Serialization(_) => ErrorKind::Serialization,
Self::Unsupported(_) => ErrorKind::Unsupported,
}
}
}
pub(crate) fn decoded_xml_error(error: xml_sec_xml_input::Error) -> Error {
match error {
xml_sec_xml_input::Error::DecodedLimit { maximum, actual } => Error::Budget {
kind: BudgetKind::OwnedBytes,
limit: maximum,
actual,
},
error => Error::Xml(error.to_string()),
}
}
#[cfg(all(test, not(feature = "embedded")))]
mod tests;