pdfium_render/pdf/document/
signatures.rs

1//! Defines the [PdfSignatures] struct, a collection of all the `PdfSignature` objects in a
2//! `PdfDocument`.
3
4use crate::bindgen::FPDF_DOCUMENT;
5use crate::bindings::PdfiumLibraryBindings;
6use crate::error::{PdfiumError, PdfiumInternalError};
7use crate::pdf::document::signature::PdfSignature;
8use std::ops::{Range, RangeInclusive};
9use std::os::raw::c_int;
10
11/// The zero-based index of a single [PdfSignature] inside its containing [PdfSignatures] collection.
12pub type PdfSignatureIndex = u16;
13
14/// The collection of [PdfSignature] objects inside a `PdfDocument`.
15pub struct PdfSignatures<'a> {
16    document_handle: FPDF_DOCUMENT,
17    bindings: &'a dyn PdfiumLibraryBindings,
18}
19
20impl<'a> PdfSignatures<'a> {
21    #[inline]
22    pub(crate) fn from_pdfium(
23        document_handle: FPDF_DOCUMENT,
24        bindings: &'a dyn PdfiumLibraryBindings,
25    ) -> Self {
26        PdfSignatures {
27            document_handle,
28            bindings,
29        }
30    }
31
32    /// Returns the [PdfiumLibraryBindings] used by this [PdfSignatures] collection.
33    #[inline]
34    pub fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
35        self.bindings
36    }
37
38    /// Returns the number of signatures in this [PdfSignatures] collection.
39    pub fn len(&self) -> PdfSignatureIndex {
40        self.bindings().FPDF_GetSignatureCount(self.document_handle) as PdfSignatureIndex
41    }
42
43    /// Returns `true` if this [PdfSignatures] collection is empty.
44    #[inline]
45    pub fn is_empty(&self) -> bool {
46        self.len() == 0
47    }
48
49    /// Returns a Range from `0..(number of signatures)` for this [PdfSignatures] collection.
50    #[inline]
51    pub fn as_range(&self) -> Range<PdfSignatureIndex> {
52        0..self.len()
53    }
54
55    /// Returns an inclusive Range from `0..=(number of signatures - 1)`
56    /// for this [PdfSignatures] collection.
57    #[inline]
58    pub fn as_range_inclusive(&self) -> RangeInclusive<PdfSignatureIndex> {
59        if self.is_empty() {
60            0..=0
61        } else {
62            0..=(self.len() - 1)
63        }
64    }
65
66    /// Returns a single [PdfSignature] from this [PdfSignatures] collection.
67    pub fn get(&self, index: PdfSignatureIndex) -> Result<PdfSignature<'a>, PdfiumError> {
68        if index >= self.len() {
69            return Err(PdfiumError::SignatureIndexOutOfBounds);
70        }
71
72        let handle = self
73            .bindings()
74            .FPDF_GetSignatureObject(self.document_handle, index as c_int);
75
76        if handle.is_null() {
77            Err(PdfiumError::PdfiumLibraryInternalError(
78                PdfiumInternalError::Unknown,
79            ))
80        } else {
81            Ok(PdfSignature::from_pdfium(handle, self.bindings()))
82        }
83    }
84
85    /// Returns an iterator over all the signatures in this [PdfSignatures] collection.
86    #[inline]
87    pub fn iter(&self) -> PdfSignaturesIterator {
88        PdfSignaturesIterator::new(self)
89    }
90}
91
92/// An iterator over all the [PdfSignature] objects in a [PdfSignatures] collection.
93pub struct PdfSignaturesIterator<'a> {
94    signatures: &'a PdfSignatures<'a>,
95    next_index: PdfSignatureIndex,
96}
97
98impl<'a> PdfSignaturesIterator<'a> {
99    #[inline]
100    pub(crate) fn new(signatures: &'a PdfSignatures<'a>) -> Self {
101        PdfSignaturesIterator {
102            signatures,
103            next_index: 0,
104        }
105    }
106}
107
108impl<'a> Iterator for PdfSignaturesIterator<'a> {
109    type Item = PdfSignature<'a>;
110
111    fn next(&mut self) -> Option<Self::Item> {
112        let next = self.signatures.get(self.next_index);
113
114        self.next_index += 1;
115
116        next.ok()
117    }
118}