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