1use std::convert::Infallible;
2use std::error::Error as StdError;
3use std::fmt::Result as FmtResult;
4use std::fmt::{Display, Formatter};
5use std::result::Result as StdResult;
6
7pub const WRONG_OFFSET: &str = "Wrong buffer offset detected";
9
10#[derive(Debug)]
12#[non_exhaustive]
13pub enum Error {
14    Invalid {
16        desc: String,
17        source: Option<Box<dyn StdError + Send + Sync + 'static>>,
18    },
19
20    Read {
23        desc: String,
24        source: Option<Box<dyn StdError + Send + Sync + 'static>>,
25    },
26
27    Write {
30        desc: String,
31        source: Option<Box<dyn StdError + Send + Sync + 'static>>,
32    },
33
34    NotImplemented { desc: String },
37
38    Internal {
42        desc: String,
43        source: Option<Box<dyn StdError + Send + Sync + 'static>>,
44    },
45}
46
47impl Error {
48    pub fn invalid<T, C>(desc: C) -> Result<T>
50    where
51        C: Display + Send + Sync + 'static,
52    {
53        Err(Error::Invalid {
54            desc: desc.to_string(),
55            source: None,
56        })
57    }
58
59    pub fn not_implemented<T, C>(desc: C) -> Result<T>
61    where
62        C: Display + Send + Sync + 'static,
63    {
64        Err(Error::NotImplemented {
65            desc: desc.to_string(),
66        })
67    }
68
69    pub fn internal<T, C>(desc: C) -> Result<T>
71    where
72        C: Display + Send + Sync + 'static,
73    {
74        Err(Error::Internal {
75            desc: desc.to_string(),
76            source: None,
77        })
78    }
79}
80
81impl Display for Error {
82    fn fmt(&self, f: &mut Formatter) -> FmtResult {
83        match self {
84            Error::Invalid { desc, .. } => write!(f, "Invalid E57 content: {desc}"),
85            Error::Read { desc, .. } => write!(f, "Failed to read E57: {desc}"),
86            Error::Internal { desc, .. } => write!(f, "Internal error: {desc}"),
87            Error::NotImplemented { desc } => write!(f, "Not implemented: {desc}"),
88            Error::Write { desc, .. } => write!(f, "Failed to write E57: {desc}"),
89        }
90    }
91}
92
93impl StdError for Error {
94    fn source(&self) -> Option<&(dyn StdError + 'static)> {
95        match self {
96            Error::Invalid { source, .. } => source
97                .as_ref()
98                .map(|s| s.as_ref() as &(dyn StdError + 'static)),
99            Error::Read { source, .. } => source
100                .as_ref()
101                .map(|s| s.as_ref() as &(dyn StdError + 'static)),
102            Error::Internal { source, .. } => source
103                .as_ref()
104                .map(|s| s.as_ref() as &(dyn StdError + 'static)),
105            Error::Write { source, .. } => source
106                .as_ref()
107                .map(|s| s.as_ref() as &(dyn StdError + 'static)),
108            Error::NotImplemented { .. } => None,
109        }
110    }
111}
112
113pub type Result<T> = StdResult<T, Error>;
115
116pub trait Converter<T, E> {
118    fn read_err<C>(self, context: C) -> Result<T>
119    where
120        C: Display + Send + Sync + 'static;
121
122    fn invalid_err<C>(self, context: C) -> Result<T>
123    where
124        C: Display + Send + Sync + 'static;
125
126    fn internal_err<C>(self, context: C) -> Result<T>
127    where
128        C: Display + Send + Sync + 'static;
129
130    fn write_err<C>(self, context: C) -> Result<T>
131    where
132        C: Display + Send + Sync + 'static;
133}
134
135impl<T, E> Converter<T, E> for StdResult<T, E>
137where
138    E: StdError + Send + Sync + 'static,
139{
140    fn read_err<C>(self, desc: C) -> Result<T>
141    where
142        C: Display + Send + Sync + 'static,
143    {
144        match self {
145            Ok(ok) => Ok(ok),
146            Err(error) => Err(Error::Read {
147                desc: desc.to_string(),
148                source: Some(Box::new(error)),
149            }),
150        }
151    }
152
153    fn invalid_err<C>(self, desc: C) -> Result<T>
154    where
155        C: Display + Send + Sync + 'static,
156    {
157        match self {
158            Ok(ok) => Ok(ok),
159            Err(error) => Err(Error::Invalid {
160                desc: desc.to_string(),
161                source: Some(Box::new(error)),
162            }),
163        }
164    }
165
166    fn internal_err<C>(self, desc: C) -> Result<T>
167    where
168        C: Display + Send + Sync + 'static,
169    {
170        match self {
171            Ok(ok) => Ok(ok),
172            Err(error) => Err(Error::Internal {
173                desc: desc.to_string(),
174                source: Some(Box::new(error)),
175            }),
176        }
177    }
178
179    fn write_err<C>(self, desc: C) -> Result<T>
180    where
181        C: Display + Send + Sync + 'static,
182    {
183        match self {
184            Ok(ok) => Ok(ok),
185            Err(error) => Err(Error::Write {
186                desc: desc.to_string(),
187                source: Some(Box::new(error)),
188            }),
189        }
190    }
191}
192
193impl<T> Converter<T, Infallible> for Option<T> {
195    fn read_err<C>(self, desc: C) -> Result<T>
196    where
197        C: Display + Send + Sync + 'static,
198    {
199        match self {
200            Some(ok) => Ok(ok),
201            None => Err(Error::Read {
202                desc: desc.to_string(),
203                source: None,
204            }),
205        }
206    }
207
208    fn invalid_err<C>(self, desc: C) -> Result<T>
209    where
210        C: Display + Send + Sync + 'static,
211    {
212        match self {
213            Some(ok) => Ok(ok),
214            None => Err(Error::Invalid {
215                desc: desc.to_string(),
216                source: None,
217            }),
218        }
219    }
220
221    fn internal_err<C>(self, desc: C) -> Result<T>
222    where
223        C: Display + Send + Sync + 'static,
224    {
225        match self {
226            Some(ok) => Ok(ok),
227            None => Err(Error::Internal {
228                desc: desc.to_string(),
229                source: None,
230            }),
231        }
232    }
233
234    fn write_err<C>(self, desc: C) -> Result<T>
235    where
236        C: Display + Send + Sync + 'static,
237    {
238        match self {
239            Some(ok) => Ok(ok),
240            None => Err(Error::Write {
241                desc: desc.to_string(),
242                source: None,
243            }),
244        }
245    }
246}