use miette::Diagnostic;
use std::path::Path;
use thiserror::Error;
#[derive(Error, Debug, Diagnostic)]
pub enum Error {
#[error("I/O {operation} failed{}", path.as_ref().map_or(String::new(), |p| format!(": {}", p.display())))]
#[diagnostic(
code(cuenv::cas::io),
help("Check file permissions and that the cache directory is writable")
)]
Io {
#[source]
source: std::io::Error,
path: Option<Box<Path>>,
operation: String,
},
#[error("CAS configuration error: {message}")]
#[diagnostic(code(cuenv::cas::config))]
Configuration {
message: String,
},
#[error("digest not found in CAS: {digest}")]
#[diagnostic(
code(cuenv::cas::not_found),
help("The blob may have been garbage collected or never written")
)]
NotFound {
digest: String,
},
#[error("digest mismatch: expected {expected}, got {actual}")]
#[diagnostic(code(cuenv::cas::digest_mismatch))]
DigestMismatch {
expected: String,
actual: String,
},
#[error("serialization error: {message}")]
#[diagnostic(code(cuenv::cas::serialization))]
Serialization {
message: String,
},
}
impl Error {
#[must_use]
pub fn configuration(msg: impl Into<String>) -> Self {
Self::Configuration {
message: msg.into(),
}
}
#[must_use]
pub fn io(
source: std::io::Error,
path: impl AsRef<Path>,
operation: impl Into<String>,
) -> Self {
Self::Io {
source,
path: Some(path.as_ref().into()),
operation: operation.into(),
}
}
#[must_use]
pub fn io_no_path(source: std::io::Error, operation: impl Into<String>) -> Self {
Self::Io {
source,
path: None,
operation: operation.into(),
}
}
#[must_use]
pub fn not_found(digest: impl Into<String>) -> Self {
Self::NotFound {
digest: digest.into(),
}
}
#[must_use]
pub fn digest_mismatch(expected: impl Into<String>, actual: impl Into<String>) -> Self {
Self::DigestMismatch {
expected: expected.into(),
actual: actual.into(),
}
}
#[must_use]
pub fn serialization(msg: impl Into<String>) -> Self {
Self::Serialization {
message: msg.into(),
}
}
}
pub type Result<T> = std::result::Result<T, Error>;