sheetkit_core/workbook/
open_options.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
3pub enum ReadMode {
4 Eager,
6 #[default]
13 Lazy,
14 Stream,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
21pub enum AuxParts {
22 #[default]
24 Deferred,
25 EagerLoad,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
39pub enum DateInterpretation {
40 CellType,
46 #[default]
52 NumFmt,
53}
54
55#[derive(Debug, Clone, Default)]
61pub struct OpenOptions {
62 pub sheet_rows: Option<u32>,
65
66 pub sheets: Option<Vec<String>>,
70
71 pub max_unzip_size: Option<u64>,
75
76 pub max_zip_entries: Option<usize>,
80
81 pub read_mode: ReadMode,
85
86 pub aux_parts: AuxParts,
88
89 pub date_interpretation: DateInterpretation,
94}
95
96impl OpenOptions {
97 pub fn new() -> Self {
99 Self::default()
100 }
101
102 pub fn sheet_rows(mut self, rows: u32) -> Self {
104 self.sheet_rows = Some(rows);
105 self
106 }
107
108 pub fn sheets(mut self, names: Vec<String>) -> Self {
110 self.sheets = Some(names);
111 self
112 }
113
114 pub fn max_unzip_size(mut self, size: u64) -> Self {
116 self.max_unzip_size = Some(size);
117 self
118 }
119
120 pub fn max_zip_entries(mut self, count: usize) -> Self {
122 self.max_zip_entries = Some(count);
123 self
124 }
125
126 pub fn read_mode(mut self, mode: ReadMode) -> Self {
129 self.read_mode = mode;
130 self
131 }
132
133 pub fn aux_parts(mut self, policy: AuxParts) -> Self {
135 self.aux_parts = policy;
136 self
137 }
138
139 pub fn date_interpretation(mut self, interpretation: DateInterpretation) -> Self {
144 self.date_interpretation = interpretation;
145 self
146 }
147
148 pub(crate) fn skip_aux_parts(&self) -> bool {
151 match self.read_mode {
152 ReadMode::Eager => self.aux_parts == AuxParts::Deferred,
153 ReadMode::Lazy | ReadMode::Stream => true,
154 }
155 }
156
157 #[allow(dead_code)]
159 pub(crate) fn is_eager(&self) -> bool {
160 self.read_mode == ReadMode::Eager
161 }
162
163 #[allow(dead_code)]
165 pub(crate) fn is_lazy(&self) -> bool {
166 self.read_mode == ReadMode::Lazy
167 }
168
169 #[allow(dead_code)]
171 pub(crate) fn is_stream(&self) -> bool {
172 self.read_mode == ReadMode::Stream
173 }
174
175 pub(crate) fn should_parse_sheet(&self, name: &str) -> bool {
177 match &self.sheets {
178 None => true,
179 Some(names) => names.iter().any(|n| n == name),
180 }
181 }
182}
183
184#[cfg(test)]
185mod tests {
186 use super::*;
187
188 #[test]
189 fn test_default_options() {
190 let opts = OpenOptions::default();
191 assert!(opts.sheet_rows.is_none());
192 assert!(opts.sheets.is_none());
193 assert!(opts.max_unzip_size.is_none());
194 assert!(opts.max_zip_entries.is_none());
195 assert_eq!(opts.read_mode, ReadMode::Lazy);
196 assert!(opts.skip_aux_parts());
197 assert_eq!(opts.date_interpretation, DateInterpretation::NumFmt);
198 }
199
200 #[test]
201 fn test_date_interpretation_default_is_num_fmt() {
202 assert_eq!(DateInterpretation::default(), DateInterpretation::NumFmt);
203 }
204
205 #[test]
206 fn test_date_interpretation_builder() {
207 let opts = OpenOptions::new().date_interpretation(DateInterpretation::CellType);
208 assert_eq!(opts.date_interpretation, DateInterpretation::CellType);
209
210 let opts = opts.date_interpretation(DateInterpretation::NumFmt);
211 assert_eq!(opts.date_interpretation, DateInterpretation::NumFmt);
212 }
213
214 #[test]
215 fn test_builder_methods() {
216 let opts = OpenOptions::new()
217 .sheet_rows(100)
218 .sheets(vec!["Sheet1".to_string()])
219 .max_unzip_size(1_000_000)
220 .max_zip_entries(500);
221 assert_eq!(opts.sheet_rows, Some(100));
222 assert_eq!(opts.sheets, Some(vec!["Sheet1".to_string()]));
223 assert_eq!(opts.max_unzip_size, Some(1_000_000));
224 assert_eq!(opts.max_zip_entries, Some(500));
225 }
226
227 #[test]
228 fn test_read_mode_builder() {
229 let opts = OpenOptions::new().read_mode(ReadMode::Lazy);
230 assert_eq!(opts.read_mode, ReadMode::Lazy);
231 assert!(opts.skip_aux_parts());
232 }
233
234 #[test]
235 fn test_read_mode_default_is_lazy() {
236 let mode = ReadMode::default();
237 assert_eq!(mode, ReadMode::Lazy);
238 }
239
240 #[test]
241 fn test_read_mode_combined_with_other_options() {
242 let opts = OpenOptions::new().sheet_rows(50).read_mode(ReadMode::Lazy);
243 assert_eq!(opts.sheet_rows, Some(50));
244 assert!(opts.skip_aux_parts());
245 }
246
247 #[test]
248 fn test_stream_mode_skips_aux_parts() {
249 let opts = OpenOptions::new().read_mode(ReadMode::Stream);
250 assert!(opts.skip_aux_parts());
251 assert!(opts.is_stream());
252 assert!(!opts.is_eager());
253 assert!(!opts.is_lazy());
254 }
255
256 #[test]
257 fn test_aux_parts_default_is_deferred() {
258 let opts = OpenOptions::default();
259 assert_eq!(opts.aux_parts, AuxParts::Deferred);
260 }
261
262 #[test]
263 fn test_aux_parts_deferred() {
264 let opts = OpenOptions::new().aux_parts(AuxParts::Deferred);
265 assert_eq!(opts.aux_parts, AuxParts::Deferred);
266 }
267
268 #[test]
269 fn test_eager_mode_with_deferred_aux_skips_aux() {
270 let opts = OpenOptions::new()
271 .read_mode(ReadMode::Eager)
272 .aux_parts(AuxParts::Deferred);
273 assert!(opts.skip_aux_parts());
274 }
275
276 #[test]
277 fn test_eager_mode_with_eager_aux_parses_all() {
278 let opts = OpenOptions::new()
279 .read_mode(ReadMode::Eager)
280 .aux_parts(AuxParts::EagerLoad);
281 assert!(!opts.skip_aux_parts());
282 }
283
284 #[test]
285 fn test_should_parse_sheet_no_filter() {
286 let opts = OpenOptions::default();
287 assert!(opts.should_parse_sheet("Sheet1"));
288 assert!(opts.should_parse_sheet("anything"));
289 }
290
291 #[test]
292 fn test_should_parse_sheet_with_filter() {
293 let opts = OpenOptions::new().sheets(vec!["Sales".to_string(), "Data".to_string()]);
294 assert!(opts.should_parse_sheet("Sales"));
295 assert!(opts.should_parse_sheet("Data"));
296 assert!(!opts.should_parse_sheet("Sheet1"));
297 assert!(!opts.should_parse_sheet("Other"));
298 }
299
300 #[test]
301 fn test_helper_methods() {
302 let eager = OpenOptions::new().read_mode(ReadMode::Eager);
303 assert!(eager.is_eager());
304 assert!(!eager.is_lazy());
305 assert!(!eager.is_stream());
306
307 let lazy = OpenOptions::new().read_mode(ReadMode::Lazy);
308 assert!(!lazy.is_eager());
309 assert!(lazy.is_lazy());
310 assert!(!lazy.is_stream());
311
312 let stream = OpenOptions::new().read_mode(ReadMode::Stream);
313 assert!(!stream.is_eager());
314 assert!(!stream.is_lazy());
315 assert!(stream.is_stream());
316 }
317}