1pub type Result<T, E = Error> = std::result::Result<T, E>;
5
6#[derive(Debug)]
7pub enum Error {
8 Io(std::io::Error),
9 NotFound(String),
10 Library(libloading::Error),
11 JpegEncoding(jpeg_encoder::EncodingError),
12 #[cfg(feature = "codec")]
13 Codec(edgefirst_codec::CodecError),
14 ResizeImageBuffer(fast_image_resize::ImageBufferError),
15 Resize(fast_image_resize::ResizeError),
16 Yuv(yuv::YuvError),
17 #[cfg(target_os = "linux")]
18 G2D(g2d_sys::Error),
19 Tensor(edgefirst_tensor::Error),
20 NotImplemented(String),
21 NotSupported(String),
22 InvalidShape(String),
23 AliasedBuffers(String),
26 #[cfg(feature = "opengl")]
27 EGL(edgefirst_egl::Error),
28 GLVersion(String),
29 #[cfg(feature = "opengl")]
30 EGLLoad(edgefirst_egl::LoadError<libloading::Error>),
31 #[cfg(target_os = "linux")]
32 #[cfg(feature = "opengl")]
33 GbmInvalidFd(gbm::InvalidFdError),
34 #[cfg(target_os = "linux")]
35 #[cfg(feature = "opengl")]
36 GbmFrontBuffer(gbm::FrontBufferError),
37 OpenGl(String),
38 Internal(String),
39 CropInvalid(String),
40 ForcedBackendUnavailable(String),
41 NoConverter,
42 NotAnImage,
43 UnsupportedFormat(String),
44}
45
46impl From<std::io::Error> for Error {
47 fn from(err: std::io::Error) -> Self {
48 Error::Io(err)
49 }
50}
51
52impl From<libloading::Error> for Error {
53 fn from(err: libloading::Error) -> Self {
54 Error::Library(err)
55 }
56}
57
58impl From<jpeg_encoder::EncodingError> for Error {
59 fn from(err: jpeg_encoder::EncodingError) -> Self {
60 Error::JpegEncoding(err)
61 }
62}
63
64#[cfg(feature = "codec")]
65impl From<edgefirst_codec::CodecError> for Error {
66 fn from(err: edgefirst_codec::CodecError) -> Self {
67 Error::Codec(err)
68 }
69}
70
71impl From<fast_image_resize::ImageBufferError> for Error {
72 fn from(err: fast_image_resize::ImageBufferError) -> Self {
73 Error::ResizeImageBuffer(err)
74 }
75}
76
77impl From<fast_image_resize::ResizeError> for Error {
78 fn from(err: fast_image_resize::ResizeError) -> Self {
79 Error::Resize(err)
80 }
81}
82
83impl From<yuv::YuvError> for Error {
84 fn from(err: yuv::YuvError) -> Self {
85 Error::Yuv(err)
86 }
87}
88
89#[cfg(target_os = "linux")]
90impl From<g2d_sys::Error> for Error {
91 fn from(err: g2d_sys::Error) -> Self {
92 Error::G2D(err)
93 }
94}
95
96impl From<edgefirst_tensor::Error> for Error {
97 fn from(err: edgefirst_tensor::Error) -> Self {
98 Error::Tensor(err)
99 }
100}
101
102#[cfg(feature = "opengl")]
103impl From<edgefirst_egl::Error> for Error {
104 fn from(err: edgefirst_egl::Error) -> Self {
105 Error::EGL(err)
106 }
107}
108
109#[cfg(feature = "opengl")]
110impl From<edgefirst_egl::LoadError<libloading::Error>> for Error {
111 fn from(err: edgefirst_egl::LoadError<libloading::Error>) -> Self {
112 Error::EGLLoad(err)
113 }
114}
115
116#[cfg(target_os = "linux")]
117#[cfg(feature = "opengl")]
118impl From<gbm::InvalidFdError> for Error {
119 fn from(err: gbm::InvalidFdError) -> Self {
120 Error::GbmInvalidFd(err)
121 }
122}
123
124#[cfg(target_os = "linux")]
125#[cfg(feature = "opengl")]
126impl From<gbm::FrontBufferError> for Error {
127 fn from(err: gbm::FrontBufferError) -> Self {
128 Error::GbmFrontBuffer(err)
129 }
130}
131
132#[cfg(target_os = "linux")]
133#[cfg(feature = "opengl")]
134impl From<edgefirst_gl::Error> for Error {
135 fn from(err: edgefirst_gl::Error) -> Self {
136 Error::OpenGl(err.to_string())
137 }
138}
139
140impl From<ndarray::ShapeError> for Error {
141 fn from(err: ndarray::ShapeError) -> Self {
142 Error::Internal(format!("{err}"))
143 }
144}
145
146impl From<fast_image_resize::CropBoxError> for Error {
147 fn from(err: fast_image_resize::CropBoxError) -> Self {
148 Error::Internal(format!("{err}"))
149 }
150}
151
152impl std::fmt::Display for Error {
153 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
154 write!(f, "{self:?}")
155 }
156}
157
158impl std::error::Error for Error {}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn test_image_error_display() {
166 let e = Error::Io(std::io::Error::new(
167 std::io::ErrorKind::NotFound,
168 "file missing",
169 ));
170 let msg = e.to_string();
171 assert!(!msg.is_empty());
172 assert!(
173 msg.contains("Io") && msg.contains("file missing"),
174 "unexpected Io message: {msg}"
175 );
176
177 let e = Error::NotFound("texture.png".to_string());
178 let msg = e.to_string();
179 assert!(!msg.is_empty());
180 assert!(
181 msg.contains("NotFound") && msg.contains("texture.png"),
182 "unexpected NotFound message: {msg}"
183 );
184
185 let e = Error::Tensor(edgefirst_tensor::Error::InvalidSize(42));
186 let msg = e.to_string();
187 assert!(!msg.is_empty());
188 assert!(
189 msg.contains("Tensor") && msg.contains("InvalidSize"),
190 "unexpected Tensor message: {msg}"
191 );
192
193 let e = Error::NotImplemented("webp".to_string());
194 let msg = e.to_string();
195 assert!(!msg.is_empty());
196 assert!(
197 msg.contains("NotImplemented") && msg.contains("webp"),
198 "unexpected NotImplemented message: {msg}"
199 );
200
201 let e = Error::NotSupported("bmp format".to_string());
202 let msg = e.to_string();
203 assert!(!msg.is_empty());
204 assert!(
205 msg.contains("NotSupported") && msg.contains("bmp format"),
206 "unexpected NotSupported message: {msg}"
207 );
208
209 let e = Error::InvalidShape("wrong dims".to_string());
210 let msg = e.to_string();
211 assert!(!msg.is_empty());
212 assert!(
213 msg.contains("InvalidShape") && msg.contains("wrong dims"),
214 "unexpected InvalidShape message: {msg}"
215 );
216
217 let e = Error::GLVersion("4.5 required".to_string());
218 let msg = e.to_string();
219 assert!(!msg.is_empty());
220 assert!(
221 msg.contains("GLVersion") && msg.contains("4.5 required"),
222 "unexpected GLVersion message: {msg}"
223 );
224
225 let e = Error::OpenGl("shader compile failed".to_string());
226 let msg = e.to_string();
227 assert!(!msg.is_empty());
228 assert!(
229 msg.contains("OpenGl") && msg.contains("shader compile failed"),
230 "unexpected OpenGl message: {msg}"
231 );
232
233 let e = Error::Internal("unexpected state".to_string());
234 let msg = e.to_string();
235 assert!(!msg.is_empty());
236 assert!(
237 msg.contains("Internal") && msg.contains("unexpected state"),
238 "unexpected Internal message: {msg}"
239 );
240
241 let e = Error::CropInvalid("out of bounds".to_string());
242 let msg = e.to_string();
243 assert!(!msg.is_empty());
244 assert!(
245 msg.contains("CropInvalid") && msg.contains("out of bounds"),
246 "unexpected CropInvalid message: {msg}"
247 );
248
249 let e = Error::ForcedBackendUnavailable("g2d".to_string());
250 let msg = e.to_string();
251 assert!(!msg.is_empty());
252 assert!(
253 msg.contains("ForcedBackendUnavailable") && msg.contains("g2d"),
254 "unexpected ForcedBackendUnavailable message: {msg}"
255 );
256
257 let e = Error::NoConverter;
258 let msg = e.to_string();
259 assert!(!msg.is_empty());
260 assert!(
261 msg.contains("NoConverter"),
262 "unexpected NoConverter message: {msg}"
263 );
264
265 let e = Error::NotAnImage;
266 let msg = e.to_string();
267 assert!(!msg.is_empty());
268 assert!(
269 msg.contains("NotAnImage"),
270 "unexpected NotAnImage message: {msg}"
271 );
272
273 let e = Error::UnsupportedFormat("tiff".to_string());
274 let msg = e.to_string();
275 assert!(!msg.is_empty());
276 assert!(
277 msg.contains("UnsupportedFormat") && msg.contains("tiff"),
278 "unexpected UnsupportedFormat message: {msg}"
279 );
280 }
281}