1use std::fmt;
4use std::io;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum InstanceError {
12 DimensionMismatch {
14 requested: (usize, usize),
16 existing: (usize, usize),
18 },
19 ConfigMismatch {
21 requested: (usize, usize),
23 existing: (usize, usize),
25 },
26}
27
28impl fmt::Display for InstanceError {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 match self {
31 InstanceError::DimensionMismatch {
32 requested,
33 existing,
34 } => write!(
35 f,
36 "Cannot create Espresso instance with dimensions {:?} because a \
37 thread-local instance with dimensions {:?} already exists. \
38 Drop all existing covers and handles first.",
39 requested, existing
40 ),
41 InstanceError::ConfigMismatch {
42 requested,
43 existing,
44 } => write!(
45 f,
46 "Cannot create Espresso instance with different configuration while a \
47 thread-local instance with dimensions {:?} already exists (requested {:?}). \
48 Drop all existing covers and handles first.",
49 existing, requested
50 ),
51 }
52 }
53}
54
55impl std::error::Error for InstanceError {}
56
57impl From<InstanceError> for io::Error {
58 fn from(err: InstanceError) -> Self {
59 io::Error::other(err)
60 }
61}
62
63#[derive(Debug, Clone, PartialEq, Eq)]
67pub enum CubeError {
68 InvalidValue {
72 value: u8,
74 position: usize,
76 },
77}
78
79impl fmt::Display for CubeError {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 match self {
82 CubeError::InvalidValue { value, position } => write!(
83 f,
84 "Invalid cube value {} at position {}. Expected 0 (low), 1 (high), or 2 (don't care).",
85 value, position
86 ),
87 }
88 }
89}
90
91impl std::error::Error for CubeError {}
92
93impl From<CubeError> for io::Error {
94 fn from(err: CubeError) -> Self {
95 io::Error::new(io::ErrorKind::InvalidData, err)
96 }
97}
98
99#[derive(Debug)]
103pub enum MinimizationError {
104 Instance(InstanceError),
106 Cube(CubeError),
108 Io(io::Error),
110}
111
112impl fmt::Display for MinimizationError {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 match self {
115 MinimizationError::Instance(e) => write!(f, "Instance error: {}", e),
116 MinimizationError::Cube(e) => write!(f, "Cube error: {}", e),
117 MinimizationError::Io(e) => write!(f, "IO error: {}", e),
118 }
119 }
120}
121
122impl std::error::Error for MinimizationError {
123 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
124 match self {
125 MinimizationError::Instance(e) => Some(e),
126 MinimizationError::Cube(e) => Some(e),
127 MinimizationError::Io(e) => Some(e),
128 }
129 }
130}
131
132impl From<InstanceError> for MinimizationError {
133 fn from(err: InstanceError) -> Self {
134 MinimizationError::Instance(err)
135 }
136}
137
138impl From<CubeError> for MinimizationError {
139 fn from(err: CubeError) -> Self {
140 MinimizationError::Cube(err)
141 }
142}
143
144impl From<io::Error> for MinimizationError {
145 fn from(err: io::Error) -> Self {
146 MinimizationError::Io(err)
147 }
148}
149
150impl From<MinimizationError> for io::Error {
151 fn from(err: MinimizationError) -> Self {
152 match err {
153 MinimizationError::Io(e) => e,
155 MinimizationError::Instance(e) => io::Error::other(e),
157 MinimizationError::Cube(e) => io::Error::new(io::ErrorKind::InvalidData, e),
158 }
159 }
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165 use std::error::Error;
166
167 #[test]
168 fn test_instance_error_dimension_mismatch() {
169 let err = InstanceError::DimensionMismatch {
170 requested: (2, 1),
171 existing: (3, 2),
172 };
173 let msg = err.to_string();
174 assert!(msg.contains("Cannot create Espresso instance"));
175 assert!(msg.contains("(2, 1)"));
176 assert!(msg.contains("(3, 2)"));
177 }
178
179 #[test]
180 fn test_instance_error_config_mismatch() {
181 let err = InstanceError::ConfigMismatch {
182 requested: (2, 1),
183 existing: (2, 1),
184 };
185 let msg = err.to_string();
186 assert!(msg.contains("different configuration"));
187 assert!(msg.contains("(2, 1)"));
188 }
189
190 #[test]
191 fn test_cube_error_invalid_value() {
192 let err = CubeError::InvalidValue {
193 value: 5,
194 position: 2,
195 };
196 let msg = err.to_string();
197 assert!(msg.contains("Invalid cube value 5"));
198 assert!(msg.contains("position 2"));
199 }
200
201 #[test]
202 fn test_minimization_error_from_instance_error() {
203 let inst_err = InstanceError::DimensionMismatch {
204 requested: (2, 1),
205 existing: (3, 2),
206 };
207 let min_err: MinimizationError = inst_err.into();
208 assert!(matches!(min_err, MinimizationError::Instance(_)));
209 assert!(min_err.source().is_some());
210 }
211
212 #[test]
213 fn test_minimization_error_from_cube_error() {
214 let cube_err = CubeError::InvalidValue {
215 value: 5,
216 position: 2,
217 };
218 let min_err: MinimizationError = cube_err.into();
219 assert!(matches!(min_err, MinimizationError::Cube(_)));
220 }
221
222 #[test]
223 fn test_minimization_error_from_io_error() {
224 let io_err = io::Error::new(io::ErrorKind::NotFound, "file not found");
225 let min_err: MinimizationError = io_err.into();
226 assert!(matches!(min_err, MinimizationError::Io(_)));
227 }
228
229 #[test]
230 fn test_instance_error_to_io_error() {
231 let err = InstanceError::DimensionMismatch {
232 requested: (2, 1),
233 existing: (3, 2),
234 };
235 let io_err: io::Error = err.into();
236 assert_eq!(io_err.kind(), io::ErrorKind::Other);
237 }
238
239 #[test]
240 fn test_cube_error_to_io_error() {
241 let err = CubeError::InvalidValue {
242 value: 5,
243 position: 2,
244 };
245 let io_err: io::Error = err.into();
246 assert_eq!(io_err.kind(), io::ErrorKind::InvalidData);
247 }
248
249 #[test]
250 fn test_minimization_error_to_io_error_preserves_io_error() {
251 let original_io_err = io::Error::new(io::ErrorKind::NotFound, "file not found");
252 let min_err = MinimizationError::Io(original_io_err);
253 let io_err: io::Error = min_err.into();
254 assert_eq!(io_err.kind(), io::ErrorKind::NotFound);
255 assert_eq!(io_err.to_string(), "file not found");
256 }
257
258 #[test]
259 fn test_minimization_error_instance_to_io_error() {
260 let inst_err = InstanceError::DimensionMismatch {
261 requested: (2, 1),
262 existing: (3, 2),
263 };
264 let min_err = MinimizationError::Instance(inst_err);
265 let io_err: io::Error = min_err.into();
266 assert_eq!(io_err.kind(), io::ErrorKind::Other);
267 }
268
269 #[test]
270 fn test_minimization_error_cube_to_io_error() {
271 let cube_err = CubeError::InvalidValue {
272 value: 5,
273 position: 2,
274 };
275 let min_err = MinimizationError::Cube(cube_err);
276 let io_err: io::Error = min_err.into();
277 assert_eq!(io_err.kind(), io::ErrorKind::InvalidData);
278 }
279}