use crate::bindgen::FPDF_DOCUMENT;
use crate::bindings::PdfiumLibraryBindings;
use crate::utils::mem::create_byte_buffer;
use crate::utils::utf16le::get_string_from_pdfium_utf16le_bytes;
use std::os::raw::c_void;
use std::slice::Iter;
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum PdfDocumentMetadataTagType {
Title,
Author,
Subject,
Keywords,
Creator,
Producer,
CreationDate,
ModificationDate,
}
#[derive(Debug, Clone, PartialEq)]
pub struct PdfDocumentMetadataTag {
tag: PdfDocumentMetadataTagType,
value: String,
}
impl PdfDocumentMetadataTag {
#[inline]
pub(crate) fn new(tag: PdfDocumentMetadataTagType, value: String) -> Self {
PdfDocumentMetadataTag { tag, value }
}
#[inline]
pub fn tag_type(&self) -> PdfDocumentMetadataTagType {
self.tag
}
#[inline]
pub fn value(&self) -> &str {
self.value.as_str()
}
}
pub struct PdfMetadata<'a> {
document_handle: FPDF_DOCUMENT,
bindings: &'a dyn PdfiumLibraryBindings,
tags: Vec<PdfDocumentMetadataTag>,
}
impl<'a> PdfMetadata<'a> {
pub(crate) fn from_pdfium(
document_handle: FPDF_DOCUMENT,
bindings: &'a dyn PdfiumLibraryBindings,
) -> Self {
let mut result = PdfMetadata {
document_handle,
bindings,
tags: vec![],
};
if let Some(tag) = result.get(PdfDocumentMetadataTagType::Title) {
result.tags.push(tag);
}
if let Some(tag) = result.get(PdfDocumentMetadataTagType::Author) {
result.tags.push(tag);
}
if let Some(tag) = result.get(PdfDocumentMetadataTagType::Subject) {
result.tags.push(tag);
}
if let Some(tag) = result.get(PdfDocumentMetadataTagType::Keywords) {
result.tags.push(tag);
}
if let Some(tag) = result.get(PdfDocumentMetadataTagType::Creator) {
result.tags.push(tag);
}
if let Some(tag) = result.get(PdfDocumentMetadataTagType::Producer) {
result.tags.push(tag);
}
if let Some(tag) = result.get(PdfDocumentMetadataTagType::CreationDate) {
result.tags.push(tag);
}
if let Some(tag) = result.get(PdfDocumentMetadataTagType::ModificationDate) {
result.tags.push(tag);
}
result
}
#[inline]
pub fn len(&self) -> usize {
self.tags.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get(&self, tag: PdfDocumentMetadataTagType) -> Option<PdfDocumentMetadataTag> {
let result = match tag {
PdfDocumentMetadataTagType::Title => self.get_raw_metadata_tag("Title"),
PdfDocumentMetadataTagType::Author => self.get_raw_metadata_tag("Author"),
PdfDocumentMetadataTagType::Subject => self.get_raw_metadata_tag("Subject"),
PdfDocumentMetadataTagType::Keywords => self.get_raw_metadata_tag("Keywords"),
PdfDocumentMetadataTagType::Creator => self.get_raw_metadata_tag("Creator"),
PdfDocumentMetadataTagType::Producer => self.get_raw_metadata_tag("Producer"),
PdfDocumentMetadataTagType::CreationDate => self.get_raw_metadata_tag("CreationDate"),
PdfDocumentMetadataTagType::ModificationDate => {
self.get_raw_metadata_tag("ModificationDate")
}
};
result.map(|value| PdfDocumentMetadataTag::new(tag, value))
}
#[inline]
fn get_raw_metadata_tag(&self, tag: &str) -> Option<String> {
let buffer_length =
self.bindings
.FPDF_GetMetaText(self.document_handle, tag, std::ptr::null_mut(), 0);
if buffer_length == 0 {
return None;
}
let mut buffer = create_byte_buffer(buffer_length as usize);
let result = self.bindings.FPDF_GetMetaText(
self.document_handle,
tag,
buffer.as_mut_ptr() as *mut c_void,
buffer_length,
);
assert_eq!(result, buffer_length);
get_string_from_pdfium_utf16le_bytes(buffer)
}
#[inline]
pub fn iter(&self) -> Iter<'_, PdfDocumentMetadataTag> {
self.tags.iter()
}
}