foundry_common/errors/
fs.rs

1use std::{
2    io,
3    path::{Path, PathBuf},
4};
5
6#[expect(unused_imports)]
7use std::fs::{self, File};
8
9/// Various error variants for `fs` operations that serve as an addition to the io::Error which
10/// does not provide any information about the path.
11#[derive(Debug, thiserror::Error)]
12#[expect(missing_docs)]
13pub enum FsPathError {
14    /// Provides additional path context for [`fs::write`].
15    #[error("failed to write to {path:?}: {source}")]
16    Write { source: io::Error, path: PathBuf },
17    /// Provides additional path context for [`fs::read`].
18    #[error("failed to read from {path:?}: {source}")]
19    Read { source: io::Error, path: PathBuf },
20    /// Provides additional path context for [`fs::copy`].
21    #[error("failed to copy from {from:?} to {to:?}: {source}")]
22    Copy { source: io::Error, from: PathBuf, to: PathBuf },
23    /// Provides additional path context for [`fs::read_link`].
24    #[error("failed to read from {path:?}: {source}")]
25    ReadLink { source: io::Error, path: PathBuf },
26    /// Provides additional path context for [`File::create`].
27    #[error("failed to create file {path:?}: {source}")]
28    CreateFile { source: io::Error, path: PathBuf },
29    /// Provides additional path context for [`fs::remove_file`].
30    #[error("failed to remove file {path:?}: {source}")]
31    RemoveFile { source: io::Error, path: PathBuf },
32    /// Provides additional path context for [`fs::create_dir`].
33    #[error("failed to create dir {path:?}: {source}")]
34    CreateDir { source: io::Error, path: PathBuf },
35    /// Provides additional path context for [`fs::remove_dir`].
36    #[error("failed to remove dir {path:?}: {source}")]
37    RemoveDir { source: io::Error, path: PathBuf },
38    /// Provides additional path context for [`File::open`].
39    #[error("failed to open file {path:?}: {source}")]
40    Open { source: io::Error, path: PathBuf },
41    /// Provides additional path context for the file whose contents should be parsed as JSON.
42    #[error("failed to parse json file: {path:?}: {source}")]
43    ReadJson { source: serde_json::Error, path: PathBuf },
44    /// Provides additional path context for the new JSON file.
45    #[error("failed to write to json file: {path:?}: {source}")]
46    WriteJson { source: serde_json::Error, path: PathBuf },
47}
48
49impl FsPathError {
50    /// Returns the complementary error variant for [`fs::write`].
51    pub fn write(source: io::Error, path: impl Into<PathBuf>) -> Self {
52        Self::Write { source, path: path.into() }
53    }
54
55    /// Returns the complementary error variant for [`fs::read`].
56    pub fn read(source: io::Error, path: impl Into<PathBuf>) -> Self {
57        Self::Read { source, path: path.into() }
58    }
59
60    /// Returns the complementary error variant for [`fs::copy`].
61    pub fn copy(source: io::Error, from: impl Into<PathBuf>, to: impl Into<PathBuf>) -> Self {
62        Self::Copy { source, from: from.into(), to: to.into() }
63    }
64
65    /// Returns the complementary error variant for [`fs::read_link`].
66    pub fn read_link(source: io::Error, path: impl Into<PathBuf>) -> Self {
67        Self::ReadLink { source, path: path.into() }
68    }
69
70    /// Returns the complementary error variant for [`File::create`].
71    pub fn create_file(source: io::Error, path: impl Into<PathBuf>) -> Self {
72        Self::CreateFile { source, path: path.into() }
73    }
74
75    /// Returns the complementary error variant for [`fs::remove_file`].
76    pub fn remove_file(source: io::Error, path: impl Into<PathBuf>) -> Self {
77        Self::RemoveFile { source, path: path.into() }
78    }
79
80    /// Returns the complementary error variant for [`fs::create_dir`].
81    pub fn create_dir(source: io::Error, path: impl Into<PathBuf>) -> Self {
82        Self::CreateDir { source, path: path.into() }
83    }
84
85    /// Returns the complementary error variant for [`fs::remove_dir`].
86    pub fn remove_dir(source: io::Error, path: impl Into<PathBuf>) -> Self {
87        Self::RemoveDir { source, path: path.into() }
88    }
89
90    /// Returns the complementary error variant for [`File::open`].
91    pub fn open(source: io::Error, path: impl Into<PathBuf>) -> Self {
92        Self::Open { source, path: path.into() }
93    }
94}
95
96impl AsRef<Path> for FsPathError {
97    fn as_ref(&self) -> &Path {
98        match self {
99            Self::Write { path, .. } |
100            Self::Read { path, .. } |
101            Self::ReadLink { path, .. } |
102            Self::Copy { from: path, .. } |
103            Self::CreateDir { path, .. } |
104            Self::RemoveDir { path, .. } |
105            Self::CreateFile { path, .. } |
106            Self::RemoveFile { path, .. } |
107            Self::Open { path, .. } |
108            Self::ReadJson { path, .. } |
109            Self::WriteJson { path, .. } => path,
110        }
111    }
112}
113
114impl From<FsPathError> for io::Error {
115    fn from(value: FsPathError) -> Self {
116        match value {
117            FsPathError::Write { source, .. } |
118            FsPathError::Read { source, .. } |
119            FsPathError::ReadLink { source, .. } |
120            FsPathError::Copy { source, .. } |
121            FsPathError::CreateDir { source, .. } |
122            FsPathError::RemoveDir { source, .. } |
123            FsPathError::CreateFile { source, .. } |
124            FsPathError::RemoveFile { source, .. } |
125            FsPathError::Open { source, .. } => source,
126
127            FsPathError::ReadJson { source, .. } | FsPathError::WriteJson { source, .. } => {
128                source.into()
129            }
130        }
131    }
132}