1mod core;
14mod file;
15mod iter;
16mod path;
17mod string;
18mod user;
19mod vfs;
20
21use std::{error::Error as StdError, fmt, io, time::SystemTimeError};
22
23pub use file::*;
24pub use iter::*;
25pub use path::*;
26pub use string::*;
27pub use user::*;
28pub use vfs::*;
29
30pub use self::core::*;
31
32pub type RvResult<T> = std::result::Result<T, RvError>;
34
35#[derive(Debug)]
37pub enum RvError {
38 Core(CoreError),
40
41 File(FileError),
43
44 Io(io::Error),
46
47 Iter(IterError),
49
50 Nix(nix::errno::Errno),
52
53 Path(PathError),
55
56 String(StringError),
58
59 SystemTime(SystemTimeError),
61
62 User(UserError),
64
65 Utf8(std::str::Utf8Error),
67
68 Var(std::env::VarError),
70
71 Vfs(VfsError),
73}
74
75impl RvError {
76 pub fn is<T: StdError + 'static>(&self) -> bool {
78 self.as_ref().is::<T>()
79 }
80
81 pub fn downcast_ref<T: StdError + 'static>(&self) -> Option<&T> {
83 self.as_ref().downcast_ref::<T>()
84 }
85
86 pub fn downcast_mut<T: StdError + 'static>(&mut self) -> Option<&mut T> {
88 self.as_mut().downcast_mut::<T>()
89 }
90
91 pub fn source(&self) -> Option<&(dyn StdError + 'static)> {
94 self.as_ref().source()
95 }
96}
97impl StdError for RvError {}
98
99impl fmt::Display for RvError {
100 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101 match *self {
102 RvError::Core(ref err) => write!(f, "{}", err),
103 RvError::File(ref err) => write!(f, "{}", err),
104 RvError::Io(ref err) => write!(f, "{}", err),
105 RvError::Iter(ref err) => write!(f, "{}", err),
106 RvError::Nix(ref err) => write!(f, "{}", err),
107 RvError::Path(ref err) => write!(f, "{}", err),
108 RvError::String(ref err) => write!(f, "{}", err),
109 RvError::SystemTime(ref err) => write!(f, "{}", err),
110 RvError::User(ref err) => write!(f, "{}", err),
111 RvError::Utf8(ref err) => write!(f, "{}", err),
112 RvError::Var(ref err) => write!(f, "{}", err),
113 RvError::Vfs(ref err) => write!(f, "{}", err),
114 }
115 }
116}
117
118impl AsRef<dyn StdError> for RvError {
119 fn as_ref(&self) -> &(dyn StdError + 'static) {
120 match *self {
121 RvError::Core(ref err) => err,
122 RvError::File(ref err) => err,
123 RvError::Io(ref err) => err,
124 RvError::Iter(ref err) => err,
125 RvError::Nix(ref err) => err,
126 RvError::Path(ref err) => err,
127 RvError::String(ref err) => err,
128 RvError::SystemTime(ref err) => err,
129 RvError::User(ref err) => err,
130 RvError::Utf8(ref err) => err,
131 RvError::Var(ref err) => err,
132 RvError::Vfs(ref err) => err,
133 }
134 }
135}
136
137impl AsMut<dyn StdError> for RvError {
138 fn as_mut(&mut self) -> &mut (dyn StdError + 'static) {
139 match *self {
140 RvError::Core(ref mut err) => err,
141 RvError::File(ref mut err) => err,
142 RvError::Io(ref mut err) => err,
143 RvError::Iter(ref mut err) => err,
144 RvError::Nix(ref mut err) => err,
145 RvError::Path(ref mut err) => err,
146 RvError::String(ref mut err) => err,
147 RvError::SystemTime(ref mut err) => err,
148 RvError::User(ref mut err) => err,
149 RvError::Utf8(ref mut err) => err,
150 RvError::Var(ref mut err) => err,
151 RvError::Vfs(ref mut err) => err,
152 }
153 }
154}
155
156impl From<CoreError> for RvError {
157 fn from(err: CoreError) -> RvError {
158 RvError::Core(err)
159 }
160}
161
162impl From<FileError> for RvError {
163 fn from(err: FileError) -> RvError {
164 RvError::File(err)
165 }
166}
167
168impl From<io::Error> for RvError {
169 fn from(err: io::Error) -> RvError {
170 RvError::Io(err)
171 }
172}
173
174impl From<IterError> for RvError {
175 fn from(err: IterError) -> RvError {
176 RvError::Iter(err)
177 }
178}
179
180impl From<nix::errno::Errno> for RvError {
181 fn from(err: nix::errno::Errno) -> RvError {
182 RvError::Nix(err)
183 }
184}
185
186impl From<PathError> for RvError {
187 fn from(err: PathError) -> RvError {
188 RvError::Path(err)
189 }
190}
191
192impl From<StringError> for RvError {
193 fn from(err: StringError) -> RvError {
194 RvError::String(err)
195 }
196}
197
198impl From<&str> for RvError {
199 fn from(err: &str) -> RvError {
200 RvError::Core(CoreError::msg(err))
201 }
202}
203
204impl From<SystemTimeError> for RvError {
205 fn from(err: SystemTimeError) -> RvError {
206 RvError::SystemTime(err)
207 }
208}
209
210impl From<UserError> for RvError {
211 fn from(err: UserError) -> RvError {
212 RvError::User(err)
213 }
214}
215
216impl From<std::str::Utf8Error> for RvError {
217 fn from(err: std::str::Utf8Error) -> RvError {
218 RvError::Utf8(err)
219 }
220}
221
222impl From<std::env::VarError> for RvError {
223 fn from(err: std::env::VarError) -> RvError {
224 RvError::Var(err)
225 }
226}
227
228impl From<VfsError> for RvError {
229 fn from(err: VfsError) -> RvError {
230 RvError::Vfs(err)
231 }
232}
233
234#[cfg(test)]
235mod tests {
236 use std::path::PathBuf;
237
238 use crate::errors::*;
239
240 #[test]
241 fn test_error() {
242 let mut err = RvError::from(CoreError::msg("foo"));
243 assert_eq!(err.to_string(), "foo");
244 assert_eq!(err.as_ref().to_string(), "foo");
245 assert_eq!(err.as_mut().to_string(), "foo");
246 assert!(err.downcast_ref::<CoreError>().is_some());
247 assert!(err.downcast_mut::<CoreError>().is_some());
248 assert!(err.source().is_none());
249
250 let mut err = RvError::from(io::Error::new(io::ErrorKind::AlreadyExists, "foo"));
251 assert_eq!("foo", err.to_string());
252 assert_eq!("foo", err.as_ref().to_string());
253 assert_eq!("foo", err.as_mut().to_string());
254 assert!(err.downcast_ref::<io::Error>().is_some());
255 assert!(err.downcast_mut::<io::Error>().is_some());
256 assert!(err.source().is_none());
257
258 let mut err = RvError::from(IterError::ItemNotFound);
259 assert_eq!("iterator item not found", err.to_string());
260 assert_eq!("iterator item not found", err.as_ref().to_string());
261 assert_eq!("iterator item not found", err.as_mut().to_string());
262 assert!(err.downcast_ref::<IterError>().is_some());
263 assert!(err.downcast_mut::<IterError>().is_some());
264 assert!(err.source().is_none());
265
266 let mut err = RvError::from(FileError::FailedToExtractString);
267 assert_eq!("Failed to extract string from file", err.to_string());
268 assert_eq!("Failed to extract string from file", err.as_ref().to_string());
269 assert_eq!("Failed to extract string from file", err.as_mut().to_string());
270 assert!(err.downcast_ref::<FileError>().is_some());
271 assert!(err.downcast_mut::<FileError>().is_some());
272 assert!(err.source().is_none());
273
274 let mut err = RvError::from(nix::errno::Errno::UnknownErrno);
275 assert_eq!(err.to_string(), "UnknownErrno: Unknown errno");
276 assert_eq!(err.as_ref().to_string(), "UnknownErrno: Unknown errno");
277 assert_eq!(err.as_mut().to_string(), "UnknownErrno: Unknown errno");
278 assert!(err.downcast_ref::<nix::errno::Errno>().is_some());
279 assert!(err.downcast_mut::<nix::errno::Errno>().is_some());
280 assert!(err.source().is_none());
281
282 let mut err = RvError::from(PathError::Empty);
283 assert_eq!("path empty", err.to_string());
284 assert_eq!("path empty", err.as_ref().to_string());
285 assert_eq!("path empty", err.as_mut().to_string());
286 assert!(err.downcast_ref::<PathError>().is_some());
287 assert!(err.downcast_mut::<PathError>().is_some());
288 assert!(err.source().is_none());
289
290 let mut err = RvError::from(StringError::FailedToString);
291 assert_eq!("failed to convert value to string", err.to_string());
292 assert_eq!("failed to convert value to string", err.as_ref().to_string());
293 assert_eq!("failed to convert value to string", err.as_mut().to_string());
294 assert!(err.downcast_ref::<StringError>().is_some());
295 assert!(err.downcast_mut::<StringError>().is_some());
296 assert!(err.source().is_none());
297
298 let time1 = std::time::SystemTime::now();
299 std::thread::sleep(std::time::Duration::from_millis(5));
300 let time2 = std::time::SystemTime::now();
301 let mut err = RvError::from(time1.duration_since(time2).unwrap_err());
302 assert_eq!(err.to_string(), "second time provided was later than self");
303 assert_eq!(err.as_ref().to_string(), "second time provided was later than self");
304 assert_eq!(err.as_mut().to_string(), "second time provided was later than self");
305 assert!(err.downcast_ref::<std::time::SystemTimeError>().is_some());
306 assert!(err.downcast_mut::<std::time::SystemTimeError>().is_some());
307 assert!(err.source().is_none());
308
309 let mut err = RvError::from(std::str::from_utf8(&vec![0, 159, 146, 150]).unwrap_err());
310 assert_eq!(err.to_string(), "invalid utf-8 sequence of 1 bytes from index 1");
311 assert_eq!(err.as_ref().to_string(), "invalid utf-8 sequence of 1 bytes from index 1");
312 assert_eq!(err.as_mut().to_string(), "invalid utf-8 sequence of 1 bytes from index 1");
313 assert!(err.downcast_ref::<std::str::Utf8Error>().is_some());
314 assert!(err.downcast_mut::<std::str::Utf8Error>().is_some());
315 assert!(err.source().is_none());
316
317 let mut err = RvError::from(std::env::VarError::NotPresent);
318 assert_eq!("environment variable not found", err.to_string());
319 assert_eq!("environment variable not found", err.as_ref().to_string());
320 assert_eq!("environment variable not found", err.as_mut().to_string());
321 assert!(err.downcast_ref::<std::env::VarError>().is_some());
322 assert!(err.downcast_mut::<std::env::VarError>().is_some());
323 assert!(err.source().is_none());
324
325 let mut err = RvError::from(VfsError::Unavailable);
326 assert_eq!("Virtual filesystem is unavailable", err.to_string());
327 assert_eq!("Virtual filesystem is unavailable", err.as_ref().to_string());
328 assert_eq!("Virtual filesystem is unavailable", err.as_mut().to_string());
329 assert!(err.downcast_ref::<VfsError>().is_some());
330 assert!(err.downcast_mut::<VfsError>().is_some());
331 assert!(err.source().is_none());
332 }
333
334 fn path_empty() -> RvResult<PathBuf> {
335 Err(PathError::Empty)?
336 }
337
338 #[test]
339 fn test_is() {
340 assert!(path_empty().is_err());
341 assert!(path_empty().unwrap_err().is::<PathError>());
342 }
343
344 #[test]
345 fn test_downcast_ref() {
346 assert!(path_empty().is_err());
347 assert_eq!(path_empty().unwrap_err().downcast_ref::<PathError>(), Some(&PathError::Empty));
348 }
349}