use std::borrow::Cow;
use thiserror::Error;
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum ResolverError {
#[error("io error: {0}")]
Io(#[from] std::io::Error),
#[error("invalid style: {0}")]
InvalidStyle(Cow<'static, str>),
#[error("style not found: {0}")]
StyleNotFound(Cow<'static, str>),
#[error("locale not found: {0}")]
LocaleNotFound(Cow<'static, str>),
#[error("yaml error: {0}")]
YamlError(String),
#[cfg(feature = "serde_json")]
#[error("json error: {0}")]
JsonError(#[from] serde_json::Error),
#[error("cbor error: {0}")]
CborError(String),
#[cfg(feature = "http")]
#[error("http error: {0}")]
HttpError(String),
#[cfg(feature = "http")]
#[error("git error: {0}")]
GitError(String),
#[error("host not in resolver allowlist: {uri} ({reason})")]
Denied {
uri: String,
reason: String,
},
#[error(
"engine version mismatch for {uri}: engine requires {required}, style declares {declared}"
)]
VersionMismatch {
uri: String,
required: String,
declared: String,
},
#[error("integrity failure for {uri}: expected {expected}, got {actual}")]
IntegrityFailure {
uri: String,
expected: String,
actual: String,
},
#[error("network error fetching {uri}: {reason}")]
NetworkError {
uri: String,
reason: String,
},
}
#[derive(Error, Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum ResolutionError {
#[error("profile styles may not override template-bearing field `{location}`")]
InvalidProfileOverride {
location: String,
},
#[error("inheritance loop detected at base `{base}`")]
InheritanceLoop {
base: String,
},
#[error("failed to resolve URI `{uri}`: {reason}")]
UriResolutionFailed {
uri: String,
reason: String,
},
#[error("template variant `{location}` extends missing variant `{selector}`")]
MissingTemplateVariantParent {
location: String,
selector: String,
},
#[error("template variant inheritance loop at `{location}` through `{selector}`")]
TemplateVariantCycle {
location: String,
selector: String,
},
#[error("template variant operation in `{location}` matched no component")]
TemplateVariantAnchorNotFound {
location: String,
},
#[error("template variant operation in `{location}` matched multiple components")]
TemplateVariantAmbiguousAnchor {
location: String,
},
#[error(
"template variant add operation in `{location}` must specify exactly one of before/after"
)]
InvalidTemplateVariantAdd {
location: String,
},
#[error("extends-pin integrity check failed for `{uri}`: expected {expected}, got {actual}")]
IntegrityFailure {
uri: String,
expected: String,
actual: String,
},
#[error("style `{uri}` requires citum-version `{required}`; running engine is `{declared}`")]
VersionMismatch {
uri: String,
required: String,
declared: String,
},
}
impl ResolutionError {
#[must_use]
pub fn from_resolver_error(uri: &str, err: ResolverError) -> Self {
match err {
ResolverError::IntegrityFailure {
expected, actual, ..
} => ResolutionError::IntegrityFailure {
uri: uri.into(),
expected,
actual,
},
ResolverError::VersionMismatch {
required, declared, ..
} => ResolutionError::VersionMismatch {
uri: uri.into(),
required,
declared,
},
_ => ResolutionError::UriResolutionFailed {
uri: uri.into(),
reason: err.to_string(),
},
}
}
}