1use thiserror::Error;
8
9#[derive(Error, Debug)]
11pub enum AssetError {
12 #[error("I/O error: {0}")]
14 Io(#[from] std::io::Error),
15
16 #[error("Index serialization error: {0}")]
18 Serialization(#[from] serde_json::Error),
19
20 #[error("Configuration error: {0}")]
22 Config(String),
23
24 #[error("Asset not found: {0}")]
26 NotFound(String),
27
28 #[error("Cache directory error: {0}")]
30 CacheDir(String),
31
32 #[error("Asset index mutex poisoned: {0}")]
36 Poisoned(String),
37
38 #[error(transparent)]
40 Core(#[from] devboy_core::Error),
41}
42
43pub type Result<T> = std::result::Result<T, AssetError>;
45
46impl AssetError {
47 pub fn config(msg: impl Into<String>) -> Self {
49 AssetError::Config(msg.into())
50 }
51
52 pub fn cache_dir(msg: impl Into<String>) -> Self {
54 AssetError::CacheDir(msg.into())
55 }
56
57 pub fn not_found(id: impl Into<String>) -> Self {
59 AssetError::NotFound(id.into())
60 }
61
62 pub fn poisoned(msg: impl Into<String>) -> Self {
64 AssetError::Poisoned(msg.into())
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn constructor_helpers() {
74 let e = AssetError::config("bad value");
75 assert!(matches!(e, AssetError::Config(_)));
76 assert!(format!("{e}").contains("bad value"));
77
78 let e = AssetError::cache_dir("no perms");
79 assert!(matches!(e, AssetError::CacheDir(_)));
80
81 let e = AssetError::not_found("asset-1");
82 assert!(matches!(e, AssetError::NotFound(_)));
83 }
84
85 #[test]
86 fn io_error_is_convertible() {
87 let io = std::io::Error::new(std::io::ErrorKind::NotFound, "x");
88 let e: AssetError = io.into();
89 assert!(matches!(e, AssetError::Io(_)));
90 }
91}