fusabi_stdlib_ext/
error.rs1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, Error>;
7
8#[derive(Error, Debug)]
10pub enum Error {
11 #[error("operation not permitted: {0}")]
13 NotPermitted(String),
14
15 #[error("path not allowed: {0}")]
17 PathNotAllowed(String),
18
19 #[error("host not allowed: {0}")]
21 HostNotAllowed(String),
22
23 #[error("operation timed out after {0:?}")]
25 Timeout(std::time::Duration),
26
27 #[error("process error: {0}")]
29 Process(String),
30
31 #[error("process exited with code {code}: {message}")]
33 ProcessExit {
34 code: i32,
36 message: String,
38 },
39
40 #[error("filesystem error: {0}")]
42 Filesystem(String),
43
44 #[error("network error: {0}")]
46 Network(String),
47
48 #[error("format error: {0}")]
50 Format(String),
51
52 #[error("environment error: {0}")]
54 Environment(String),
55
56 #[error("module not available: {0}")]
58 ModuleNotAvailable(String),
59
60 #[error("invalid argument: {0}")]
62 InvalidArgument(String),
63
64 #[error("io error: {0}")]
66 Io(#[from] std::io::Error),
67
68 #[error("host error: {0}")]
70 Host(#[from] fusabi_host::Error),
71
72 #[error("internal error: {0}")]
74 Internal(String),
75
76 #[error("terminal UI error: {0}")]
78 TerminalUI(String),
79
80 #[error("kubernetes error: {0}")]
82 K8s(String),
83
84 #[error("invalid value: {0}")]
86 InvalidValue(String),
87
88 #[error("serialization error: {0}")]
90 Serialization(String),
91}
92
93impl Error {
94 pub fn not_permitted(msg: impl Into<String>) -> Self {
96 Self::NotPermitted(msg.into())
97 }
98
99 pub fn path_not_allowed(path: impl Into<String>) -> Self {
101 Self::PathNotAllowed(path.into())
102 }
103
104 pub fn host_not_allowed(host: impl Into<String>) -> Self {
106 Self::HostNotAllowed(host.into())
107 }
108
109 pub fn timeout(duration: std::time::Duration) -> Self {
111 Self::Timeout(duration)
112 }
113
114 pub fn process(msg: impl Into<String>) -> Self {
116 Self::Process(msg.into())
117 }
118
119 pub fn process_exit(code: i32, message: impl Into<String>) -> Self {
121 Self::ProcessExit {
122 code,
123 message: message.into(),
124 }
125 }
126
127 pub fn filesystem(msg: impl Into<String>) -> Self {
129 Self::Filesystem(msg.into())
130 }
131
132 pub fn network(msg: impl Into<String>) -> Self {
134 Self::Network(msg.into())
135 }
136
137 pub fn format(msg: impl Into<String>) -> Self {
139 Self::Format(msg.into())
140 }
141
142 pub fn invalid_argument(msg: impl Into<String>) -> Self {
144 Self::InvalidArgument(msg.into())
145 }
146
147 pub fn is_safety_error(&self) -> bool {
149 matches!(
150 self,
151 Self::NotPermitted(_) | Self::PathNotAllowed(_) | Self::HostNotAllowed(_)
152 )
153 }
154
155 pub fn is_timeout(&self) -> bool {
157 matches!(self, Self::Timeout(_))
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164
165 #[test]
166 fn test_error_display() {
167 let err = Error::path_not_allowed("/etc/passwd");
168 assert!(err.to_string().contains("/etc/passwd"));
169
170 let err = Error::process_exit(1, "command failed");
171 assert!(err.to_string().contains("code 1"));
172 }
173
174 #[test]
175 fn test_error_classification() {
176 assert!(Error::not_permitted("test").is_safety_error());
177 assert!(Error::path_not_allowed("/tmp").is_safety_error());
178 assert!(!Error::process("test").is_safety_error());
179
180 assert!(Error::timeout(std::time::Duration::from_secs(1)).is_timeout());
181 assert!(!Error::process("test").is_timeout());
182 }
183}