ironflow_artifacts/
error.rs1use thiserror::Error;
4
5#[derive(Debug, Error)]
16pub enum ArtifactError {
17 #[error("artifact not found: {0}")]
19 NotFound(String),
20
21 #[error("invalid artifact name {name:?}: {reason}")]
25 InvalidName {
26 name: String,
28 reason: &'static str,
30 },
31
32 #[error("invalid storage key {key:?}: {reason}")]
37 InvalidKey {
38 key: String,
40 reason: &'static str,
42 },
43
44 #[error("artifact exceeds the {limit_bytes} byte limit")]
46 TooLarge {
47 limit_bytes: u64,
49 },
50
51 #[error("artifact storage io error: {0}")]
53 Io(String),
54}
55
56impl From<std::io::Error> for ArtifactError {
57 fn from(err: std::io::Error) -> Self {
58 ArtifactError::Io(err.to_string())
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use std::io::{Error as IoError, ErrorKind};
65
66 use super::*;
67
68 #[test]
69 fn not_found_display() {
70 let err = ArtifactError::NotFound("a/b".to_string());
71 assert_eq!(err.to_string(), "artifact not found: a/b");
72 }
73
74 #[test]
75 fn invalid_name_display_quotes_the_name() {
76 let err = ArtifactError::InvalidName {
77 name: "../etc/passwd".to_string(),
78 reason: "contains a forbidden character",
79 };
80 assert!(err.to_string().contains("\"../etc/passwd\""));
81 assert!(err.to_string().contains("forbidden character"));
82 }
83
84 #[test]
85 fn invalid_key_display() {
86 let err = ArtifactError::InvalidKey {
87 key: "/abs".to_string(),
88 reason: "must be relative",
89 };
90 assert!(err.to_string().contains("must be relative"));
91 }
92
93 #[test]
94 fn too_large_display_shows_the_limit() {
95 let err = ArtifactError::TooLarge { limit_bytes: 1024 };
96 assert!(err.to_string().contains("1024"));
97 }
98
99 #[test]
100 fn io_error_converts() {
101 let io = IoError::new(ErrorKind::PermissionDenied, "nope");
102 let err = ArtifactError::from(io);
103 assert!(matches!(err, ArtifactError::Io(_)));
104 assert!(err.to_string().contains("nope"));
105 }
106}