use super::extractor::XfaExtractor;
use super::parser::XfaParser;
use crate::document::PdfDocument;
use crate::error::Result;
#[derive(Debug, Clone)]
pub struct XfaAnalysis {
pub has_xfa: bool,
pub field_count: Option<usize>,
pub page_count: Option<usize>,
pub field_types: Vec<String>,
}
pub fn analyze_xfa_document(doc: &mut PdfDocument) -> Result<XfaAnalysis> {
let has_xfa = XfaExtractor::has_xfa(doc)?;
if !has_xfa {
return Ok(XfaAnalysis {
has_xfa: false,
field_count: None,
page_count: None,
field_types: Vec::new(),
});
}
let xfa_data = XfaExtractor::extract_xfa(doc)?;
let mut parser = XfaParser::new();
let xfa_form = parser.parse(&xfa_data)?;
let mut field_types: Vec<String> = xfa_form.fields.iter().map(|f| format!("{:?}", f.field_type)).collect();
field_types.sort();
field_types.dedup();
Ok(XfaAnalysis {
has_xfa: true,
field_count: Some(xfa_form.field_count()),
page_count: Some(if xfa_form.pages.is_empty() {
1
} else {
xfa_form.pages.len()
}),
field_types,
})
}
#[cfg(test)]
mod tests {
use super::*;
const SIMPLE_PDF: &[u8] = include_bytes!("../../tests/fixtures/simple.pdf");
#[test]
fn analyze_xfa_document_should_report_no_xfa_for_a_plain_pdf() {
let mut doc = PdfDocument::from_bytes(SIMPLE_PDF.to_vec()).expect("simple.pdf should parse");
let analysis = analyze_xfa_document(&mut doc).expect("analysis should not fail on a non-XFA document");
assert!(!analysis.has_xfa);
assert_eq!(analysis.field_count, None);
assert_eq!(analysis.page_count, None);
assert!(analysis.field_types.is_empty());
}
}