Skip to main content

hexga_io/
result.rs

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}