pdfium_render/pdf/action/
uri.rs

1//! Defines the [PdfActionUri] struct, exposing functionality related to a single
2//! action of type `PdfActionType::Uri`.
3
4use crate::bindgen::{FPDF_ACTION, FPDF_DOCUMENT};
5use crate::bindings::PdfiumLibraryBindings;
6use crate::error::PdfiumError;
7use crate::pdf::action::private::internal::PdfActionPrivate;
8use crate::utils::mem::create_byte_buffer;
9use std::ffi::{c_void, CString};
10
11pub struct PdfActionUri<'a> {
12    handle: FPDF_ACTION,
13    document: FPDF_DOCUMENT,
14    bindings: &'a dyn PdfiumLibraryBindings,
15}
16
17impl<'a> PdfActionUri<'a> {
18    #[inline]
19    pub(crate) fn from_pdfium(
20        handle: FPDF_ACTION,
21        document: FPDF_DOCUMENT,
22        bindings: &'a dyn PdfiumLibraryBindings,
23    ) -> Self {
24        PdfActionUri {
25            handle,
26            document,
27            bindings,
28        }
29    }
30
31    /// Returns the URI path associated with this [PdfActionUri], if any.
32    pub fn uri(&self) -> Result<String, PdfiumError> {
33        // Retrieving the URI path from Pdfium is a two-step operation. First, we call
34        // FPDFAction_GetURIPath() with a null buffer; this will retrieve the length of
35        // the path in bytes. If the length is zero, then there is no path associated
36        // with this action.
37
38        // If the length is non-zero, then we reserve a byte buffer of the given
39        // length and call FPDFAction_GetURIPath() again with a pointer to the buffer;
40        // this will write the path to the buffer as an array of 7-bit ASCII characters.
41
42        let buffer_length = self.bindings().FPDFAction_GetURIPath(
43            self.document,
44            self.handle,
45            std::ptr::null_mut(),
46            0,
47        );
48
49        if buffer_length == 0 {
50            // There is no URI path for this action.
51
52            return Err(PdfiumError::NoUriForAction);
53        }
54
55        let mut buffer = create_byte_buffer(buffer_length as usize);
56
57        let result = self.bindings().FPDFAction_GetURIPath(
58            self.document,
59            self.handle,
60            buffer.as_mut_ptr() as *mut c_void,
61            buffer_length,
62        );
63
64        assert_eq!(result, buffer_length);
65
66        if let Ok(result) = CString::from_vec_with_nul(buffer) {
67            result
68                .into_string()
69                .map_err(PdfiumError::CStringConversionError)
70        } else {
71            Err(PdfiumError::NoUriForAction)
72        }
73    }
74}
75
76impl<'a> PdfActionPrivate<'a> for PdfActionUri<'a> {
77    #[inline]
78    fn handle(&self) -> &FPDF_ACTION {
79        &self.handle
80    }
81
82    #[inline]
83    fn bindings(&self) -> &dyn PdfiumLibraryBindings {
84        self.bindings
85    }
86}