1use super::*;
2
3pub type IoResult<T = ()> = Result<T, IoError>;
4
5#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
6pub enum IoMode
7{
8 Read,
9 Write,
10}
11
12impl Display for IoMode
13{
14 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
15 {
16 match self
17 {
18 IoMode::Read => f.write_str("Read"),
19 IoMode::Write => f.write_str("Write"),
20 }
21 }
22}
23
24impl IoMode
25{
26 pub const fn is_read(self) -> bool { matches!(self, Self::Read) }
27 pub const fn is_write(self) -> bool { matches!(self, Self::Write) }
28}
29
30#[derive(Default, Clone, PartialEq, Eq)]
31pub struct IoError
32{
33 pub path: PathBuf,
34 pub mode: Option<IoMode>,
35 pub kind: FileError,
36}
37impl IoError
38{
39 pub fn new(path: impl Into<PathBuf>, kind: impl Into<FileError>) -> Self
40 {
41 Self {
42 path: path.into(),
43 kind: kind.into(),
44 mode: None,
45 }
46 }
47 pub fn with_mode(self, mode: Option<IoMode>) -> Self { Self { mode, ..self } }
48 pub fn when_reading(self) -> Self
49 {
50 Self {
51 mode: Some(IoMode::Read),
52 ..self
53 }
54 }
55 pub fn when_writing(self) -> Self
56 {
57 Self {
58 mode: Some(IoMode::Write),
59 ..self
60 }
61 }
62}
63impl Display for IoError
64{
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
66 {
67 write!(f, "IO error at {:?} ", self.path)?;
68 if let Some(mode) = self.mode
69 {
70 match mode
71 {
72 IoMode::Read => write!(f, "when reading")?,
73 IoMode::Write => write!(f, "when writing")?,
74 }
75 }
76 write!(f, ": {}", self.kind)
77 }
78}
79impl std::fmt::Debug for IoError
80{
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self) }
82}
83
84impl std::error::Error for IoError {}
85
86#[cfg(feature = "serde")]
87impl serde::ser::Error for IoError
88{
89 fn custom<T>(msg: T) -> Self
90 where
91 T: std::fmt::Display,
92 {
93 Self {
94 kind: FileError::custom(msg.to_string()),
95 ..Default::default()
96 }
97 }
98}
99#[cfg(feature = "serde")]
100impl serde::de::Error for IoError
101{
102 fn custom<T>(msg: T) -> Self
103 where
104 T: std::fmt::Display,
105 {
106 Self {
107 kind: FileError::custom(msg.to_string()),
108 ..Default::default()
109 }
110 }
111}
112
113pub type FileResult<T = ()> = Result<T, FileError>;
114
115#[non_exhaustive]
116#[derive(Default, Clone, PartialEq, Eq)]
117pub enum FileError
118{
119 #[default]
120 Unknow,
121 NotSupported,
122 DownloadFailed,
123 Unimplemented,
124 NotFound,
125 Custom(Reason),
126 Std(std::io::ErrorKind),
127 Encoding(EncodeError),
128}
129impl From<EncodeError> for FileError
130{
131 fn from(value: EncodeError) -> Self { Self::Encoding(value) }
132}
133impl From<String> for FileError
134{
135 fn from(custom: String) -> Self { Self::Custom(custom.into()) }
136}
137impl From<&'static str> for FileError
138{
139 fn from(custom: &'static str) -> Self { Self::Custom(custom.into()) }
140}
141
142impl From<FromUtf8Error> for FileError
143{
144 fn from(value: FromUtf8Error) -> Self { value.utf8_error().into() }
145}
146impl From<Utf8Error> for FileError
147{
148 fn from(value: Utf8Error) -> Self { FileError::Encoding(value.into()) }
149}
150impl From<Base64Error> for FileError
151{
152 fn from(value: Base64Error) -> Self { FileError::Encoding(value.into()) }
153}
154impl From<std::io::Error> for FileError
155{
156 fn from(value: std::io::Error) -> Self { value.kind().into() }
157}
158impl From<std::io::ErrorKind> for FileError
159{
160 fn from(kind: std::io::ErrorKind) -> Self { Self::Std(kind) }
161}
162impl From<std::fmt::Error> for FileError
163{
164 fn from(value: std::fmt::Error) -> Self { Self::Encoding(value.into()) }
165}
166
167impl FileError
168{
169 pub fn custom(reason: impl Into<Reason>) -> Self { Self::Custom(reason.into()) }
170 pub fn from_display(reason: impl Display) -> Self { Self::custom(reason.to_string()) }
171
172 pub fn is_encoding(&self) -> bool { matches!(self, Self::Encoding(_)) }
173}
174
175impl Display for FileError
176{
177 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
178 {
179 match self
180 {
181 FileError::Unknow => f.write_str("unknow"),
182 FileError::Unimplemented => f.write_str("unimplemented"),
183 FileError::NotSupported => f.write_str("not supported"),
184 FileError::DownloadFailed => f.write_str("download failed"),
185 FileError::NotFound => f.write_str("not found"),
186 FileError::Custom(reason) => write!(f, "custom: {reason}"),
187 FileError::Std(kind) => write!(f, "std: {kind}"),
188 FileError::Encoding(encode_error) => write!(f, "encoding: {encode_error}"),
189 }
190 }
191}
192impl std::fmt::Debug for FileError
193{
194 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self) }
195}
196
197impl std::error::Error for FileError {}
198#[cfg(feature = "serde")]
199impl serde::ser::Error for FileError
200{
201 fn custom<T>(msg: T) -> Self
202 where
203 T: std::fmt::Display,
204 {
205 Self::custom(msg.to_string())
206 }
207}
208#[cfg(feature = "serde")]
209impl serde::de::Error for FileError
210{
211 fn custom<T>(msg: T) -> Self
212 where
213 T: std::fmt::Display,
214 {
215 Self::custom(msg.to_string())
216 }
217}