1use thiserror::Error;
2
3#[derive(Error, Debug)]
4pub enum PdfError {
5 #[error("IO error: {0}")]
6 Io(#[from] std::io::Error),
7
8 #[error("Invalid PDF structure: {0}")]
9 InvalidStructure(String),
10
11 #[error("Invalid object reference: {0}")]
12 InvalidReference(String),
13
14 #[error("Encoding error: {0}")]
15 EncodingError(String),
16
17 #[error("Font error: {0}")]
18 FontError(String),
19
20 #[error("Compression error: {0}")]
21 CompressionError(String),
22
23 #[error("Invalid image: {0}")]
24 InvalidImage(String),
25}
26
27pub type Result<T> = std::result::Result<T, PdfError>;
28
29#[derive(Error, Debug)]
31pub enum OxidizePdfError {
32 #[error("IO error: {0}")]
33 Io(#[from] std::io::Error),
34
35 #[error("Parse error: {0}")]
36 ParseError(String),
37
38 #[error("Invalid PDF structure: {0}")]
39 InvalidStructure(String),
40
41 #[error("Encoding error: {0}")]
42 EncodingError(String),
43
44 #[error("Other error: {0}")]
45 Other(String),
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use std::io::{Error as IoError, ErrorKind};
52
53 #[test]
54 fn test_pdf_error_display() {
55 let error = PdfError::InvalidStructure("test message".to_string());
56 assert_eq!(error.to_string(), "Invalid PDF structure: test message");
57 }
58
59 #[test]
60 fn test_pdf_error_debug() {
61 let error = PdfError::InvalidReference("object 1 0".to_string());
62 let debug_str = format!("{:?}", error);
63 assert!(debug_str.contains("InvalidReference"));
64 assert!(debug_str.contains("object 1 0"));
65 }
66
67 #[test]
68 fn test_pdf_error_from_io_error() {
69 let io_error = IoError::new(ErrorKind::NotFound, "file not found");
70 let pdf_error = PdfError::from(io_error);
71
72 match pdf_error {
73 PdfError::Io(ref err) => {
74 assert_eq!(err.kind(), ErrorKind::NotFound);
75 }
76 _ => panic!("Expected IO error variant"),
77 }
78 }
79
80 #[test]
81 fn test_all_pdf_error_variants() {
82 let errors = vec![
83 PdfError::InvalidStructure("structure error".to_string()),
84 PdfError::InvalidReference("ref error".to_string()),
85 PdfError::EncodingError("encoding error".to_string()),
86 PdfError::FontError("font error".to_string()),
87 PdfError::CompressionError("compression error".to_string()),
88 PdfError::InvalidImage("image error".to_string()),
89 ];
90
91 for error in errors {
93 let error_string = error.to_string();
94 assert!(!error_string.is_empty());
95 assert!(error_string.contains("error"));
96 }
97 }
98
99 #[test]
100 fn test_oxidize_pdf_error_display() {
101 let error = OxidizePdfError::ParseError("parsing failed".to_string());
102 assert_eq!(error.to_string(), "Parse error: parsing failed");
103 }
104
105 #[test]
106 fn test_oxidize_pdf_error_debug() {
107 let error = OxidizePdfError::InvalidStructure("malformed PDF".to_string());
108 let debug_str = format!("{:?}", error);
109 assert!(debug_str.contains("InvalidStructure"));
110 assert!(debug_str.contains("malformed PDF"));
111 }
112
113 #[test]
114 fn test_oxidize_pdf_error_from_io_error() {
115 let io_error = IoError::new(ErrorKind::PermissionDenied, "access denied");
116 let pdf_error = OxidizePdfError::from(io_error);
117
118 match pdf_error {
119 OxidizePdfError::Io(ref err) => {
120 assert_eq!(err.kind(), ErrorKind::PermissionDenied);
121 }
122 _ => panic!("Expected IO error variant"),
123 }
124 }
125
126 #[test]
127 fn test_all_oxidize_pdf_error_variants() {
128 let errors = vec![
129 OxidizePdfError::ParseError("parse error".to_string()),
130 OxidizePdfError::InvalidStructure("structure error".to_string()),
131 OxidizePdfError::EncodingError("encoding error".to_string()),
132 OxidizePdfError::Other("other error".to_string()),
133 ];
134
135 for error in errors {
137 let error_string = error.to_string();
138 assert!(!error_string.is_empty());
139 assert!(error_string.contains("error"));
140 }
141 }
142
143 #[test]
144 fn test_result_type_ok() {
145 let result: Result<i32> = Ok(42);
146 assert!(result.is_ok());
147 assert_eq!(result.unwrap(), 42);
148 }
149
150 #[test]
151 fn test_result_type_err() {
152 let result: Result<i32> = Err(PdfError::InvalidStructure("test".to_string()));
153 assert!(result.is_err());
154
155 let error = result.unwrap_err();
156 match error {
157 PdfError::InvalidStructure(msg) => assert_eq!(msg, "test"),
158 _ => panic!("Expected InvalidStructure variant"),
159 }
160 }
161
162 #[test]
163 fn test_error_chain_display() {
164 let errors = [
166 ("Invalid PDF structure: corrupted header",
167 PdfError::InvalidStructure("corrupted header".to_string())),
168 ("Invalid object reference: 999 0 R",
169 PdfError::InvalidReference("999 0 R".to_string())),
170 ("Encoding error: unsupported encoding",
171 PdfError::EncodingError("unsupported encoding".to_string())),
172 ("Font error: missing font",
173 PdfError::FontError("missing font".to_string())),
174 ("Compression error: deflate failed",
175 PdfError::CompressionError("deflate failed".to_string())),
176 ("Invalid image: corrupt JPEG",
177 PdfError::InvalidImage("corrupt JPEG".to_string())),
178 ];
179
180 for (expected, error) in errors {
181 assert_eq!(error.to_string(), expected);
182 }
183 }
184
185 #[test]
186 fn test_oxidize_pdf_error_chain_display() {
187 let errors = [
189 ("Parse error: unexpected token",
190 OxidizePdfError::ParseError("unexpected token".to_string())),
191 ("Invalid PDF structure: missing xref",
192 OxidizePdfError::InvalidStructure("missing xref".to_string())),
193 ("Encoding error: invalid UTF-8",
194 OxidizePdfError::EncodingError("invalid UTF-8".to_string())),
195 ("Other error: unknown issue",
196 OxidizePdfError::Other("unknown issue".to_string())),
197 ];
198
199 for (expected, error) in errors {
200 assert_eq!(error.to_string(), expected);
201 }
202 }
203
204 #[test]
205 fn test_error_send_sync() {
206 fn assert_send_sync<T: Send + Sync>() {}
208 assert_send_sync::<PdfError>();
209 assert_send_sync::<OxidizePdfError>();
210 }
211
212 #[test]
213 fn test_error_struct_creation() {
214 let errors = vec![
216 PdfError::InvalidStructure("test".to_string()),
217 PdfError::InvalidReference("ref".to_string()),
218 PdfError::EncodingError("encoding".to_string()),
219 PdfError::FontError("font".to_string()),
220 PdfError::CompressionError("compression".to_string()),
221 PdfError::InvalidImage("image".to_string()),
222 ];
223
224 for error in errors {
226 let msg = error.to_string();
227 assert!(msg.contains("error") || msg.contains("Invalid"));
228 }
229 }
230
231 #[test]
232 fn test_oxidize_pdf_error_struct_creation() {
233 let errors = vec![
235 OxidizePdfError::ParseError("test".to_string()),
236 OxidizePdfError::InvalidStructure("structure".to_string()),
237 OxidizePdfError::EncodingError("encoding".to_string()),
238 OxidizePdfError::Other("other".to_string()),
239 ];
240
241 for error in errors {
243 let msg = error.to_string();
244 assert!(msg.contains("error") || msg.contains("Invalid"));
245 }
246 }
247
248 #[test]
249 fn test_error_equality() {
250 let error1 = PdfError::InvalidStructure("test".to_string());
251 let error2 = PdfError::InvalidStructure("test".to_string());
252 let error3 = PdfError::InvalidStructure("different".to_string());
253
254 assert_eq!(error1.to_string(), error2.to_string());
256 assert_ne!(error1.to_string(), error3.to_string());
257 }
258
259 #[test]
260 fn test_io_error_preservation() {
261 let original_io_error = IoError::new(ErrorKind::UnexpectedEof, "sudden EOF");
263 let pdf_error = PdfError::from(original_io_error);
264
265 if let PdfError::Io(io_err) = pdf_error {
266 assert_eq!(io_err.kind(), ErrorKind::UnexpectedEof);
267 assert_eq!(io_err.to_string(), "sudden EOF");
268 } else {
269 panic!("IO error should be preserved as PdfError::Io");
270 }
271 }
272
273 #[test]
274 fn test_oxidize_pdf_error_io_error_preservation() {
275 let original_io_error = IoError::new(ErrorKind::InvalidData, "corrupted data");
277 let oxidize_error = OxidizePdfError::from(original_io_error);
278
279 if let OxidizePdfError::Io(io_err) = oxidize_error {
280 assert_eq!(io_err.kind(), ErrorKind::InvalidData);
281 assert_eq!(io_err.to_string(), "corrupted data");
282 } else {
283 panic!("IO error should be preserved as OxidizePdfError::Io");
284 }
285 }
286}