foundry_common/errors/
fs.rs

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