Skip to main content

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