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(
61 document_handle: FPDF_DOCUMENT,
62 bindings: &'a dyn PdfiumLibraryBindings,
63 ) -> Self {
64 let mut result = PdfMetadata {
65 document_handle,
66 bindings,
67 tags: vec![],
68 };
69
70 if let Some(tag) = result.get(PdfDocumentMetadataTagType::Title) {
71 result.tags.push(tag);
72 }
73
74 if let Some(tag) = result.get(PdfDocumentMetadataTagType::Author) {
75 result.tags.push(tag);
76 }
77
78 if let Some(tag) = result.get(PdfDocumentMetadataTagType::Subject) {
79 result.tags.push(tag);
80 }
81
82 if let Some(tag) = result.get(PdfDocumentMetadataTagType::Keywords) {
83 result.tags.push(tag);
84 }
85
86 if let Some(tag) = result.get(PdfDocumentMetadataTagType::Creator) {
87 result.tags.push(tag);
88 }
89
90 if let Some(tag) = result.get(PdfDocumentMetadataTagType::Producer) {
91 result.tags.push(tag);
92 }
93
94 if let Some(tag) = result.get(PdfDocumentMetadataTagType::CreationDate) {
95 result.tags.push(tag);
96 }
97
98 if let Some(tag) = result.get(PdfDocumentMetadataTagType::ModificationDate) {
99 result.tags.push(tag);
100 }
101
102 result
103 }
104
105 #[inline]
107 pub fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
108 self.bindings
109 }
110
111 #[inline]
113 pub fn len(&self) -> usize {
114 self.tags.len()
115 }
116
117 #[inline]
119 pub fn is_empty(&self) -> bool {
120 self.len() == 0
121 }
122
123 pub fn get(&self, tag: PdfDocumentMetadataTagType) -> Option<PdfDocumentMetadataTag> {
125 let result = match tag {
126 PdfDocumentMetadataTagType::Title => self.get_raw_metadata_tag("Title"),
127 PdfDocumentMetadataTagType::Author => self.get_raw_metadata_tag("Author"),
128 PdfDocumentMetadataTagType::Subject => self.get_raw_metadata_tag("Subject"),
129 PdfDocumentMetadataTagType::Keywords => self.get_raw_metadata_tag("Keywords"),
130 PdfDocumentMetadataTagType::Creator => self.get_raw_metadata_tag("Creator"),
131 PdfDocumentMetadataTagType::Producer => self.get_raw_metadata_tag("Producer"),
132 PdfDocumentMetadataTagType::CreationDate => self.get_raw_metadata_tag("CreationDate"),
133 PdfDocumentMetadataTagType::ModificationDate => {
134 self.get_raw_metadata_tag("ModificationDate")
135 }
136 };
137
138 result.map(|value| PdfDocumentMetadataTag::new(tag, value))
139 }
140
141 #[inline]
142 fn get_raw_metadata_tag(&self, tag: &str) -> Option<String> {
143 let buffer_length =
152 self.bindings
153 .FPDF_GetMetaText(self.document_handle, tag, std::ptr::null_mut(), 0);
154
155 if buffer_length == 0 {
156 return None;
159 }
160
161 let mut buffer = create_byte_buffer(buffer_length as usize);
162
163 let result = self.bindings.FPDF_GetMetaText(
164 self.document_handle,
165 tag,
166 buffer.as_mut_ptr() as *mut c_void,
167 buffer_length,
168 );
169
170 assert_eq!(result, buffer_length);
171
172 get_string_from_pdfium_utf16le_bytes(buffer)
173 }
174
175 #[inline]
177 pub fn iter(&self) -> Iter<'_, PdfDocumentMetadataTag> {
178 self.tags.iter()
179 }
180}