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