#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ReadMode {
Eager,
#[default]
Lazy,
Stream,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum AuxParts {
#[default]
Deferred,
EagerLoad,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum DateInterpretation {
CellType,
#[default]
NumFmt,
}
#[derive(Debug, Clone, Default)]
pub struct OpenOptions {
pub sheet_rows: Option<u32>,
pub sheets: Option<Vec<String>>,
pub max_unzip_size: Option<u64>,
pub max_zip_entries: Option<usize>,
pub read_mode: ReadMode,
pub aux_parts: AuxParts,
pub date_interpretation: DateInterpretation,
}
impl OpenOptions {
pub fn new() -> Self {
Self::default()
}
pub fn sheet_rows(mut self, rows: u32) -> Self {
self.sheet_rows = Some(rows);
self
}
pub fn sheets(mut self, names: Vec<String>) -> Self {
self.sheets = Some(names);
self
}
pub fn max_unzip_size(mut self, size: u64) -> Self {
self.max_unzip_size = Some(size);
self
}
pub fn max_zip_entries(mut self, count: usize) -> Self {
self.max_zip_entries = Some(count);
self
}
pub fn read_mode(mut self, mode: ReadMode) -> Self {
self.read_mode = mode;
self
}
pub fn aux_parts(mut self, policy: AuxParts) -> Self {
self.aux_parts = policy;
self
}
pub fn date_interpretation(mut self, interpretation: DateInterpretation) -> Self {
self.date_interpretation = interpretation;
self
}
pub(crate) fn skip_aux_parts(&self) -> bool {
match self.read_mode {
ReadMode::Eager => self.aux_parts == AuxParts::Deferred,
ReadMode::Lazy | ReadMode::Stream => true,
}
}
#[allow(dead_code)]
pub(crate) fn is_eager(&self) -> bool {
self.read_mode == ReadMode::Eager
}
#[allow(dead_code)]
pub(crate) fn is_lazy(&self) -> bool {
self.read_mode == ReadMode::Lazy
}
#[allow(dead_code)]
pub(crate) fn is_stream(&self) -> bool {
self.read_mode == ReadMode::Stream
}
pub(crate) fn should_parse_sheet(&self, name: &str) -> bool {
match &self.sheets {
None => true,
Some(names) => names.iter().any(|n| n == name),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_options() {
let opts = OpenOptions::default();
assert!(opts.sheet_rows.is_none());
assert!(opts.sheets.is_none());
assert!(opts.max_unzip_size.is_none());
assert!(opts.max_zip_entries.is_none());
assert_eq!(opts.read_mode, ReadMode::Lazy);
assert!(opts.skip_aux_parts());
assert_eq!(opts.date_interpretation, DateInterpretation::NumFmt);
}
#[test]
fn test_date_interpretation_default_is_num_fmt() {
assert_eq!(DateInterpretation::default(), DateInterpretation::NumFmt);
}
#[test]
fn test_date_interpretation_builder() {
let opts = OpenOptions::new().date_interpretation(DateInterpretation::CellType);
assert_eq!(opts.date_interpretation, DateInterpretation::CellType);
let opts = opts.date_interpretation(DateInterpretation::NumFmt);
assert_eq!(opts.date_interpretation, DateInterpretation::NumFmt);
}
#[test]
fn test_builder_methods() {
let opts = OpenOptions::new()
.sheet_rows(100)
.sheets(vec!["Sheet1".to_string()])
.max_unzip_size(1_000_000)
.max_zip_entries(500);
assert_eq!(opts.sheet_rows, Some(100));
assert_eq!(opts.sheets, Some(vec!["Sheet1".to_string()]));
assert_eq!(opts.max_unzip_size, Some(1_000_000));
assert_eq!(opts.max_zip_entries, Some(500));
}
#[test]
fn test_read_mode_builder() {
let opts = OpenOptions::new().read_mode(ReadMode::Lazy);
assert_eq!(opts.read_mode, ReadMode::Lazy);
assert!(opts.skip_aux_parts());
}
#[test]
fn test_read_mode_default_is_lazy() {
let mode = ReadMode::default();
assert_eq!(mode, ReadMode::Lazy);
}
#[test]
fn test_read_mode_combined_with_other_options() {
let opts = OpenOptions::new().sheet_rows(50).read_mode(ReadMode::Lazy);
assert_eq!(opts.sheet_rows, Some(50));
assert!(opts.skip_aux_parts());
}
#[test]
fn test_stream_mode_skips_aux_parts() {
let opts = OpenOptions::new().read_mode(ReadMode::Stream);
assert!(opts.skip_aux_parts());
assert!(opts.is_stream());
assert!(!opts.is_eager());
assert!(!opts.is_lazy());
}
#[test]
fn test_aux_parts_default_is_deferred() {
let opts = OpenOptions::default();
assert_eq!(opts.aux_parts, AuxParts::Deferred);
}
#[test]
fn test_aux_parts_deferred() {
let opts = OpenOptions::new().aux_parts(AuxParts::Deferred);
assert_eq!(opts.aux_parts, AuxParts::Deferred);
}
#[test]
fn test_eager_mode_with_deferred_aux_skips_aux() {
let opts = OpenOptions::new()
.read_mode(ReadMode::Eager)
.aux_parts(AuxParts::Deferred);
assert!(opts.skip_aux_parts());
}
#[test]
fn test_eager_mode_with_eager_aux_parses_all() {
let opts = OpenOptions::new()
.read_mode(ReadMode::Eager)
.aux_parts(AuxParts::EagerLoad);
assert!(!opts.skip_aux_parts());
}
#[test]
fn test_should_parse_sheet_no_filter() {
let opts = OpenOptions::default();
assert!(opts.should_parse_sheet("Sheet1"));
assert!(opts.should_parse_sheet("anything"));
}
#[test]
fn test_should_parse_sheet_with_filter() {
let opts = OpenOptions::new().sheets(vec!["Sales".to_string(), "Data".to_string()]);
assert!(opts.should_parse_sheet("Sales"));
assert!(opts.should_parse_sheet("Data"));
assert!(!opts.should_parse_sheet("Sheet1"));
assert!(!opts.should_parse_sheet("Other"));
}
#[test]
fn test_helper_methods() {
let eager = OpenOptions::new().read_mode(ReadMode::Eager);
assert!(eager.is_eager());
assert!(!eager.is_lazy());
assert!(!eager.is_stream());
let lazy = OpenOptions::new().read_mode(ReadMode::Lazy);
assert!(!lazy.is_eager());
assert!(lazy.is_lazy());
assert!(!lazy.is_stream());
let stream = OpenOptions::new().read_mode(ReadMode::Stream);
assert!(!stream.is_eager());
assert!(!stream.is_lazy());
assert!(stream.is_stream());
}
}