Skip to main content

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::{CString, c_void};
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
43            .bindings()
44            .FPDFAction_GetURIPath(self.document, self.handle, std::ptr::null_mut(), 0);
45
46        if buffer_length == 0 {
47            // There is no URI path for this action.
48
49            return Err(PdfiumError::NoUriForAction);
50        }
51
52        let mut buffer = create_byte_buffer(buffer_length as usize);
53
54        let result = self.bindings().FPDFAction_GetURIPath(
55            self.document,
56            self.handle,
57            buffer.as_mut_ptr() as *mut c_void,
58            buffer_length,
59        );
60
61        assert_eq!(result, buffer_length);
62
63        if let Ok(result) = CString::from_vec_with_nul(buffer) {
64            result.into_string().map_err(PdfiumError::CStringConversionError)
65        } else {
66            Err(PdfiumError::NoUriForAction)
67        }
68    }
69}
70
71impl<'a> PdfActionPrivate<'a> for PdfActionUri<'a> {
72    #[inline]
73    fn handle(&self) -> &FPDF_ACTION {
74        &self.handle
75    }
76
77    #[inline]
78    fn bindings(&self) -> &dyn PdfiumLibraryBindings {
79        self.bindings
80    }
81}