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    #[error("failed to lock file {path:?}: {source}")]
42    Lock { source: io::Error, path: PathBuf },
43    #[error("failed to unlock file {path:?}: {source}")]
44    Unlock { source: io::Error, path: PathBuf },
45    /// Provides additional path context for the file whose contents should be parsed as JSON.
46    #[error("failed to parse json file: {path:?}: {source}")]
47    ReadJson { source: serde_json::Error, path: PathBuf },
48    /// Provides additional path context for the new JSON file.
49    #[error("failed to write to json file: {path:?}: {source}")]
50    WriteJson { source: serde_json::Error, path: PathBuf },
51}
52
53impl FsPathError {
54    /// Returns the complementary error variant for [`fs::write`].
55    pub fn write(source: io::Error, path: impl Into<PathBuf>) -> Self {
56        Self::Write { source, path: path.into() }
57    }
58
59    /// Returns the complementary error variant for [`fs::read`].
60    pub fn read(source: io::Error, path: impl Into<PathBuf>) -> Self {
61        Self::Read { source, path: path.into() }
62    }
63
64    /// Returns the complementary error variant for [`fs::copy`].
65    pub fn copy(source: io::Error, from: impl Into<PathBuf>, to: impl Into<PathBuf>) -> Self {
66        Self::Copy { source, from: from.into(), to: to.into() }
67    }
68
69    /// Returns the complementary error variant for [`fs::read_link`].
70    pub fn read_link(source: io::Error, path: impl Into<PathBuf>) -> Self {
71        Self::ReadLink { source, path: path.into() }
72    }
73
74    /// Returns the complementary error variant for [`File::create`].
75    pub fn create_file(source: io::Error, path: impl Into<PathBuf>) -> Self {
76        Self::CreateFile { source, path: path.into() }
77    }
78
79    /// Returns the complementary error variant for [`fs::remove_file`].
80    pub fn remove_file(source: io::Error, path: impl Into<PathBuf>) -> Self {
81        Self::RemoveFile { source, path: path.into() }
82    }
83
84    /// Returns the complementary error variant for [`fs::create_dir`].
85    pub fn create_dir(source: io::Error, path: impl Into<PathBuf>) -> Self {
86        Self::CreateDir { source, path: path.into() }
87    }
88
89    /// Returns the complementary error variant for [`fs::remove_dir`].
90    pub fn remove_dir(source: io::Error, path: impl Into<PathBuf>) -> Self {
91        Self::RemoveDir { source, path: path.into() }
92    }
93
94    /// Returns the complementary error variant for [`File::open`].
95    pub fn open(source: io::Error, path: impl Into<PathBuf>) -> Self {
96        Self::Open { source, path: path.into() }
97    }
98
99    /// Returns the complementary error variant for [`File::lock`].
100    pub fn lock(source: io::Error, path: impl Into<PathBuf>) -> Self {
101        Self::Lock { source, path: path.into() }
102    }
103
104    /// Returns the complementary error variant for [`File::unlock`].
105    pub fn unlock(source: io::Error, path: impl Into<PathBuf>) -> Self {
106        Self::Unlock { source, path: path.into() }
107    }
108}
109
110impl AsRef<Path> for FsPathError {
111    fn as_ref(&self) -> &Path {
112        match self {
113            Self::Write { path, .. }
114            | Self::Read { path, .. }
115            | Self::ReadLink { path, .. }
116            | Self::Copy { from: path, .. }
117            | Self::CreateDir { path, .. }
118            | Self::RemoveDir { path, .. }
119            | Self::CreateFile { path, .. }
120            | Self::RemoveFile { path, .. }
121            | Self::Open { path, .. }
122            | Self::Lock { path, .. }
123            | Self::Unlock { path, .. }
124            | Self::ReadJson { path, .. }
125            | Self::WriteJson { path, .. } => path,
126        }
127    }
128}
129
130impl From<FsPathError> for io::Error {
131    fn from(value: FsPathError) -> Self {
132        match value {
133            FsPathError::Write { source, .. }
134            | FsPathError::Read { source, .. }
135            | FsPathError::ReadLink { source, .. }
136            | FsPathError::Copy { source, .. }
137            | FsPathError::CreateDir { source, .. }
138            | FsPathError::RemoveDir { source, .. }
139            | FsPathError::CreateFile { source, .. }
140            | FsPathError::RemoveFile { source, .. }
141            | FsPathError::Open { source, .. }
142            | FsPathError::Lock { source, .. }
143            | FsPathError::Unlock { source, .. } => source,
144
145            FsPathError::ReadJson { source, .. } | FsPathError::WriteJson { source, .. } => {
146                source.into()
147            }
148        }
149    }
150}