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, Default)]
35pub struct OpenOptions {
36 pub sheet_rows: Option<u32>,
39
40 pub sheets: Option<Vec<String>>,
44
45 pub max_unzip_size: Option<u64>,
49
50 pub max_zip_entries: Option<usize>,
54
55 pub read_mode: ReadMode,
59
60 pub aux_parts: AuxParts,
62}
63
64impl OpenOptions {
65 pub fn new() -> Self {
67 Self::default()
68 }
69
70 pub fn sheet_rows(mut self, rows: u32) -> Self {
72 self.sheet_rows = Some(rows);
73 self
74 }
75
76 pub fn sheets(mut self, names: Vec<String>) -> Self {
78 self.sheets = Some(names);
79 self
80 }
81
82 pub fn max_unzip_size(mut self, size: u64) -> Self {
84 self.max_unzip_size = Some(size);
85 self
86 }
87
88 pub fn max_zip_entries(mut self, count: usize) -> Self {
90 self.max_zip_entries = Some(count);
91 self
92 }
93
94 pub fn read_mode(mut self, mode: ReadMode) -> Self {
97 self.read_mode = mode;
98 self
99 }
100
101 pub fn aux_parts(mut self, policy: AuxParts) -> Self {
103 self.aux_parts = policy;
104 self
105 }
106
107 pub(crate) fn skip_aux_parts(&self) -> bool {
110 match self.read_mode {
111 ReadMode::Eager => self.aux_parts == AuxParts::Deferred,
112 ReadMode::Lazy | ReadMode::Stream => true,
113 }
114 }
115
116 #[allow(dead_code)]
118 pub(crate) fn is_eager(&self) -> bool {
119 self.read_mode == ReadMode::Eager
120 }
121
122 #[allow(dead_code)]
124 pub(crate) fn is_lazy(&self) -> bool {
125 self.read_mode == ReadMode::Lazy
126 }
127
128 #[allow(dead_code)]
130 pub(crate) fn is_stream(&self) -> bool {
131 self.read_mode == ReadMode::Stream
132 }
133
134 pub(crate) fn should_parse_sheet(&self, name: &str) -> bool {
136 match &self.sheets {
137 None => true,
138 Some(names) => names.iter().any(|n| n == name),
139 }
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
148 fn test_default_options() {
149 let opts = OpenOptions::default();
150 assert!(opts.sheet_rows.is_none());
151 assert!(opts.sheets.is_none());
152 assert!(opts.max_unzip_size.is_none());
153 assert!(opts.max_zip_entries.is_none());
154 assert_eq!(opts.read_mode, ReadMode::Lazy);
155 assert!(opts.skip_aux_parts());
156 }
157
158 #[test]
159 fn test_builder_methods() {
160 let opts = OpenOptions::new()
161 .sheet_rows(100)
162 .sheets(vec!["Sheet1".to_string()])
163 .max_unzip_size(1_000_000)
164 .max_zip_entries(500);
165 assert_eq!(opts.sheet_rows, Some(100));
166 assert_eq!(opts.sheets, Some(vec!["Sheet1".to_string()]));
167 assert_eq!(opts.max_unzip_size, Some(1_000_000));
168 assert_eq!(opts.max_zip_entries, Some(500));
169 }
170
171 #[test]
172 fn test_read_mode_builder() {
173 let opts = OpenOptions::new().read_mode(ReadMode::Lazy);
174 assert_eq!(opts.read_mode, ReadMode::Lazy);
175 assert!(opts.skip_aux_parts());
176 }
177
178 #[test]
179 fn test_read_mode_default_is_lazy() {
180 let mode = ReadMode::default();
181 assert_eq!(mode, ReadMode::Lazy);
182 }
183
184 #[test]
185 fn test_read_mode_combined_with_other_options() {
186 let opts = OpenOptions::new().sheet_rows(50).read_mode(ReadMode::Lazy);
187 assert_eq!(opts.sheet_rows, Some(50));
188 assert!(opts.skip_aux_parts());
189 }
190
191 #[test]
192 fn test_stream_mode_skips_aux_parts() {
193 let opts = OpenOptions::new().read_mode(ReadMode::Stream);
194 assert!(opts.skip_aux_parts());
195 assert!(opts.is_stream());
196 assert!(!opts.is_eager());
197 assert!(!opts.is_lazy());
198 }
199
200 #[test]
201 fn test_aux_parts_default_is_deferred() {
202 let opts = OpenOptions::default();
203 assert_eq!(opts.aux_parts, AuxParts::Deferred);
204 }
205
206 #[test]
207 fn test_aux_parts_deferred() {
208 let opts = OpenOptions::new().aux_parts(AuxParts::Deferred);
209 assert_eq!(opts.aux_parts, AuxParts::Deferred);
210 }
211
212 #[test]
213 fn test_eager_mode_with_deferred_aux_skips_aux() {
214 let opts = OpenOptions::new()
215 .read_mode(ReadMode::Eager)
216 .aux_parts(AuxParts::Deferred);
217 assert!(opts.skip_aux_parts());
218 }
219
220 #[test]
221 fn test_eager_mode_with_eager_aux_parses_all() {
222 let opts = OpenOptions::new()
223 .read_mode(ReadMode::Eager)
224 .aux_parts(AuxParts::EagerLoad);
225 assert!(!opts.skip_aux_parts());
226 }
227
228 #[test]
229 fn test_should_parse_sheet_no_filter() {
230 let opts = OpenOptions::default();
231 assert!(opts.should_parse_sheet("Sheet1"));
232 assert!(opts.should_parse_sheet("anything"));
233 }
234
235 #[test]
236 fn test_should_parse_sheet_with_filter() {
237 let opts = OpenOptions::new().sheets(vec!["Sales".to_string(), "Data".to_string()]);
238 assert!(opts.should_parse_sheet("Sales"));
239 assert!(opts.should_parse_sheet("Data"));
240 assert!(!opts.should_parse_sheet("Sheet1"));
241 assert!(!opts.should_parse_sheet("Other"));
242 }
243
244 #[test]
245 fn test_helper_methods() {
246 let eager = OpenOptions::new().read_mode(ReadMode::Eager);
247 assert!(eager.is_eager());
248 assert!(!eager.is_lazy());
249 assert!(!eager.is_stream());
250
251 let lazy = OpenOptions::new().read_mode(ReadMode::Lazy);
252 assert!(!lazy.is_eager());
253 assert!(lazy.is_lazy());
254 assert!(!lazy.is_stream());
255
256 let stream = OpenOptions::new().read_mode(ReadMode::Stream);
257 assert!(!stream.is_eager());
258 assert!(!stream.is_lazy());
259 assert!(stream.is_stream());
260 }
261}