1use std::error::Error;
10use std::fmt::{Display, Formatter};
11use std::io;
12
13#[derive(Debug)]
14pub enum BlobCacheError {
16 Closed,
18 InvalidConfig(String),
20 InvalidBlob(String),
22 ContentMismatch(String),
24 Corrupt(String),
26 Reconciliation(String),
28 Policy(String),
30 Io {
32 operation: String,
34 source: io::Error,
36 },
37}
38
39impl BlobCacheError {
40 pub(crate) fn io(operation: impl Into<String>, source: io::Error) -> Self {
41 Self::Io {
42 operation: operation.into(),
43 source,
44 }
45 }
46
47 pub(crate) fn is_missing_or_corrupt(&self) -> bool {
48 matches!(self, Self::Corrupt(_))
49 || matches!(self, Self::Io { source, .. } if source.kind() == io::ErrorKind::NotFound)
50 }
51}
52
53impl Display for BlobCacheError {
54 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
55 match self {
56 Self::Closed => formatter.write_str("blob cache is closed"),
57 Self::InvalidConfig(message) => {
58 write!(formatter, "invalid blob cache configuration: {message}")
59 }
60 Self::InvalidBlob(message) => write!(formatter, "invalid blob: {message}"),
61 Self::ContentMismatch(blob_id) => {
62 write!(formatter, "blob ID content mismatch: {blob_id:?}")
63 }
64 Self::Corrupt(message) => write!(formatter, "corrupt blob cache entry: {message}"),
65 Self::Reconciliation(message) => {
66 write!(formatter, "blob cache reconciliation failed: {message}")
67 }
68 Self::Policy(message) => write!(formatter, "blob cache policy failed: {message}"),
69 Self::Io { operation, source } => write!(formatter, "{operation}: {source}"),
70 }
71 }
72}
73
74impl Error for BlobCacheError {
75 fn source(&self) -> Option<&(dyn Error + 'static)> {
76 match self {
77 Self::Io { source, .. } => Some(source),
78 _ => None,
79 }
80 }
81}