1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7pub enum OutputFormat {
8 Json,
10 Text,
12 Html,
14 Pdf,
16 Markdown,
18 MarkdownWithHtml,
20 MarkdownWithImages,
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
26pub enum TableMethod {
27 Default,
29 Cluster,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
35pub enum ReadingOrder {
36 Off,
38 XyCut,
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
44pub enum ImageOutput {
45 Off,
47 Embedded,
49 External,
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
55pub enum ImageFormat {
56 Png,
58 Jpeg,
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
64pub enum HybridBackend {
65 Off,
67 DoclingFast,
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
73pub enum HybridMode {
74 Auto,
76 Full,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct ProcessingConfig {
83 pub output_dir: Option<String>,
85 pub password: Option<String>,
87 pub formats: Vec<OutputFormat>,
89 pub quiet: bool,
91 pub filter_config: super::filter::FilterConfig,
93 pub sanitize: bool,
95 pub keep_line_breaks: bool,
97 pub replace_invalid_chars: String,
99 pub use_struct_tree: bool,
101 pub table_method: TableMethod,
103 pub reading_order: ReadingOrder,
105 pub markdown_page_separator: Option<String>,
107 pub text_page_separator: Option<String>,
109 pub html_page_separator: Option<String>,
111 pub image_output: ImageOutput,
113 pub image_format: ImageFormat,
115 pub image_dir: Option<String>,
117 pub raster_table_ocr: bool,
119 pub ocr_budget_ms: Option<u64>,
122 pub pages: Option<String>,
124 pub include_header_footer: bool,
126 pub hybrid: HybridBackend,
128 pub hybrid_mode: HybridMode,
130 pub hybrid_url: Option<String>,
132 pub hybrid_timeout: u64,
134 pub hybrid_fallback: bool,
136}
137
138impl Default for ProcessingConfig {
139 fn default() -> Self {
140 Self {
141 output_dir: None,
142 password: None,
143 formats: vec![OutputFormat::Json],
144 quiet: false,
145 filter_config: super::filter::FilterConfig::default(),
146 sanitize: false,
147 keep_line_breaks: false,
148 replace_invalid_chars: " ".to_string(),
149 use_struct_tree: false,
150 table_method: TableMethod::Default,
151 reading_order: ReadingOrder::XyCut,
152 markdown_page_separator: None,
153 text_page_separator: None,
154 html_page_separator: None,
155 image_output: ImageOutput::External,
156 image_format: ImageFormat::Png,
157 image_dir: None,
158 raster_table_ocr: true,
159 ocr_budget_ms: None,
160 pages: None,
161 include_header_footer: false,
162 hybrid: HybridBackend::Off,
163 hybrid_mode: HybridMode::Auto,
164 hybrid_url: None,
165 hybrid_timeout: 30000,
166 hybrid_fallback: false,
167 }
168 }
169}
170
171impl ProcessingConfig {
172 pub fn hybrid_enabled(&self) -> bool {
174 !matches!(self.hybrid, HybridBackend::Off)
175 }
176
177 pub fn raster_table_ocr_enabled(&self) -> bool {
183 self.raster_table_ocr
184 }
185
186 pub fn ocr_budget(&self) -> crate::pdf::image_region::OcrBudget {
188 crate::pdf::image_region::OcrBudget::from_millis(self.ocr_budget_ms)
189 }
190}
191
192#[cfg(test)]
193mod tests {
194 use super::*;
195
196 #[test]
197 fn test_default_config() {
198 let config = ProcessingConfig::default();
199 assert_eq!(config.formats, vec![OutputFormat::Json]);
200 assert!(!config.quiet);
201 assert!(!config.sanitize);
202 assert_eq!(config.reading_order, ReadingOrder::XyCut);
203 assert_eq!(config.table_method, TableMethod::Default);
204 assert_eq!(config.image_output, ImageOutput::External);
205 assert_eq!(config.image_format, ImageFormat::Png);
206 assert!(config.raster_table_ocr);
207 assert_eq!(config.hybrid, HybridBackend::Off);
208 assert_eq!(config.hybrid_timeout, 30000);
209 }
210
211 #[test]
212 fn test_raster_table_ocr_independent_of_hybrid() {
213 let mut config = ProcessingConfig::default();
214 assert!(!config.hybrid_enabled());
215 assert!(config.raster_table_ocr_enabled());
216
217 config.hybrid = HybridBackend::DoclingFast;
218 assert!(config.hybrid_enabled());
219 assert!(config.raster_table_ocr_enabled());
220
221 config.raster_table_ocr = false;
222 assert!(!config.raster_table_ocr_enabled());
223 }
224}