pdfium_render/pdf/document/page/field/
options.rs1use crate::bindgen::{FPDF_ANNOTATION, FPDF_FORMHANDLE, FPDF_WCHAR};
5use crate::bindings::PdfiumLibraryBindings;
6use crate::error::PdfiumError;
7use crate::pdf::document::page::field::option::PdfFormFieldOption;
8use crate::utils::mem::create_byte_buffer;
9use crate::utils::utf16le::get_string_from_pdfium_utf16le_bytes;
10use std::ops::{Range, RangeInclusive};
11use std::os::raw::c_int;
12
13pub type PdfFormFieldOptionIndex = usize;
15
16pub struct PdfFormFieldOptions<'a> {
18 form_handle: FPDF_FORMHANDLE,
19 annotation_handle: FPDF_ANNOTATION,
20 bindings: &'a dyn PdfiumLibraryBindings,
21}
22
23impl<'a> PdfFormFieldOptions<'a> {
24 #[inline]
25 pub(crate) fn from_pdfium(
26 form_handle: FPDF_FORMHANDLE,
27 annotation_handle: FPDF_ANNOTATION,
28 bindings: &'a dyn PdfiumLibraryBindings,
29 ) -> Self {
30 PdfFormFieldOptions {
31 form_handle,
32 annotation_handle,
33 bindings,
34 }
35 }
36
37 #[inline]
39 pub fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
40 self.bindings
41 }
42
43 pub fn len(&self) -> PdfFormFieldOptionIndex {
45 let result = self
46 .bindings
47 .FPDFAnnot_GetOptionCount(self.form_handle, self.annotation_handle);
48
49 if result == -1 {
50 0
51 } else {
52 result as PdfFormFieldOptionIndex
53 }
54 }
55
56 #[inline]
58 pub fn is_empty(&self) -> bool {
59 self.len() == 0
60 }
61
62 #[inline]
64 pub fn as_range(&self) -> Range<PdfFormFieldOptionIndex> {
65 0..self.len()
66 }
67
68 #[inline]
71 pub fn as_range_inclusive(&self) -> RangeInclusive<PdfFormFieldOptionIndex> {
72 if self.is_empty() {
73 0..=0
74 } else {
75 0..=(self.len() - 1)
76 }
77 }
78
79 pub fn get(&self, index: PdfFormFieldOptionIndex) -> Result<PdfFormFieldOption, PdfiumError> {
81 if index >= self.len() {
82 return Err(PdfiumError::FormFieldOptionIndexOutOfBounds);
83 }
84
85 let buffer_length = self.bindings().FPDFAnnot_GetOptionLabel(
94 self.form_handle,
95 self.annotation_handle,
96 index as c_int,
97 std::ptr::null_mut(),
98 0,
99 );
100
101 let option_label = if buffer_length == 0 {
102 None
105 } else {
106 let mut buffer = create_byte_buffer(buffer_length as usize);
107
108 let result = self.bindings().FPDFAnnot_GetOptionLabel(
109 self.form_handle,
110 self.annotation_handle,
111 index as c_int,
112 buffer.as_mut_ptr() as *mut FPDF_WCHAR,
113 buffer_length,
114 );
115
116 debug_assert_eq!(result, buffer_length);
117
118 get_string_from_pdfium_utf16le_bytes(buffer)
119 };
120
121 let option_is_set = self
122 .bindings
123 .is_true(self.bindings.FPDFAnnot_IsOptionSelected(
124 self.form_handle,
125 self.annotation_handle,
126 index as c_int,
127 ));
128
129 Ok(PdfFormFieldOption::new(index, option_is_set, option_label))
130 }
131
132 #[inline]
134 pub fn iter(&self) -> PdfFormFieldOptionsIterator {
135 PdfFormFieldOptionsIterator::new(self)
136 }
137}
138
139pub struct PdfFormFieldOptionsIterator<'a> {
141 options: &'a PdfFormFieldOptions<'a>,
142 next_index: PdfFormFieldOptionIndex,
143}
144
145impl<'a> PdfFormFieldOptionsIterator<'a> {
146 #[inline]
147 pub(crate) fn new(options: &'a PdfFormFieldOptions<'a>) -> Self {
148 PdfFormFieldOptionsIterator {
149 options,
150 next_index: 0,
151 }
152 }
153}
154
155impl<'a> Iterator for PdfFormFieldOptionsIterator<'a> {
156 type Item = PdfFormFieldOption;
157
158 fn next(&mut self) -> Option<Self::Item> {
159 let next = self.options.get(self.next_index);
160
161 self.next_index += 1;
162
163 next.ok()
164 }
165}