use crate::{XlOpenOptions, XL_OPT_DEFAULT, XL_OPT_FALSE, XL_OPT_TRUE};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct OpenOptions {
pub csv_sniff_dialect: Option<bool>,
pub csv_delimiter: Option<i32>,
pub csv_quote: Option<i32>,
pub csv_detect_bom: Option<bool>,
pub csv_max_cell_bytes: Option<i32>,
pub csv_intern_strings: Option<bool>,
pub max_total_decompressed_bytes: Option<i64>,
pub max_cell_bytes: Option<i32>,
pub max_shared_string_bytes: Option<i64>,
pub max_zip_entries: Option<i32>,
pub prefetch_decompression: Option<bool>,
pub intern_strings: Option<bool>,
}
macro_rules! setters {
($($(#[$doc:meta])* $name:ident: $ty:ty),* $(,)?) => {
$(
$(#[$doc])*
#[must_use]
pub fn $name(mut self, value: $ty) -> Self {
self.$name = Some(value);
self
}
)*
};
}
impl OpenOptions {
#[must_use]
pub fn new() -> Self {
Self::default()
}
setters! {
csv_sniff_dialect: bool,
csv_delimiter: i32,
csv_quote: i32,
csv_detect_bom: bool,
csv_max_cell_bytes: i32,
csv_intern_strings: bool,
max_total_decompressed_bytes: i64,
max_cell_bytes: i32,
max_shared_string_bytes: i64,
max_zip_entries: i32,
prefetch_decompression: bool,
intern_strings: bool,
}
#[must_use]
pub fn to_raw(&self) -> XlOpenOptions {
XlOpenOptions {
struct_size: std::mem::size_of::<XlOpenOptions>() as i32,
csv_sniff_dialect: opt_state(self.csv_sniff_dialect),
csv_delimiter: opt_number(self.csv_delimiter),
csv_quote: opt_number(self.csv_quote),
csv_detect_bom: opt_state(self.csv_detect_bom),
csv_max_cell_bytes: opt_number(self.csv_max_cell_bytes),
csv_intern_strings: opt_state(self.csv_intern_strings),
max_total_decompressed_bytes: opt_number(self.max_total_decompressed_bytes),
max_cell_bytes: opt_number(self.max_cell_bytes),
max_shared_string_bytes: opt_number(self.max_shared_string_bytes),
max_zip_entries: opt_number(self.max_zip_entries),
prefetch_decompression: opt_state(self.prefetch_decompression),
intern_strings: opt_state(self.intern_strings),
}
}
}
fn opt_state(value: Option<bool>) -> i32 {
match value {
None => XL_OPT_DEFAULT,
Some(true) => XL_OPT_TRUE,
Some(false) => XL_OPT_FALSE,
}
}
fn opt_number<T: Default>(value: Option<T>) -> T {
value.unwrap_or_default()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn unset_fields_lower_to_the_abi_defaults() {
let raw = OpenOptions::new().to_raw();
assert_eq!(raw.struct_size, std::mem::size_of::<XlOpenOptions>() as i32);
assert_eq!(raw.csv_sniff_dialect, XL_OPT_DEFAULT);
assert_eq!(raw.prefetch_decompression, XL_OPT_DEFAULT);
assert_eq!(raw.csv_delimiter, 0);
assert_eq!(raw.max_total_decompressed_bytes, 0);
}
#[test]
fn booleans_lower_to_distinct_true_and_false_states() {
let raw = OpenOptions::new()
.prefetch_decompression(true)
.intern_strings(false)
.to_raw();
assert_eq!(raw.prefetch_decompression, XL_OPT_TRUE);
assert_eq!(raw.intern_strings, XL_OPT_FALSE);
assert_eq!(raw.csv_detect_bom, XL_OPT_DEFAULT);
}
#[test]
fn numbers_pass_through_unchanged() {
let raw = OpenOptions::new()
.csv_delimiter(b';' as i32)
.max_zip_entries(1024)
.max_shared_string_bytes(1 << 20)
.to_raw();
assert_eq!(raw.csv_delimiter, b';' as i32);
assert_eq!(raw.max_zip_entries, 1024);
assert_eq!(raw.max_shared_string_bytes, 1 << 20);
}
}