simple_fs/
error.rs

1use crate::SPath;
2use derive_more::{Display, From};
3use std::io;
4use std::path::Path;
5use std::time::SystemTimeError;
6
7pub type Result<T> = core::result::Result<T, Error>;
8
9#[derive(Debug, Display)]
10pub enum Error {
11	// -- Path
12	#[display("Path is not valid UTF-8: '{_0}'")]
13	PathNotUtf8(String),
14	#[display("Home directory not found")]
15	HomeDirNotFound,
16	#[display("Path has no file name: '{_0}'")]
17	PathHasNoFileName(String),
18	#[display("Strip Prefix fail. Path '{path}' does not a base of '{prefix}'")]
19	StripPrefix {
20		prefix: String,
21		path: String,
22	},
23
24	// -- File
25	#[display("File not found at path: '{_0}'")]
26	FileNotFound(String),
27	#[display("Cannot open file '{}'\nCause: {}", _0.path, _0.cause)]
28	FileCantOpen(PathAndCause),
29	#[display("Cannot read path '{}'\nCause: {}", _0.path, _0.cause)]
30	FileCantRead(PathAndCause),
31	#[display("Cannot write file '{}'\nCause: {}", _0.path, _0.cause)]
32	FileCantWrite(PathAndCause),
33	#[display("Cannot create file '{}'\nCause: {}", _0.path, _0.cause)]
34	FileCantCreate(PathAndCause),
35	#[display("File path has no parent directory: '{_0}'")]
36	FileHasNoParent(String),
37
38	// -- Remove
39	#[display("File not safe to remove.\nPath: '{}'\nCause: {}", _0.path, _0.cause)]
40	FileNotSafeToRemove(PathAndCause),
41	#[display("Directory not safe to remove.\nPath: '{}'\nCause: {}", _0.path, _0.cause)]
42	DirNotSafeToRemove(PathAndCause),
43
44	// -- Trash
45	#[display("File not safe to trash.\nPath: '{}'\nCause: {}", _0.path, _0.cause)]
46	FileNotSafeToTrash(PathAndCause),
47	#[display("Directory not safe to trash.\nPath: '{}'\nCause: {}", _0.path, _0.cause)]
48	DirNotSafeToTrash(PathAndCause),
49	#[display("Cannot trash path '{}'\nCause: {}", _0.path, _0.cause)]
50	CantTrash(PathAndCause),
51
52	// -- Sort
53	#[display("Cannot sort by globs.\nCause: {cause}")]
54	SortByGlobs {
55		cause: String,
56	},
57
58	// -- Metadata
59	#[display("Cannot get metadata for path '{}'\nCause: {}", _0.path, _0.cause)]
60	CantGetMetadata(PathAndCause),
61	#[display("Cannot get 'modified' metadata for path '{}'\nCause: {}", _0.path, _0.cause)]
62	CantGetMetadataModified(PathAndCause),
63
64	// -- Time
65	#[display("Cannot get duration from system time. Cause: {_0}")]
66	CantGetDurationSystemTimeError(SystemTimeError),
67
68	// -- Directory
69	#[display("Cannot create directory (and parents) '{}'\nCause: {}", _0.path, _0.cause)]
70	DirCantCreateAll(PathAndCause),
71
72	// -- Path Validations
73	#[display("Path is invalid: '{}'\nCause: {}",_0.path, _0.cause)]
74	PathNotValidForPath(PathAndCause),
75
76	// -- Glob
77	#[display("Cannot create glob pattern '{glob}'.\nCause: {cause}")]
78	GlobCantNew {
79		glob: String,
80		cause: globset::Error,
81	},
82	#[display("Cannot build glob set from '{globs:?}'.\nCause: {cause}")]
83	GlobSetCantBuild {
84		globs: Vec<String>,
85		cause: globset::Error,
86	},
87
88	// -- Watch
89	#[display("Failed to watch path '{path}'.\nCause: {cause}")]
90	FailToWatch {
91		path: String,
92		cause: String,
93	},
94	#[display("Cannot watch path because it was not found: '{_0}'")]
95	CantWatchPathNotFound(String),
96
97	// -- Span
98	SpanInvalidStartAfterEnd,
99	SpanOutOfBounds,
100	SpanInvalidUtf8,
101
102	// -- Other
103	#[display("Cannot compute relative path from '{base}' to '{path}'")]
104	CannotDiff {
105		path: String,
106		base: String,
107	},
108	#[display("Cannot Canonicalize path '{}'\nCause: {}", _0.path, _0.cause)]
109	CannotCanonicalize(PathAndCause),
110
111	// -- with-json
112	#[cfg(feature = "with-json")]
113	#[display("Cannot read json path '{}'\nCause: {}", _0.path, _0.cause)]
114	JsonCantRead(PathAndCause),
115	#[cfg(feature = "with-json")]
116	#[display("Cannot write JSON to path '{}'\nCause: {}", _0.path, _0.cause)]
117	JsonCantWrite(PathAndCause),
118	#[cfg(feature = "with-json")]
119	#[display("Error processing NDJSON: {_0}")]
120	NdJson(String),
121
122	// -- with-toml
123	#[cfg(feature = "with-toml")]
124	#[display("Cannot read TOML from path '{}'\nCause: {}", _0.path, _0.cause)]
125	TomlCantRead(PathAndCause),
126	#[cfg(feature = "with-toml")]
127	#[display("Cannot write TOML to path '{}'\nCause: {}", _0.path, _0.cause)]
128	TomlCantWrite(PathAndCause),
129}
130
131impl Error {
132	pub fn sort_by_globs(cause: impl std::fmt::Display) -> Error {
133		Error::SortByGlobs {
134			cause: cause.to_string(),
135		}
136	}
137}
138
139// region:    --- Cause Types
140
141#[derive(Debug, Display, From)]
142pub enum Cause {
143	#[from]
144	Custom(String),
145
146	#[from]
147	Io(Box<io::Error>),
148
149	#[cfg(feature = "with-json")]
150	SerdeJson(Box<serde_json::Error>),
151
152	#[cfg(feature = "with-toml")]
153	TomlDe(Box<toml::de::Error>),
154
155	#[cfg(feature = "with-toml")]
156	TomlSer(Box<toml::ser::Error>),
157}
158
159#[derive(Debug)]
160pub struct PathAndCause {
161	pub path: String,
162	pub cause: Cause,
163}
164
165// endregion: --- Cause Types
166
167// region:    --- IO
168
169impl From<(&Path, io::Error)> for PathAndCause {
170	fn from(val: (&Path, io::Error)) -> Self {
171		PathAndCause {
172			path: val.0.to_string_lossy().to_string(),
173			cause: Cause::Io(Box::new(val.1)),
174		}
175	}
176}
177
178impl From<(&SPath, io::Error)> for PathAndCause {
179	fn from(val: (&SPath, io::Error)) -> Self {
180		PathAndCause {
181			path: val.0.to_string(),
182			cause: Cause::Io(Box::new(val.1)),
183		}
184	}
185}
186
187//std::time::SystemTimeError
188impl From<(&SPath, std::time::SystemTimeError)> for PathAndCause {
189	fn from(val: (&SPath, std::time::SystemTimeError)) -> Self {
190		PathAndCause {
191			path: val.0.to_string(),
192			cause: Cause::Custom(val.1.to_string()),
193		}
194	}
195}
196
197// endregion: --- IO
198
199// region:    --- JSON
200
201#[cfg(feature = "with-json")]
202impl From<(&Path, serde_json::Error)> for PathAndCause {
203	fn from(val: (&Path, serde_json::Error)) -> Self {
204		PathAndCause {
205			path: val.0.to_string_lossy().to_string(),
206			cause: Cause::SerdeJson(Box::new(val.1)),
207		}
208	}
209}
210
211// endregion: --- JSON
212
213// region:    --- TOML
214
215#[cfg(feature = "with-toml")]
216impl From<(&Path, toml::de::Error)> for PathAndCause {
217	fn from(val: (&Path, toml::de::Error)) -> Self {
218		PathAndCause {
219			path: val.0.to_string_lossy().to_string(),
220			cause: Cause::TomlDe(Box::new(val.1)),
221		}
222	}
223}
224
225#[cfg(feature = "with-toml")]
226impl From<(&Path, toml::ser::Error)> for PathAndCause {
227	fn from(val: (&Path, toml::ser::Error)) -> Self {
228		PathAndCause {
229			path: val.0.to_string_lossy().to_string(),
230			cause: Cause::TomlSer(Box::new(val.1)),
231		}
232	}
233}
234
235// endregion: --- TOML
236
237// region:    --- Error Boilerplate
238
239impl std::error::Error for Error {}
240
241// endregion: --- Error Boilerplate