1use std::{
2 error::Error as StdError,
3 fmt,
4 path::{Path, PathBuf},
5};
6
7#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
9pub enum PathError {
10 DoesNotExist(PathBuf),
12
13 Empty,
15
16 ExistsAlready(PathBuf),
18
19 ExtensionNotFound(PathBuf),
21
22 FailedToString(PathBuf),
24
25 FileNameNotFound(PathBuf),
27
28 InvalidExpansion(PathBuf),
30
31 IsNotDir(PathBuf),
33
34 IsNotExec(PathBuf),
36
37 IsNotFile(PathBuf),
39
40 IsNotFileOrSymlinkToFile(PathBuf),
42
43 MultipleHomeSymbols(PathBuf),
45
46 ParentNotFound(PathBuf),
48}
49impl PathError {
50 pub fn does_not_exist<T: AsRef<Path>>(path: T) -> PathError {
52 PathError::DoesNotExist(path.as_ref().to_path_buf())
53 }
54
55 pub fn exists_already<T: AsRef<Path>>(path: T) -> PathError {
57 PathError::ExistsAlready(path.as_ref().to_path_buf())
58 }
59
60 pub fn extension_not_found<T: AsRef<Path>>(path: T) -> PathError {
62 PathError::ExtensionNotFound(path.as_ref().to_path_buf())
63 }
64
65 pub fn failed_to_string<T: AsRef<Path>>(path: T) -> PathError {
67 PathError::FailedToString(path.as_ref().to_path_buf())
68 }
69
70 pub fn filename_not_found<T: AsRef<Path>>(path: T) -> PathError {
72 PathError::FileNameNotFound(path.as_ref().to_path_buf())
73 }
74
75 pub fn is_not_dir<T: AsRef<Path>>(path: T) -> PathError {
77 PathError::IsNotDir(path.as_ref().to_path_buf())
78 }
79
80 pub fn is_not_exec<T: AsRef<Path>>(path: T) -> PathError {
82 PathError::IsNotExec(path.as_ref().to_path_buf())
83 }
84
85 pub fn is_not_file<T: AsRef<Path>>(path: T) -> PathError {
87 PathError::IsNotFile(path.as_ref().to_path_buf())
88 }
89
90 pub fn is_not_file_or_symlink_to_file<T: AsRef<Path>>(path: T) -> PathError {
92 PathError::IsNotFileOrSymlinkToFile(path.as_ref().to_path_buf())
93 }
94
95 pub fn invalid_expansion<T: AsRef<Path>>(path: T) -> PathError {
97 PathError::InvalidExpansion(path.as_ref().to_path_buf())
98 }
99
100 pub fn multiple_home_symbols<T: AsRef<Path>>(path: T) -> PathError {
102 PathError::MultipleHomeSymbols(path.as_ref().to_path_buf())
103 }
104
105 pub fn parent_not_found<T: AsRef<Path>>(path: T) -> PathError {
107 PathError::ParentNotFound(path.as_ref().to_path_buf())
108 }
109}
110
111impl StdError for PathError {}
112
113impl AsRef<dyn StdError> for PathError {
114 fn as_ref(&self) -> &(dyn StdError+'static) {
115 self
116 }
117}
118
119impl fmt::Display for PathError {
120 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121 match *self {
122 PathError::DoesNotExist(ref path) => write!(f, "path does not exist: {}", path.display()),
123 PathError::Empty => write!(f, "path empty"),
124 PathError::ExistsAlready(ref path) => write!(f, "path exists already: {}", path.display()),
125 PathError::ExtensionNotFound(ref path) => write!(f, "path extension not found: {}", path.display()),
126 PathError::FailedToString(ref path) => write!(f, "failed to convert to string for path: {}", path.display()),
127 PathError::FileNameNotFound(ref path) => write!(f, "filename not found for path: {}", path.display()),
128 PathError::InvalidExpansion(ref path) => write!(f, "invalid expansion for path: {}", path.display()),
129 PathError::IsNotDir(ref path) => write!(f, "is not a directory: {}", path.display()),
130 PathError::IsNotExec(ref path) => write!(f, "is not an executable: {}", path.display()),
131 PathError::IsNotFile(ref path) => write!(f, "is not a file: {}", path.display()),
132 PathError::IsNotFileOrSymlinkToFile(ref path) => write!(f, "is not a file or a symlink to a file: {}", path.display()),
133 PathError::MultipleHomeSymbols(ref path) => write!(f, "multiple home symbols for path: {}", path.display()),
134 PathError::ParentNotFound(ref path) => write!(f, "parent not found for path: {}", path.display()),
135 }
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use crate::prelude::*;
142
143 fn path_empty() -> FuResult<PathBuf> {
144 Err(PathError::Empty)?
145 }
146
147 fn parent_not_found() -> FuResult<PathBuf> {
148 Err(PathError::parent_not_found("foo"))?
149 }
150
151 #[test]
152 fn test_new_path_empty() {
153 assert!(path_empty().is_err());
154 assert_eq!(path_empty().unwrap_err().downcast_ref::<PathError>(), Some(&PathError::Empty));
155 }
156
157 #[test]
158 fn test_parent_not_found() {
159 assert!(parent_not_found().is_err());
160 assert_ne!(parent_not_found().unwrap_err().downcast_ref::<PathError>(), Some(&PathError::parent_not_found("bar")));
161 assert_eq!(parent_not_found().unwrap_err().downcast_ref::<PathError>(), Some(&PathError::parent_not_found("foo")));
162 assert_eq!(format!("{}", parent_not_found().unwrap_err().downcast_ref::<PathError>().unwrap()), "parent not found for path: foo");
163 }
164
165 #[test]
166 fn test_other_errors() {
167 assert_eq!(PathError::does_not_exist(Path::new("foo")), PathError::DoesNotExist(PathBuf::from("foo")));
168 assert_eq!(format!("{}", PathError::DoesNotExist(PathBuf::from("foo"))), "path does not exist: foo");
169 assert_eq!(format!("{}", PathError::Empty), "path empty");
170 assert_eq!(PathError::exists_already(Path::new("foo")), PathError::ExistsAlready(PathBuf::from("foo")));
171 assert_eq!(format!("{}", PathError::ExistsAlready(PathBuf::from("foo"))), "path exists already: foo");
172 assert_eq!(PathError::extension_not_found(Path::new("foo")), PathError::ExtensionNotFound(PathBuf::from("foo")));
173 assert_eq!(format!("{}", PathError::ExtensionNotFound(PathBuf::from("foo"))), "path extension not found: foo");
174 assert_eq!(PathError::failed_to_string(Path::new("foo")), PathError::FailedToString(PathBuf::from("foo")));
175 assert_eq!(format!("{}", PathError::failed_to_string(PathBuf::from("foo"))), "failed to convert to string for path: foo");
176 assert_eq!(PathError::filename_not_found(Path::new("foo")), PathError::FileNameNotFound(PathBuf::from("foo")));
177 assert_eq!(format!("{}", PathError::filename_not_found(PathBuf::from("foo"))), "filename not found for path: foo");
178 assert_eq!(PathError::invalid_expansion(Path::new("foo")), PathError::InvalidExpansion(PathBuf::from("foo")));
179 assert_eq!(format!("{}", PathError::invalid_expansion(PathBuf::from("foo"))), "invalid expansion for path: foo");
180 assert_eq!(PathError::is_not_dir(Path::new("foo")), PathError::IsNotDir(PathBuf::from("foo")));
181 assert_eq!(format!("{}", PathError::is_not_dir(PathBuf::from("foo"))), "is not a directory: foo");
182 assert_eq!(PathError::is_not_exec(Path::new("foo")), PathError::IsNotExec(PathBuf::from("foo")));
183 assert_eq!(format!("{}", PathError::is_not_exec(PathBuf::from("foo"))), "is not an executable: foo");
184 assert_eq!(PathError::is_not_file(Path::new("foo")), PathError::IsNotFile(PathBuf::from("foo")));
185 assert_eq!(format!("{}", PathError::is_not_file(PathBuf::from("foo"))), "is not a file: foo");
186 assert_eq!(PathError::is_not_file_or_symlink_to_file(Path::new("foo")), PathError::IsNotFileOrSymlinkToFile(PathBuf::from("foo")));
187 assert_eq!(format!("{}", PathError::is_not_file_or_symlink_to_file(PathBuf::from("foo"))), "is not a file or a symlink to a file: foo");
188 assert_eq!(PathError::multiple_home_symbols(Path::new("foo")), PathError::MultipleHomeSymbols(PathBuf::from("foo")));
189 assert_eq!(format!("{}", PathError::multiple_home_symbols(PathBuf::from("foo"))), "multiple home symbols for path: foo");
190 }
191
192 #[test]
193 fn test_backtrace() {
194 let err = path_empty().unwrap_err();
195 println!("{:?}", err);
196 }
197}