mod utils;
use crate::config::RuntimeConfig;
use crate::parsers::ParseResult;
use crate::results::PdfMetadata;
use anyhow::Result;
use log::warn;
use pdf::file::FileOptions;
fn extract_document_info(info: &pdf::object::InfoDict, metadata: &mut PdfMetadata) {
metadata.title = utils::extract_text_str(info.title.as_ref());
metadata.author = utils::extract_text_str(info.author.as_ref());
metadata.subject = utils::extract_text_str(info.subject.as_ref());
metadata.creator = utils::extract_text_str(info.creator.as_ref());
metadata.producer = utils::extract_text_str(info.producer.as_ref());
metadata.creation_date = info
.creation_date
.as_ref()
.and_then(utils::extract_pdf_date_to_iso8601);
metadata.modification_date = info
.mod_date
.as_ref()
.and_then(utils::extract_pdf_date_to_iso8601);
}
pub fn extract_pdf_metadata(
content: &[u8],
stats: &ParseResult,
_config: &RuntimeConfig,
) -> Result<PdfMetadata> {
let mut metadata = PdfMetadata {
file_size: Some(stats.byte_count),
..Default::default()
};
let data = content.to_vec();
let file = match FileOptions::cached().load(data) {
Ok(f) => f,
Err(e) => {
warn!("Failed to parse PDF {}: {:?}", stats.file_path, e);
return Ok(metadata);
}
};
metadata.pdf_version = file.version().ok();
metadata.page_count = Some(file.num_pages() as usize);
metadata.is_encrypted = Some(file.trailer.encrypt_dict.is_some());
if let Some(ref info) = file.trailer.info_dict {
extract_document_info(info, &mut metadata);
}
Ok(metadata)
}
crate::no_template_mining!(
extract_pdf_templates,
"PDFs are binary files, don't have templates, return empty result."
);