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