1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use std::fmt::{Display, Formatter};
use std::io::Error;
#[derive(Debug)]
pub enum VfsError {
IoError(std::io::Error),
FileNotFound {
path: String,
},
InvalidPath {
path: String,
},
Other {
message: String,
},
WithContext {
context: String,
cause: Box<VfsError>,
},
NotSupported,
}
impl From<String> for VfsError {
fn from(message: String) -> Self {
VfsError::Other { message }
}
}
impl From<std::io::Error> for VfsError {
fn from(cause: Error) -> Self {
VfsError::IoError(cause)
}
}
impl std::fmt::Display for VfsError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
VfsError::IoError(cause) => {
write!(f, "IO error: {}", cause)
}
VfsError::FileNotFound { path } => {
write!(f, "The file or directory `{}` could not be found", path)
}
VfsError::InvalidPath { path } => {
write!(f, "The path `{}` is invalid", path)
}
VfsError::Other { message } => {
write!(f, "FileSystem error: {}", message)
}
VfsError::WithContext { context, cause } => {
write!(f, "{}, cause: {}", context, cause)
}
VfsError::NotSupported => {
write!(f, "Functionality not supported by this filesystem")
}
}
}
}
pub type VfsResult<T> = std::result::Result<T, VfsError>;
pub(crate) trait VfsResultExt<T> {
fn with_context<C, F>(self, f: F) -> VfsResult<T>
where
C: Display + Send + Sync + 'static,
F: FnOnce() -> C;
}
impl<T> VfsResultExt<T> for VfsResult<T> {
fn with_context<C, F>(self, context: F) -> VfsResult<T>
where
C: Display + Send + Sync + 'static,
F: FnOnce() -> C,
{
self.map_err(|error| VfsError::WithContext {
context: context().to_string(),
cause: Box::new(error),
})
}
}