use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BoundingBox {
pub x0: f32,
pub y0: f32,
pub x1: f32,
pub y1: f32,
pub width: f32,
pub height: f32,
}
impl BoundingBox {
pub fn new(x0: f32, y0: f32, x1: f32, y1: f32) -> Self {
Self {
x0,
y0,
x1,
y1,
width: (x1 - x0).abs(),
height: (y1 - y0).abs(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RawCoordSpan {
pub page: usize,
pub x0: f32,
pub y0: f32,
pub x1: f32,
pub y1: f32,
pub font_size: f32,
pub font_name: String,
pub text: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RawSpatialDocument {
pub file_name: String,
pub total_pages: usize,
pub total_spans: usize,
pub parse_time_ms: f64,
pub spans: Vec<RawCoordSpan>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpatialSpan {
pub text: String,
pub bbox: BoundingBox,
pub font_name: String,
pub font_size: f32,
pub char_count: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpatialLine {
pub text: String,
pub bbox: BoundingBox,
pub spans: Vec<SpatialSpan>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpatialBlock {
pub block_id: usize,
pub block_type: String, pub bbox: BoundingBox,
pub lines: Vec<SpatialLine>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpatialCell {
pub row: usize,
pub col: usize,
pub text: String,
pub bbox: BoundingBox,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpatialTable {
pub table_id: usize,
pub bbox: BoundingBox,
pub col_count: usize,
pub row_count: usize,
pub headers: Vec<String>,
pub rows: Vec<Vec<String>>,
pub cells: Vec<SpatialCell>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum SpatialDrawingItem {
Line { p1: [f32; 2], p2: [f32; 2] },
Curve {
p1: [f32; 2],
p2: [f32; 2],
p3: [f32; 2],
p4: [f32; 2],
},
Rect { bbox: BoundingBox, orientation: i32 },
Quad { points: [[f32; 2]; 4] },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpatialDrawing {
pub drawing_id: usize,
pub bbox: BoundingBox,
pub drawing_type: String,
pub item_count: usize,
pub items: Vec<SpatialDrawingItem>,
pub stroke_color: Option<[f32; 3]>,
pub fill_color: Option<[f32; 3]>,
pub width: Option<f32>,
pub fill_opacity: Option<f32>,
pub stroke_opacity: Option<f32>,
pub even_odd: Option<bool>,
pub dash_pattern: Option<Vec<f32>>,
pub dash_phase: Option<f32>,
pub line_join: Option<String>,
pub line_cap: Option<String>,
pub layer: Option<String>,
pub seqno: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpatialImage {
pub image_id: usize,
pub name: String,
pub xref: i32,
pub bbox: Option<BoundingBox>,
pub pixel_width: u32,
pub pixel_height: u32,
pub bits_per_component: Option<i32>,
pub color_space: Option<String>,
pub filter: Option<String>,
pub mime_type: Option<String>,
pub byte_length: Option<usize>,
pub sha256: Option<String>,
pub file: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpatialPage {
pub page_number: usize, pub width: f32,
pub height: f32,
pub rotation: i32,
pub text_blocks: Vec<SpatialBlock>,
pub tables: Vec<SpatialTable>,
pub raw_span_count: usize,
#[serde(default)]
pub images: Vec<SpatialImage>,
#[serde(default)]
pub drawings: Vec<SpatialDrawing>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpatialDocument {
pub file_name: String,
pub total_pages: usize,
pub parse_time_ms: f64,
pub pages: Vec<SpatialPage>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct ParserOptions {
pub mode: String, pub detect_tables: bool,
pub min_table_columns: usize,
pub column_tolerance: f32,
pub row_tolerance: f32,
pub extract_images: bool,
pub extract_drawings: bool,
pub filter_background_fills: bool,
}
impl Default for ParserOptions {
fn default() -> Self {
Self {
mode: "structured".to_string(),
detect_tables: true,
min_table_columns: 3,
column_tolerance: 16.0,
row_tolerance: 6.0,
extract_images: false,
extract_drawings: false,
filter_background_fills: true,
}
}
}