1use crate::api_error::PdfError;
10
11#[derive(Debug, thiserror::Error)]
13pub enum EngineError {
14 #[error("invalid PDF: {0}")]
16 InvalidPdf(String),
17
18 #[error("page {index} out of range (document has {count} pages)")]
20 PageOutOfRange {
21 index: usize,
23 count: usize,
25 },
26
27 #[error("render error: {0}")]
29 RenderError(String),
30
31 #[error(transparent)]
33 Io(#[from] std::io::Error),
34
35 #[error("PDF is encrypted: {0}")]
37 Encrypted(String),
38
39 #[error("invalid page geometry (w={width:.2}pt, h={height:.2}pt): {reason}")]
41 InvalidPageGeometry {
42 width: f32,
44 height: f32,
46 reason: String,
48 },
49
50 #[error("XFA flatten failed: {0}")]
52 XfaFlattenFailed(String),
53
54 #[error("resource limit exceeded: {0}")]
60 LimitExceeded(crate::limits::LimitError),
61}
62
63impl PdfError for EngineError {
64 fn code(&self) -> &str {
65 match self {
66 EngineError::InvalidPdf(_) => "INVALID_PDF",
67 EngineError::PageOutOfRange { .. } => "PAGE_OUT_OF_RANGE",
68 EngineError::RenderError(_) => "RENDER_ERROR",
69 EngineError::Io(_) => "IO_ERROR",
70 EngineError::Encrypted(_) => "ENCRYPTED",
71 EngineError::InvalidPageGeometry { .. } => "INVALID_PAGE_GEOMETRY",
72 EngineError::XfaFlattenFailed(_) => "XFA_FLATTEN_FAILED",
73 EngineError::LimitExceeded(_) => "LIMIT_EXCEEDED",
74 }
75 }
76
77 fn help(&self) -> Option<String> {
78 match self {
79 EngineError::InvalidPdf(_) => {
80 Some("The PDF file is corrupt or invalid. Try using a PDF repair tool or re-save the document.".to_string())
81 }
82 EngineError::PageOutOfRange { index, count } => {
83 Some(format!("Page {} does not exist. This document has {} pages (0-{}).", index, count, count - 1))
84 }
85 EngineError::RenderError(_) => {
86 Some("Rendering failed. Check that the page exists and the document is not corrupted.".to_string())
87 }
88 EngineError::Io(_) => {
89 Some("An I/O error occurred. Check file permissions and disk space.".to_string())
90 }
91 EngineError::Encrypted(_) => {
92 Some("The PDF is encrypted. Provide the correct password to open it.".to_string())
93 }
94 EngineError::InvalidPageGeometry { .. } => {
95 Some("The page has invalid or degenerate dimensions and cannot be rendered.".to_string())
96 }
97 EngineError::XfaFlattenFailed(_) => {
98 Some("XFA flattening produced an invalid PDF. The document may use unsupported XFA features.".to_string())
99 }
100 EngineError::LimitExceeded(_) => {
101 Some("A processing resource limit was exceeded. Raise the relevant cap in ProcessingLimits or check that the input is not adversarial.".to_string())
102 }
103 }
104 }
105}
106
107pub type Result<T> = std::result::Result<T, EngineError>;
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn encrypted_error_code() {
116 let e = EngineError::Encrypted("bad password".into());
117 assert_eq!(e.code(), "ENCRYPTED");
118 }
119
120 #[test]
121 fn invalid_page_geometry_error_code() {
122 let e = EngineError::InvalidPageGeometry {
123 width: 0.5,
124 height: 0.5,
125 reason: "test".into(),
126 };
127 assert_eq!(e.code(), "INVALID_PAGE_GEOMETRY");
128 }
129
130 #[test]
131 fn xfa_flatten_failed_error_code() {
132 let e = EngineError::XfaFlattenFailed("corrupt output".into());
133 assert_eq!(e.code(), "XFA_FLATTEN_FAILED");
134 }
135}