pdfium_render/pdf/document/
metadata.rs1use crate::bindgen::FPDF_DOCUMENT;
4use crate::bindings::PdfiumLibraryBindings;
5use crate::utils::mem::create_byte_buffer;
6use crate::utils::utf16le::get_string_from_pdfium_utf16le_bytes;
7use std::os::raw::c_void;
8use std::slice::Iter;
9
10#[cfg(doc)]
11use crate::pdf::document::PdfDocument;
12
13#[derive(Debug, Copy, Clone, PartialEq)]
15pub enum PdfDocumentMetadataTagType {
16 Title,
17 Author,
18 Subject,
19 Keywords,
20 Creator,
21 Producer,
22 CreationDate,
23 ModificationDate,
24}
25
26#[derive(Debug, Clone, PartialEq)]
28pub struct PdfDocumentMetadataTag {
29 tag: PdfDocumentMetadataTagType,
30 value: String,
31}
32
33impl PdfDocumentMetadataTag {
34 #[inline]
35 pub(crate) fn new(tag: PdfDocumentMetadataTagType, value: String) -> Self {
36 PdfDocumentMetadataTag { tag, value }
37 }
38
39 #[inline]
41 pub fn tag_type(&self) -> PdfDocumentMetadataTagType {
42 self.tag
43 }
44
45 #[inline]
47 pub fn value(&self) -> &str {
48 self.value.as_str()
49 }
50}
51
52pub struct PdfMetadata<'a> {
54 document_handle: FPDF_DOCUMENT,
55 bindings: &'a dyn PdfiumLibraryBindings,
56 tags: Vec<PdfDocumentMetadataTag>,
57}
58
59impl<'a> PdfMetadata<'a> {
60 pub(crate) fn from_pdfium(document_handle: FPDF_DOCUMENT, bindings: &'a dyn PdfiumLibraryBindings) -> Self {
61 let mut result = PdfMetadata {
62 document_handle,
63 bindings,
64 tags: vec![],
65 };
66
67 if let Some(tag) = result.get(PdfDocumentMetadataTagType::Title) {
68 result.tags.push(tag);
69 }
70
71 if let Some(tag) = result.get(PdfDocumentMetadataTagType::Author) {
72 result.tags.push(tag);
73 }
74
75 if let Some(tag) = result.get(PdfDocumentMetadataTagType::Subject) {
76 result.tags.push(tag);
77 }
78
79 if let Some(tag) = result.get(PdfDocumentMetadataTagType::Keywords) {
80 result.tags.push(tag);
81 }
82
83 if let Some(tag) = result.get(PdfDocumentMetadataTagType::Creator) {
84 result.tags.push(tag);
85 }
86
87 if let Some(tag) = result.get(PdfDocumentMetadataTagType::Producer) {
88 result.tags.push(tag);
89 }
90
91 if let Some(tag) = result.get(PdfDocumentMetadataTagType::CreationDate) {
92 result.tags.push(tag);
93 }
94
95 if let Some(tag) = result.get(PdfDocumentMetadataTagType::ModificationDate) {
96 result.tags.push(tag);
97 }
98
99 result
100 }
101
102 #[inline]
104 pub fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
105 self.bindings
106 }
107
108 #[inline]
110 pub fn len(&self) -> usize {
111 self.tags.len()
112 }
113
114 #[inline]
116 pub fn is_empty(&self) -> bool {
117 self.len() == 0
118 }
119
120 pub fn get(&self, tag: PdfDocumentMetadataTagType) -> Option<PdfDocumentMetadataTag> {
122 let result = match tag {
123 PdfDocumentMetadataTagType::Title => self.get_raw_metadata_tag("Title"),
124 PdfDocumentMetadataTagType::Author => self.get_raw_metadata_tag("Author"),
125 PdfDocumentMetadataTagType::Subject => self.get_raw_metadata_tag("Subject"),
126 PdfDocumentMetadataTagType::Keywords => self.get_raw_metadata_tag("Keywords"),
127 PdfDocumentMetadataTagType::Creator => self.get_raw_metadata_tag("Creator"),
128 PdfDocumentMetadataTagType::Producer => self.get_raw_metadata_tag("Producer"),
129 PdfDocumentMetadataTagType::CreationDate => self.get_raw_metadata_tag("CreationDate"),
130 PdfDocumentMetadataTagType::ModificationDate => self.get_raw_metadata_tag("ModificationDate"),
131 };
132
133 result.map(|value| PdfDocumentMetadataTag::new(tag, value))
134 }
135
136 #[inline]
137 fn get_raw_metadata_tag(&self, tag: &str) -> Option<String> {
138 let buffer_length = self
139 .bindings
140 .FPDF_GetMetaText(self.document_handle, tag, std::ptr::null_mut(), 0);
141
142 if buffer_length == 0 {
143 return None;
144 }
145
146 let mut buffer = create_byte_buffer(buffer_length as usize);
147
148 let result = self.bindings.FPDF_GetMetaText(
149 self.document_handle,
150 tag,
151 buffer.as_mut_ptr() as *mut c_void,
152 buffer_length,
153 );
154
155 assert_eq!(result, buffer_length);
156
157 get_string_from_pdfium_utf16le_bytes(buffer)
158 }
159
160 #[inline]
162 pub fn iter(&self) -> Iter<'_, PdfDocumentMetadataTag> {
163 self.tags.iter()
164 }
165}