1use std::error::Error;
2use std::path::Path;
3use crate::engine::PurePdfDoc;
4use crate::types::*;
5
6pub fn parse_raw_file(pdf_path: &str) -> Result<RawSpatialDocument, Box<dyn Error + Send + Sync>> {
9 let path = Path::new(pdf_path);
10 if !path.exists() {
11 return Err(format!("PDF file not found: {}", pdf_path).into());
12 }
13
14 let file_name = path
15 .file_name()
16 .map(|f| f.to_string_lossy().to_string())
17 .unwrap_or_else(|| "document.pdf".to_string());
18
19 let bytes = std::fs::read(pdf_path)?;
20 let mut doc = PurePdfDoc::from_bytes(&bytes).map_err(|e| format!("Pure PDF parse error: {e}"))?;
21 let raw = doc.parse_raw(&file_name).map_err(|e| format!("Pure PDF parse_raw error: {e}"))?;
22 Ok(raw)
23}
24
25pub fn parse_raw_bytes(pdf_bytes: &[u8]) -> Result<RawSpatialDocument, Box<dyn Error + Send + Sync>> {
27 let mut doc = PurePdfDoc::from_bytes(pdf_bytes).map_err(|e| format!("Pure PDF parse error: {e}"))?;
28 let raw = doc.parse_raw("memory.pdf").map_err(|e| format!("Pure PDF parse_raw error: {e}"))?;
29 Ok(raw)
30}
31
32pub fn parse_file(pdf_path: &str, options: &ParserOptions) -> Result<SpatialDocument, Box<dyn Error + Send + Sync>> {
34 let path = Path::new(pdf_path);
35 if !path.exists() {
36 return Err(format!("PDF file not found: {}", pdf_path).into());
37 }
38
39 let file_name = path
40 .file_name()
41 .map(|f| f.to_string_lossy().to_string())
42 .unwrap_or_else(|| "document.pdf".to_string());
43
44 let bytes = std::fs::read(pdf_path)?;
45 let mut doc = PurePdfDoc::from_bytes(&bytes).map_err(|e| format!("Pure PDF parse error: {e}"))?;
46 let structured = doc.parse_structured(&file_name, options).map_err(|e| format!("Pure PDF parse_structured error: {e}"))?;
47 Ok(structured)
48}
49
50pub fn parse_bytes(pdf_bytes: &[u8], options: &ParserOptions) -> Result<SpatialDocument, Box<dyn Error + Send + Sync>> {
52 let mut doc = PurePdfDoc::from_bytes(pdf_bytes).map_err(|e| format!("Pure PDF parse error: {e}"))?;
53 let structured = doc.parse_structured("memory.pdf", options).map_err(|e| format!("Pure PDF parse_structured error: {e}"))?;
54 Ok(structured)
55}
56
57pub fn extract_text_bytes(pdf_bytes: &[u8]) -> Result<String, Box<dyn Error + Send + Sync>> {
59 let mut doc = PurePdfDoc::from_bytes(pdf_bytes).map_err(|e| format!("Pure PDF parse error: {e}"))?;
60 let raw = doc.parse_raw("memory.pdf").map_err(|e| format!("Pure PDF parse_raw error: {e}"))?;
61
62 let mut out = String::with_capacity(raw.total_spans * 16);
63 let mut last_page = 0;
64 let mut last_y0 = -1.0;
65
66 for span in &raw.spans {
67 if span.page != last_page {
68 if last_page != 0 {
69 out.push('\n');
70 out.push('\n');
71 }
72 last_page = span.page;
73 last_y0 = span.y0;
74 } else if (span.y0 - last_y0).abs() > 4.0 {
75 out.push('\n');
76 last_y0 = span.y0;
77 } else if !out.ends_with(' ') && !span.text.starts_with(' ') {
78 out.push(' ');
79 }
80
81 out.push_str(&span.text);
82 }
83
84 if !out.ends_with('\n') && !out.is_empty() {
85 out.push('\n');
86 }
87
88 Ok(out)
89}