use crate::bindgen::{FPDF_ANNOTATION, FPDF_FORMHANDLE, FPDF_WCHAR};
use crate::bindings::PdfiumLibraryBindings;
use crate::error::PdfiumError;
use crate::form_field_option::PdfFormFieldOption;
use crate::utils::mem::create_byte_buffer;
use crate::utils::utf16le::get_string_from_pdfium_utf16le_bytes;
use std::ops::{Range, RangeInclusive};
use std::os::raw::c_int;
pub type PdfFormFieldOptionIndex = usize;
pub struct PdfFormFieldOptions<'a> {
form_handle: FPDF_FORMHANDLE,
annotation_handle: FPDF_ANNOTATION,
bindings: &'a dyn PdfiumLibraryBindings,
}
impl<'a> PdfFormFieldOptions<'a> {
#[inline]
pub(crate) fn from_pdfium(
form_handle: FPDF_FORMHANDLE,
annotation_handle: FPDF_ANNOTATION,
bindings: &'a dyn PdfiumLibraryBindings,
) -> Self {
PdfFormFieldOptions {
form_handle,
annotation_handle,
bindings,
}
}
#[inline]
pub fn bindings(&self) -> &'a dyn PdfiumLibraryBindings {
self.bindings
}
pub fn len(&self) -> PdfFormFieldOptionIndex {
let result = self
.bindings
.FPDFAnnot_GetOptionCount(self.form_handle, self.annotation_handle);
if result == -1 {
0
} else {
result as PdfFormFieldOptionIndex
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn as_range(&self) -> Range<PdfFormFieldOptionIndex> {
0..self.len()
}
#[inline]
pub fn as_range_inclusive(&self) -> RangeInclusive<PdfFormFieldOptionIndex> {
if self.is_empty() {
0..=0
} else {
0..=(self.len() - 1)
}
}
pub fn get(&self, index: PdfFormFieldOptionIndex) -> Result<PdfFormFieldOption, PdfiumError> {
if index >= self.len() {
return Err(PdfiumError::FormFieldOptionIndexOutOfBounds);
}
let buffer_length = self.bindings().FPDFAnnot_GetOptionLabel(
self.form_handle,
self.annotation_handle,
index as c_int,
std::ptr::null_mut(),
0,
);
let option_label = if buffer_length == 0 {
None
} else {
let mut buffer = create_byte_buffer(buffer_length as usize);
let result = self.bindings().FPDFAnnot_GetOptionLabel(
self.form_handle,
self.annotation_handle,
index as c_int,
buffer.as_mut_ptr() as *mut FPDF_WCHAR,
buffer_length,
);
debug_assert_eq!(result, buffer_length);
get_string_from_pdfium_utf16le_bytes(buffer)
};
let option_is_set = self
.bindings
.is_true(self.bindings.FPDFAnnot_IsOptionSelected(
self.form_handle,
self.annotation_handle,
index as c_int,
));
Ok(PdfFormFieldOption::new(index, option_is_set, option_label))
}
#[inline]
pub fn iter(&self) -> PdfFormFieldOptionsIterator {
PdfFormFieldOptionsIterator::new(self)
}
}
pub struct PdfFormFieldOptionsIterator<'a> {
options: &'a PdfFormFieldOptions<'a>,
next_index: PdfFormFieldOptionIndex,
}
impl<'a> PdfFormFieldOptionsIterator<'a> {
#[inline]
pub(crate) fn new(options: &'a PdfFormFieldOptions<'a>) -> Self {
PdfFormFieldOptionsIterator {
options,
next_index: 0,
}
}
}
impl<'a> Iterator for PdfFormFieldOptionsIterator<'a> {
type Item = PdfFormFieldOption;
fn next(&mut self) -> Option<Self::Item> {
let next = self.options.get(self.next_index);
self.next_index += 1;
next.ok()
}
}