cloudiful_docling_convert/
error.rs1use std::error::Error;
2use std::fmt;
3
4#[derive(Debug)]
5pub enum PdfConvertError {
6 IoError {
7 context: String,
8 source: std::io::Error,
9 },
10
11 ApiError {
12 status_code: Option<u16>,
13 message: String,
14 source: Option<reqwest::Error>,
15 },
16
17 ParseError {
18 target: String,
19 message: String,
20 },
21
22 #[allow(dead_code)]
23 ValidationError {
24 parameter: String,
25 reason: String,
26 },
27
28 EnvError {
29 var_name: String,
30 message: String,
31 },
32
33 OperationError {
34 context: String,
35 message: String,
36 },
37}
38
39impl fmt::Display for PdfConvertError {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 match self {
42 PdfConvertError::IoError { context, source } => {
43 write!(f, "IO error while {}: {}", context, source)?;
44 let mut curr = source.source();
45 while let Some(src) = curr {
46 write!(f, " caused by: {}", src)?;
47 curr = src.source();
48 }
49 Ok(())
50 }
51 PdfConvertError::ApiError {
52 status_code,
53 message,
54 source,
55 } => {
56 if let Some(src) = source {
57 write!(f, "{}", src)?;
58 let mut curr = src.source();
59 while let Some(cause) = curr {
60 write!(f, " caused by: {}", cause)?;
61 curr = cause.source();
62 }
63 Ok(())
64 } else if let Some(code) = status_code {
65 write!(f, "HTTP {}: {}", code, message)
66 } else {
67 write!(f, "{}", message)
68 }
69 }
70 PdfConvertError::ParseError { target, message } => {
71 write!(f, "Failed to parse {}: {}", target, message)
72 }
73 PdfConvertError::ValidationError { parameter, reason } => {
74 write!(f, "Validation error for '{}': {}", parameter, reason)
75 }
76 PdfConvertError::EnvError { var_name, message } => {
77 write!(
78 f,
79 "Environment variable error for '{}': {}",
80 var_name, message
81 )
82 }
83 PdfConvertError::OperationError { context, message } => {
84 write!(f, "{}: {}", context, message)
85 }
86 }
87 }
88}
89
90impl std::error::Error for PdfConvertError {
91 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
92 match self {
93 PdfConvertError::IoError { source, .. } => Some(source),
94 PdfConvertError::ApiError { source, .. } => source
95 .as_ref()
96 .map(|e| e as &(dyn std::error::Error + 'static)),
97 _ => None,
98 }
99 }
100}
101
102pub type Result<T> = std::result::Result<T, PdfConvertError>;
103
104impl From<std::io::Error> for PdfConvertError {
105 fn from(err: std::io::Error) -> Self {
106 PdfConvertError::IoError {
107 context: "performing file operation".to_string(),
108 source: err,
109 }
110 }
111}
112
113impl From<reqwest::Error> for PdfConvertError {
114 fn from(err: reqwest::Error) -> Self {
115 let status_code = err.status().map(|s| s.as_u16());
116 let message = err.to_string();
117
118 PdfConvertError::ApiError {
119 status_code,
120 message,
121 source: Some(err),
122 }
123 }
124}
125
126impl From<serde_json::Error> for PdfConvertError {
127 fn from(err: serde_json::Error) -> Self {
128 PdfConvertError::ParseError {
129 target: "JSON".to_string(),
130 message: err.to_string(),
131 }
132 }
133}
134
135impl From<lopdf::Error> for PdfConvertError {
136 fn from(err: lopdf::Error) -> Self {
137 PdfConvertError::ParseError {
138 target: "PDF".to_string(),
139 message: err.to_string(),
140 }
141 }
142}
143
144impl From<std::env::VarError> for PdfConvertError {
145 fn from(err: std::env::VarError) -> Self {
146 match err {
147 std::env::VarError::NotPresent => PdfConvertError::EnvError {
148 var_name: "unknown".to_string(),
149 message: "Environment variable not set".to_string(),
150 },
151 std::env::VarError::NotUnicode(_) => PdfConvertError::EnvError {
152 var_name: "unknown".to_string(),
153 message: "Environment variable contains invalid Unicode".to_string(),
154 },
155 }
156 }
157}
158
159impl PdfConvertError {
160 pub fn io_error(context: impl Into<String>, source: std::io::Error) -> Self {
161 PdfConvertError::IoError {
162 context: context.into(),
163 source,
164 }
165 }
166
167 pub fn api_error(status_code: Option<u16>, message: impl Into<String>) -> Self {
168 PdfConvertError::ApiError {
169 status_code,
170 message: message.into(),
171 source: None,
172 }
173 }
174
175 pub fn parse_error(target: impl Into<String>, message: impl Into<String>) -> Self {
176 PdfConvertError::ParseError {
177 target: target.into(),
178 message: message.into(),
179 }
180 }
181
182 #[allow(dead_code)]
183 pub fn validation_error(parameter: impl Into<String>, reason: impl Into<String>) -> Self {
184 PdfConvertError::ValidationError {
185 parameter: parameter.into(),
186 reason: reason.into(),
187 }
188 }
189
190 pub fn env_error(var_name: impl Into<String>, message: impl Into<String>) -> Self {
191 PdfConvertError::EnvError {
192 var_name: var_name.into(),
193 message: message.into(),
194 }
195 }
196
197 pub fn operation_error(context: impl Into<String>, message: impl Into<String>) -> Self {
198 PdfConvertError::OperationError {
199 context: context.into(),
200 message: message.into(),
201 }
202 }
203
204 pub fn api_task_failed(status: impl Into<String>, details: impl Into<String>) -> Self {
205 PdfConvertError::ApiError {
206 status_code: None,
207 message: format!(
208 "Task failed - Status: {}, Details: {}",
209 status.into(),
210 details.into()
211 ),
212 source: None,
213 }
214 }
215}