dir_structure/
error.rs

1//! Error type, see [`Error`].
2
3use std::error;
4use std::fmt;
5use std::io;
6use std::result;
7
8use crate::prelude::PathType;
9use crate::prelude::VfsCore;
10use crate::traits::vfs;
11use crate::traits::vfs::OwnedPathType;
12
13/// The error type for this library.
14#[derive(Debug)]
15pub enum Error<P> {
16    /// An IO error.
17    Io(P, io::Error),
18    /// Parse error.
19    Parse(P, Box<dyn error::Error + Send + Sync>),
20    /// Write error.
21    Write(P, Box<dyn error::Error + Send + Sync>),
22    /// Serde error.
23    Serde(P, Box<dyn error::Error + Send + Sync>),
24
25    /// An error related to the directory structure.
26    UnexpectedNumberOfChildren {
27        /// The expected number of children.
28        expected: &'static str,
29        /// How many children were found.
30        found: usize,
31        /// The path to the directory where this happened.
32        path: P,
33    },
34}
35
36impl<P: fmt::Debug> error::Error for Error<P> {
37    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
38        match self {
39            Self::Io(_, e) => Some(e),
40            Self::Parse(_, e) => Some(e.as_ref()),
41            Self::Write(_, e) => Some(e.as_ref()),
42            Self::Serde(_, e) => Some(e.as_ref()),
43            Self::UnexpectedNumberOfChildren { .. } => None,
44        }
45    }
46}
47
48impl<P: fmt::Debug> fmt::Display for Error<P> {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        match self {
51            Self::Io(path, e) => write!(f, "IO error at {:?}: {}", path, e),
52            Self::Parse(path, e) => write!(f, "Parse error at {:?}: {}", path, e),
53            Self::Write(path, e) => write!(f, "Write error at {:?}: {}", path, e),
54            Self::Serde(path, e) => write!(f, "Serde error at {:?}: {}", path, e),
55            Self::UnexpectedNumberOfChildren {
56                expected,
57                found,
58                path,
59            } => write!(
60                f,
61                "Unexpected number of children: expected {}, found {} at {:?}",
62                expected, found, path
63            ),
64        }
65    }
66}
67
68mod sealed {
69    use std::io;
70
71    pub trait Sealed {}
72
73    impl<T> Sealed for io::Result<T> {}
74}
75
76/// A trait for wrapping IO errors with the path where they happened, turning [`std::io::Result`]s into [`crate::error::Result`]s.
77pub trait WrapIoError<PathType: vfs::PathType + ?Sized>: Sized + sealed::Sealed {
78    /// The inner type.
79    type Output;
80
81    /// Wrap the IO error with the path where it happened.
82    fn wrap_io_error(
83        self,
84        get_path: impl FnOnce() -> PathType::OwnedPath,
85    ) -> Result<Self::Output, PathType::OwnedPath>;
86
87    /// Wrap the IO error with the given path.
88    fn wrap_io_error_with(self, path: &PathType) -> Result<Self::Output, PathType::OwnedPath> {
89        self.wrap_io_error(|| path.owned())
90    }
91}
92
93impl<T, P: vfs::PathType + ?Sized> WrapIoError<P> for io::Result<T> {
94    type Output = T;
95
96    fn wrap_io_error(
97        self,
98        get_path: impl FnOnce() -> P::OwnedPath,
99    ) -> Result<Self::Output, P::OwnedPath> {
100        self.map_err(|e| Error::Io(get_path(), e))
101    }
102}
103
104/// The result type for this library.
105///
106/// See [the `Error` enum](Error) for the errors that can happen.
107#[expect(type_alias_bounds)]
108pub type Result<T, P: OwnedPathType> = result::Result<T, Error<P>>;
109
110/// A convenience result type for a specific VFS.
111#[expect(type_alias_bounds)]
112pub type VfsResult<T, Vfs: VfsCore> = Result<T, <Vfs::Path as PathType>::OwnedPath>;