async_vfs/
error.rs

1use std::fmt::Display;
2use thiserror::Error;
3
4#[derive(Error, Debug)]
5pub enum VfsError {
6    #[error("IO error: {0}")]
7    IoError(#[from] std::io::Error),
8
9    #[error("Invalid absolute path: {path}")]
10    InvalidAbsolutePath { path: String },
11
12    #[error("Invalid file: {path}")]
13    InvalidFile { path: String },
14
15    #[error("Unauthorized")]
16    Unauthorized,
17
18    #[error("Forbidden")]
19    Forbidden,
20
21    #[error("Not supported")]
22    NotSupported,
23
24    /// Generic error context, used for adding context to an error (like a path)
25    #[error("{context}, cause: {cause}")]
26    WithContext {
27        /// The context error message
28        context: String,
29        /// The underlying error
30        #[source]
31        cause: Box<VfsError>,
32    },
33}
34
35pub type VfsResult<T> = std::result::Result<T, VfsError>;
36
37pub(crate) trait VfsResultExt<T> {
38    fn with_context<C, F>(self, f: F) -> VfsResult<T>
39    where
40        C: Display + Send + Sync + 'static,
41        F: FnOnce() -> C;
42}
43
44impl<T> VfsResultExt<T> for VfsResult<T> {
45    fn with_context<C, F>(self, context: F) -> VfsResult<T>
46    where
47        C: Display + Send + Sync + 'static,
48        F: FnOnce() -> C,
49    {
50        self.map_err(|error| VfsError::WithContext {
51            context: context().to_string(),
52            cause: Box::new(error),
53        })
54    }
55}