1use miette::Diagnostic;
4use std::path::Path;
5use thiserror::Error;
6
7#[derive(Error, Debug, Diagnostic)]
9pub enum Error {
10 #[error("I/O {operation} failed{}", path.as_ref().map_or(String::new(), |p| format!(": {}", p.display())))]
12 #[diagnostic(
13 code(cuenv::cas::io),
14 help("Check file permissions and that the cache directory is writable")
15 )]
16 Io {
17 #[source]
19 source: std::io::Error,
20 path: Option<Box<Path>>,
22 operation: String,
24 },
25
26 #[error("CAS configuration error: {message}")]
28 #[diagnostic(code(cuenv::cas::config))]
29 Configuration {
30 message: String,
32 },
33
34 #[error("digest not found in CAS: {digest}")]
36 #[diagnostic(
37 code(cuenv::cas::not_found),
38 help("The blob may have been garbage collected or never written")
39 )]
40 NotFound {
41 digest: String,
43 },
44
45 #[error("digest mismatch: expected {expected}, got {actual}")]
47 #[diagnostic(code(cuenv::cas::digest_mismatch))]
48 DigestMismatch {
49 expected: String,
51 actual: String,
53 },
54
55 #[error("serialization error: {message}")]
57 #[diagnostic(code(cuenv::cas::serialization))]
58 Serialization {
59 message: String,
61 },
62}
63
64impl Error {
65 #[must_use]
67 pub fn configuration(msg: impl Into<String>) -> Self {
68 Self::Configuration {
69 message: msg.into(),
70 }
71 }
72
73 #[must_use]
75 pub fn io(
76 source: std::io::Error,
77 path: impl AsRef<Path>,
78 operation: impl Into<String>,
79 ) -> Self {
80 Self::Io {
81 source,
82 path: Some(path.as_ref().into()),
83 operation: operation.into(),
84 }
85 }
86
87 #[must_use]
89 pub fn io_no_path(source: std::io::Error, operation: impl Into<String>) -> Self {
90 Self::Io {
91 source,
92 path: None,
93 operation: operation.into(),
94 }
95 }
96
97 #[must_use]
99 pub fn not_found(digest: impl Into<String>) -> Self {
100 Self::NotFound {
101 digest: digest.into(),
102 }
103 }
104
105 #[must_use]
107 pub fn digest_mismatch(expected: impl Into<String>, actual: impl Into<String>) -> Self {
108 Self::DigestMismatch {
109 expected: expected.into(),
110 actual: actual.into(),
111 }
112 }
113
114 #[must_use]
116 pub fn serialization(msg: impl Into<String>) -> Self {
117 Self::Serialization {
118 message: msg.into(),
119 }
120 }
121}
122
123pub type Result<T> = std::result::Result<T, Error>;