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<std::env::VarError> for PdfConvertError {
136 fn from(err: std::env::VarError) -> Self {
137 match err {
138 std::env::VarError::NotPresent => PdfConvertError::EnvError {
139 var_name: "unknown".to_string(),
140 message: "Environment variable not set".to_string(),
141 },
142 std::env::VarError::NotUnicode(_) => PdfConvertError::EnvError {
143 var_name: "unknown".to_string(),
144 message: "Environment variable contains invalid Unicode".to_string(),
145 },
146 }
147 }
148}
149
150impl PdfConvertError {
151 pub fn io_error(context: impl Into<String>, source: std::io::Error) -> Self {
152 PdfConvertError::IoError {
153 context: context.into(),
154 source,
155 }
156 }
157
158 pub fn api_error(status_code: Option<u16>, message: impl Into<String>) -> Self {
159 PdfConvertError::ApiError {
160 status_code,
161 message: message.into(),
162 source: None,
163 }
164 }
165
166 pub fn parse_error(target: impl Into<String>, message: impl Into<String>) -> Self {
167 PdfConvertError::ParseError {
168 target: target.into(),
169 message: message.into(),
170 }
171 }
172
173 #[allow(dead_code)]
174 pub fn validation_error(parameter: impl Into<String>, reason: impl Into<String>) -> Self {
175 PdfConvertError::ValidationError {
176 parameter: parameter.into(),
177 reason: reason.into(),
178 }
179 }
180
181 pub fn env_error(var_name: impl Into<String>, message: impl Into<String>) -> Self {
182 PdfConvertError::EnvError {
183 var_name: var_name.into(),
184 message: message.into(),
185 }
186 }
187
188 pub fn operation_error(context: impl Into<String>, message: impl Into<String>) -> Self {
189 PdfConvertError::OperationError {
190 context: context.into(),
191 message: message.into(),
192 }
193 }
194
195 pub fn api_task_failed(status: impl Into<String>, details: impl Into<String>) -> Self {
196 PdfConvertError::ApiError {
197 status_code: None,
198 message: format!(
199 "Task failed - Status: {}, Details: {}",
200 status.into(),
201 details.into()
202 ),
203 source: None,
204 }
205 }
206}