zenpixels_convert/
error.rs1use crate::{PixelDescriptor, TransferFunction};
4use core::fmt;
5
6#[derive(Debug, Clone, PartialEq)]
9pub enum ConvertError {
10 NoMatch { source: PixelDescriptor },
12 NoPath {
14 from: PixelDescriptor,
15 to: PixelDescriptor,
16 },
17 BufferSize { expected: usize, actual: usize },
19 InvalidWidth(u32),
21 EmptyFormatList,
23 UnsupportedTransfer {
25 from: TransferFunction,
26 to: TransferFunction,
27 },
28 AlphaNotOpaque,
30 DepthReductionForbidden,
32 AlphaRemovalForbidden,
34 RgbToGray,
36 AllocationFailed,
38 CmsError(alloc::string::String),
40 }
45
46impl fmt::Display for ConvertError {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 match self {
49 Self::NoMatch { source } => {
50 write!(
51 f,
52 "no supported format matches source {:?}/{:?}",
53 source.channel_type(),
54 source.layout()
55 )
56 }
57 Self::NoPath { from, to } => {
58 write!(
59 f,
60 "no conversion path from {:?}/{:?} to {:?}/{:?}",
61 from.channel_type(),
62 from.layout(),
63 to.channel_type(),
64 to.layout()
65 )
66 }
67 Self::BufferSize { expected, actual } => {
68 write!(
69 f,
70 "buffer size mismatch: expected {expected} bytes, got {actual}"
71 )
72 }
73 Self::InvalidWidth(w) => write!(f, "invalid width: {w}"),
74 Self::EmptyFormatList => write!(f, "supported format list is empty"),
75 Self::UnsupportedTransfer { from, to } => {
76 write!(f, "unsupported transfer conversion: {from:?} → {to:?}")
77 }
78 Self::AlphaNotOpaque => write!(f, "alpha channel is not fully opaque"),
79 Self::DepthReductionForbidden => write!(f, "depth reduction forbidden by policy"),
80 Self::AlphaRemovalForbidden => write!(f, "alpha removal forbidden by policy"),
81 Self::RgbToGray => {
82 write!(f, "RGB-to-grayscale requires explicit luma coefficients")
83 }
84 Self::AllocationFailed => write!(f, "buffer allocation failed"),
85 Self::CmsError(msg) => write!(f, "CMS transform failed: {msg}"),
86 }
87 }
88}
89
90#[cfg(feature = "std")]
91impl std::error::Error for ConvertError {}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96 use alloc::format;
97
98 #[test]
99 fn display_no_match() {
100 let e = ConvertError::NoMatch {
101 source: PixelDescriptor::RGB8_SRGB,
102 };
103 let s = format!("{e}");
104 assert!(s.contains("no supported format"));
105 assert!(s.contains("U8"));
106 assert!(s.contains("Rgb"));
107 }
108
109 #[test]
110 fn display_no_path() {
111 let e = ConvertError::NoPath {
112 from: PixelDescriptor::RGB8_SRGB,
113 to: PixelDescriptor::GRAY8_SRGB,
114 };
115 let s = format!("{e}");
116 assert!(s.contains("no conversion path"));
117 }
118
119 #[test]
120 fn display_buffer_size() {
121 let e = ConvertError::BufferSize {
122 expected: 1024,
123 actual: 512,
124 };
125 let s = format!("{e}");
126 assert!(s.contains("1024"));
127 assert!(s.contains("512"));
128 }
129
130 #[test]
131 fn display_invalid_width() {
132 let e = ConvertError::InvalidWidth(0);
133 assert!(format!("{e}").contains("0"));
134 }
135
136 #[test]
137 fn display_empty_format_list() {
138 let s = format!("{}", ConvertError::EmptyFormatList);
139 assert!(s.contains("empty"));
140 }
141
142 #[test]
143 fn display_unsupported_transfer() {
144 let e = ConvertError::UnsupportedTransfer {
145 from: TransferFunction::Pq,
146 to: TransferFunction::Hlg,
147 };
148 let s = format!("{e}");
149 assert!(s.contains("Pq"));
150 assert!(s.contains("Hlg"));
151 }
152
153 #[test]
154 fn display_alpha_not_opaque() {
155 assert!(format!("{}", ConvertError::AlphaNotOpaque).contains("opaque"));
156 }
157
158 #[test]
159 fn display_depth_reduction_forbidden() {
160 assert!(format!("{}", ConvertError::DepthReductionForbidden).contains("forbidden"));
161 }
162
163 #[test]
164 fn display_alpha_removal_forbidden() {
165 assert!(format!("{}", ConvertError::AlphaRemovalForbidden).contains("forbidden"));
166 }
167
168 #[test]
169 fn display_rgb_to_gray() {
170 assert!(format!("{}", ConvertError::RgbToGray).contains("luma"));
171 }
172
173 #[test]
174 fn display_allocation_failed() {
175 assert!(format!("{}", ConvertError::AllocationFailed).contains("allocation"));
176 }
177
178 #[test]
179 fn display_cms_error() {
180 let e = ConvertError::CmsError(alloc::string::String::from("profile mismatch"));
181 let s = format!("{e}");
182 assert!(s.contains("CMS transform failed"));
183 assert!(s.contains("profile mismatch"));
184 }
185
186 #[test]
187 fn error_eq() {
188 assert_eq!(ConvertError::AlphaNotOpaque, ConvertError::AlphaNotOpaque);
189 assert_ne!(ConvertError::AlphaNotOpaque, ConvertError::RgbToGray);
190 }
191
192 #[test]
193 fn error_debug() {
194 let e = ConvertError::AllocationFailed;
195 let s = format!("{e:?}");
196 assert!(s.contains("AllocationFailed"));
197 }
198
199 #[test]
200 fn error_clone() {
201 let e = ConvertError::BufferSize {
202 expected: 100,
203 actual: 50,
204 };
205 let e2 = e.clone();
206 assert_eq!(e, e2);
207 }
208}