1use super::array::ArrayArena;
4use super::ast::{AstArena, AstNodeId, CompactRefType, SheetKey};
5use super::error_arena::{ErrorArena, ErrorRef};
6use super::scalar::ScalarArena;
7use super::string_interner::{StringId, StringInterner};
8use super::value_ref::ValueRef;
9use crate::engine::sheet_registry::SheetRegistry;
10use formualizer_common::{ExcelError, ExcelErrorKind, LiteralValue};
11use formualizer_parse::parser::{
12 ASTNode, ASTNodeType, ExternalBookRef, ExternalReference, ReferenceType, TableReference,
13};
14
15#[derive(Debug)]
17pub struct DataStore {
18 scalars: ScalarArena,
20
21 strings: StringInterner,
23
24 arrays: ArrayArena,
26
27 asts: AstArena,
29
30 errors: ErrorArena,
32}
33
34impl DataStore {
35 pub fn new() -> Self {
36 Self {
37 scalars: ScalarArena::new(),
38 strings: StringInterner::new(),
39 arrays: ArrayArena::new(),
40 asts: AstArena::new(),
41 errors: ErrorArena::new(),
42 }
43 }
44
45 pub fn store_values_batch<I>(&mut self, values: I) -> Vec<ValueRef>
47 where
48 I: IntoIterator<Item = LiteralValue>,
49 {
50 let iter = values.into_iter();
51 let (lower, _) = iter.size_hint();
52 let mut out = Vec::with_capacity(lower);
53 for v in iter {
54 out.push(self.store_value(v));
55 }
56 out
57 }
58
59 pub fn store_asts_batch<'a, I>(
61 &mut self,
62 asts: I,
63 sheet_registry: &SheetRegistry,
64 ) -> Vec<AstNodeId>
65 where
66 I: IntoIterator<Item = &'a ASTNode>,
67 {
68 let iter = asts.into_iter();
69 let (lower, _) = iter.size_hint();
70 let mut out = Vec::with_capacity(lower);
71 for ast in iter {
72 out.push(self.store_ast(ast, sheet_registry));
73 }
74 out
75 }
76
77 pub fn with_capacity(estimated_cells: usize) -> Self {
78 Self {
79 scalars: ScalarArena::with_capacity(estimated_cells),
80 strings: StringInterner::with_capacity(estimated_cells / 10),
81 arrays: ArrayArena::with_capacity(estimated_cells / 100),
82 asts: AstArena::with_capacity(estimated_cells / 2),
83 errors: ErrorArena::with_capacity(estimated_cells / 20),
84 }
85 }
86
87 pub fn store_value(&mut self, value: LiteralValue) -> ValueRef {
89 match value {
90 LiteralValue::Empty => ValueRef::empty(),
91
92 LiteralValue::Number(n) => {
93 let idx = self.scalars.insert_float(n);
95 ValueRef::number(idx.as_u32())
96 }
97
98 LiteralValue::Text(s) => {
99 let id = self.strings.intern(&s);
100 ValueRef::string(id.as_u32())
101 }
102
103 LiteralValue::Boolean(b) => ValueRef::boolean(b),
104
105 LiteralValue::Error(err) => self.store_error(&err),
106
107 LiteralValue::Array(array) => {
108 let rows = array.len() as u32;
110 let cols = array.first().map(|r| r.len()).unwrap_or(0) as u32;
111
112 let elements: Vec<ValueRef> = array
113 .into_iter()
114 .flatten()
115 .map(|v| self.store_value(v))
116 .collect();
117
118 let array_ref = self.arrays.insert(rows, cols, elements);
119 ValueRef::array(array_ref.as_u32())
120 }
121
122 LiteralValue::DateTime(dt) => {
123 let serial = formualizer_common::datetime_to_serial_for(
127 formualizer_common::DateSystem::Excel1900,
128 &dt,
129 );
130 let idx = self.scalars.insert_float(serial);
131 ValueRef::date_time(idx.as_u32())
132 }
133
134 LiteralValue::Date(d) => {
135 let dt = d.and_hms_opt(0, 0, 0).unwrap();
137 let serial = formualizer_common::datetime_to_serial_for(
138 formualizer_common::DateSystem::Excel1900,
139 &dt,
140 );
141 let idx = self.scalars.insert_float(serial);
142 ValueRef::date_time(idx.as_u32())
143 }
144
145 LiteralValue::Time(t) => {
146 let fraction = formualizer_common::time_to_fraction(&t);
148 let idx = self.scalars.insert_float(fraction);
149 ValueRef::date_time(idx.as_u32())
150 }
151
152 LiteralValue::Duration(dur) => {
153 let secs = dur.num_seconds();
155 let idx = self.scalars.insert_integer(secs);
156 let raw_index = idx.as_u32() & 0x7FFF_FFFF;
157 ValueRef::duration(raw_index)
158 }
159
160 LiteralValue::Int(i) => {
161 if let Some(vref) = ValueRef::small_int(i as i32) {
163 vref
164 } else {
165 let idx = self.scalars.insert_integer(i);
167 ValueRef::large_int(idx.as_u32())
168 }
169 }
170
171 LiteralValue::Pending => ValueRef::pending(),
172 }
173 }
174
175 pub fn retrieve_value(&self, value_ref: ValueRef) -> LiteralValue {
177 use super::value_ref::ValueType;
178
179 match value_ref.value_type() {
180 ValueType::Empty => LiteralValue::Empty,
181
182 ValueType::SmallInt => {
183 if let Some(i) = value_ref.as_small_int() {
185 LiteralValue::Int(i as i64)
186 } else {
187 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
188 }
189 }
190
191 ValueType::LargeInt => {
192 if let Some(idx) = value_ref.arena_index() {
193 let scalar_ref = super::scalar::ScalarRef::from_raw(idx | (1 << 31));
194 if let Some(i) = self.scalars.get_integer(scalar_ref) {
195 LiteralValue::Int(i)
196 } else {
197 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
198 }
199 } else {
200 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
201 }
202 }
203
204 ValueType::Number => {
205 if let Some(idx) = value_ref.arena_index() {
206 let scalar_ref = super::scalar::ScalarRef::from_raw(idx);
207 if let Some(f) = self.scalars.get_float(scalar_ref) {
208 LiteralValue::Number(f)
209 } else {
210 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
211 }
212 } else {
213 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
214 }
215 }
216
217 ValueType::String => {
218 if let Some(idx) = value_ref.arena_index() {
219 let string_id = StringId::from_raw(idx);
220 let s = self.strings.resolve(string_id);
221 LiteralValue::Text(s.to_string())
222 } else {
223 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
224 }
225 }
226
227 ValueType::Boolean => {
228 if let Some(b) = value_ref.as_boolean() {
229 LiteralValue::Boolean(b)
230 } else {
231 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
232 }
233 }
234
235 ValueType::Error => {
236 if let Some(error_ref_raw) = value_ref.as_error_ref() {
237 let error_ref = ErrorRef::from_raw(error_ref_raw);
238 if let Some(error) = self.errors.get(error_ref) {
239 LiteralValue::Error(error)
240 } else {
241 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
242 }
243 } else {
244 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
245 }
246 }
247
248 ValueType::Array => {
249 if let Some(idx) = value_ref.arena_index() {
250 let array_ref = super::array::ArrayRef::from_raw(idx);
251 if let Some(array_2d) = self.arrays.get_2d(array_ref) {
252 let result: Vec<Vec<LiteralValue>> = array_2d
254 .into_iter()
255 .map(|row| row.into_iter().map(|v| self.retrieve_value(v)).collect())
256 .collect();
257 LiteralValue::Array(result)
258 } else {
259 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
260 }
261 } else {
262 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
263 }
264 }
265
266 ValueType::DateTime => {
267 if let Some(idx) = value_ref.arena_index() {
268 let scalar_ref = super::scalar::ScalarRef::from_raw(idx);
269 if let Some(serial) = self.scalars.get_float(scalar_ref) {
270 LiteralValue::DateTime(formualizer_common::serial_to_datetime(serial))
275 } else {
276 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
277 }
278 } else {
279 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
280 }
281 }
282
283 ValueType::Duration => {
284 if let Some(idx) = value_ref.arena_index() {
285 let scalar_ref = super::scalar::ScalarRef::from_raw(idx | (1 << 31));
286 if let Some(secs) = self.scalars.get_integer(scalar_ref) {
287 let dur = chrono::Duration::seconds(secs);
288 LiteralValue::Duration(dur)
289 } else {
290 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
291 }
292 } else {
293 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
294 }
295 }
296
297 ValueType::Pending => LiteralValue::Pending,
298
299 ValueType::FormulaAst => {
300 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
302 }
303 }
304 }
305
306 pub fn store_ast(&mut self, ast: &ASTNode, sheet_registry: &SheetRegistry) -> AstNodeId {
308 self.convert_ast_node(ast, sheet_registry)
309 }
310
311 pub fn retrieve_ast(&self, id: AstNodeId, sheet_registry: &SheetRegistry) -> Option<ASTNode> {
313 self.reconstruct_ast_node(id, sheet_registry)
314 }
315
316 pub fn resolve_ast_string(&self, id: StringId) -> &str {
317 self.asts.resolve_string(id)
318 }
319
320 pub(crate) fn ast_strings(&self) -> &StringInterner {
321 self.asts.strings()
322 }
323
324 pub fn reconstruct_reference_type_for_eval(
325 &self,
326 ref_type: &CompactRefType,
327 sheet_registry: &SheetRegistry,
328 ) -> ReferenceType {
329 self.reconstruct_reference_type(ref_type, sheet_registry)
330 }
331
332 pub fn get_node(&self, id: AstNodeId) -> Option<&super::ast::AstNodeData> {
333 self.asts.get(id)
334 }
335
336 pub fn get_args(&self, id: AstNodeId) -> Option<&[AstNodeId]> {
337 self.asts.get_function_args(id)
338 }
339
340 pub fn get_array_elems(&self, id: AstNodeId) -> Option<(u16, u16, &[AstNodeId])> {
341 self.asts.get_array_elements_info(id)
342 }
343
344 pub fn ast_needs_structural_rewrite(&self, id: AstNodeId) -> bool {
345 let mut stack = vec![id];
346 while let Some(node_id) = stack.pop() {
347 let Some(node) = self.get_node(node_id) else {
348 continue;
349 };
350 match node {
351 super::ast::AstNodeData::Reference { ref_type, .. } => {
352 if let CompactRefType::Table { name_id, .. } = ref_type
353 && self.resolve_ast_string(*name_id).is_empty()
354 {
355 return true;
356 }
357 }
358 super::ast::AstNodeData::UnaryOp { expr_id, .. } => stack.push(*expr_id),
359 super::ast::AstNodeData::BinaryOp {
360 left_id, right_id, ..
361 } => {
362 stack.push(*right_id);
363 stack.push(*left_id);
364 }
365 super::ast::AstNodeData::Function { .. } => {
366 if let Some(args) = self.get_args(node_id) {
367 stack.extend(args.iter().rev().copied());
368 }
369 }
370 super::ast::AstNodeData::Array { .. } => {
371 if let Some((_, _, elems)) = self.get_array_elems(node_id) {
372 stack.extend(elems.iter().rev().copied());
373 }
374 }
375 super::ast::AstNodeData::Literal(_) | super::ast::AstNodeData::Omitted => {}
376 }
377 }
378 false
379 }
380
381 fn convert_ast_node(&mut self, node: &ASTNode, sheet_registry: &SheetRegistry) -> AstNodeId {
383 match &node.node_type {
384 ASTNodeType::Literal(lit) => {
385 let value_ref = self.store_value(lit.clone());
386 self.asts.insert_literal(value_ref)
387 }
388
389 ASTNodeType::Omitted => self.asts.insert_omitted(),
390
391 ASTNodeType::Reference {
392 original,
393 reference,
394 } => {
395 let ref_type = self.convert_reference_type(reference, sheet_registry);
396 self.asts.insert_reference(original, ref_type)
397 }
398
399 ASTNodeType::UnaryOp { op, expr } => {
400 let expr_id = self.convert_ast_node(expr, sheet_registry);
401 self.asts.insert_unary_op(op, expr_id)
402 }
403
404 ASTNodeType::BinaryOp { op, left, right } => {
405 let left_id = self.convert_ast_node(left, sheet_registry);
406 let right_id = self.convert_ast_node(right, sheet_registry);
407 self.asts.insert_binary_op(op, left_id, right_id)
408 }
409
410 ASTNodeType::Function { name, args } => {
411 let arg_ids: Vec<AstNodeId> = args
412 .iter()
413 .map(|arg| self.convert_ast_node(arg, sheet_registry))
414 .collect();
415 self.asts.insert_function(name, arg_ids)
416 }
417
418 ASTNodeType::Array(rows) => {
419 let total_elements = rows.iter().map(|r| r.len()).sum();
420 let mut elements = Vec::with_capacity(total_elements);
421
422 let rows_count = rows.len() as u16;
423 let cols_count = rows.first().map(|r| r.len()).unwrap_or(0) as u16;
424
425 for row in rows {
426 for elem in row {
427 elements.push(self.convert_ast_node(elem, sheet_registry));
428 }
429 }
430
431 self.asts.insert_array(rows_count, cols_count, elements)
432 }
433
434 ASTNodeType::Call { .. } => {
441 let value_ref = self.store_value(LiteralValue::Error(
442 ExcelError::new(ExcelErrorKind::NImpl)
443 .with_message("Immediate-invocation calls are not yet supported"),
444 ));
445 self.asts.insert_literal(value_ref)
446 }
447 }
448 }
449
450 fn convert_reference_type(
452 &mut self,
453 ref_type: &ReferenceType,
454 sheet_registry: &SheetRegistry,
455 ) -> CompactRefType {
456 match ref_type {
457 ReferenceType::Cell {
458 sheet,
459 row,
460 col,
461 row_abs,
462 col_abs,
463 } => {
464 let sheet = match sheet.as_ref() {
465 Some(s) => match sheet_registry.get_id(s) {
466 Some(id) => Some(SheetKey::Id(id)),
467 None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
468 },
469 None => None,
470 };
471 CompactRefType::Cell {
472 sheet,
473 row: *row,
474 col: *col,
475 row_abs: *row_abs,
476 col_abs: *col_abs,
477 }
478 }
479
480 ReferenceType::Range {
481 sheet,
482 start_row,
483 start_col,
484 end_row,
485 end_col,
486 start_row_abs,
487 start_col_abs,
488 end_row_abs,
489 end_col_abs,
490 } => {
491 let sheet = match sheet.as_ref() {
492 Some(s) => match sheet_registry.get_id(s) {
493 Some(id) => Some(SheetKey::Id(id)),
494 None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
495 },
496 None => None,
497 };
498 CompactRefType::Range {
500 sheet,
501 start_row: start_row.unwrap_or(0),
502 start_col: start_col.unwrap_or(0),
503 end_row: end_row.unwrap_or(u32::MAX),
504 end_col: end_col.unwrap_or(u32::MAX),
505 start_row_abs: *start_row_abs,
506 start_col_abs: *start_col_abs,
507 end_row_abs: *end_row_abs,
508 end_col_abs: *end_col_abs,
509 }
510 }
511
512 ReferenceType::External(ext) => {
513 let raw_id = self.asts.strings_mut().intern(&ext.raw);
514 let book_id = self.asts.strings_mut().intern(ext.book.token());
515 let sheet_id = self.asts.strings_mut().intern(&ext.sheet);
516 CompactRefType::External {
517 raw_id,
518 book_id,
519 sheet_id,
520 kind: ext.kind,
521 }
522 }
523
524 ReferenceType::NamedRange(name) => {
525 let string_id = self.asts.strings_mut().intern(name);
526 CompactRefType::NamedRange(string_id)
527 }
528
529 ReferenceType::Table(table_ref) => {
530 let name_id = self.asts.strings_mut().intern(&table_ref.name);
531 let specifier_id = table_ref
532 .specifier
533 .as_ref()
534 .map(|specifier| self.asts.intern_table_specifier(specifier));
535 CompactRefType::Table {
536 name_id,
537 specifier_id,
538 }
539 }
540
541 ReferenceType::Cell3D {
542 sheet_first,
543 sheet_last,
544 row,
545 col,
546 row_abs,
547 col_abs,
548 } => {
549 let sheet_first = self.asts.strings_mut().intern(sheet_first);
550 let sheet_last = self.asts.strings_mut().intern(sheet_last);
551 CompactRefType::Cell3D {
552 sheet_first,
553 sheet_last,
554 row: *row,
555 col: *col,
556 row_abs: *row_abs,
557 col_abs: *col_abs,
558 }
559 }
560
561 ReferenceType::Range3D {
562 sheet_first,
563 sheet_last,
564 start_row,
565 start_col,
566 end_row,
567 end_col,
568 start_row_abs,
569 start_col_abs,
570 end_row_abs,
571 end_col_abs,
572 } => {
573 let sheet_first = self.asts.strings_mut().intern(sheet_first);
574 let sheet_last = self.asts.strings_mut().intern(sheet_last);
575 CompactRefType::Range3D {
576 sheet_first,
577 sheet_last,
578 start_row: start_row.unwrap_or(0),
579 start_col: start_col.unwrap_or(0),
580 end_row: end_row.unwrap_or(u32::MAX),
581 end_col: end_col.unwrap_or(u32::MAX),
582 start_row_abs: *start_row_abs,
583 start_col_abs: *start_col_abs,
584 end_row_abs: *end_row_abs,
585 end_col_abs: *end_col_abs,
586 }
587 }
588 }
589 }
590
591 pub(crate) fn reconstruct_ast_node(
593 &self,
594 id: AstNodeId,
595 sheet_registry: &SheetRegistry,
596 ) -> Option<ASTNode> {
597 use super::ast::AstNodeData;
598
599 let node_data = self.asts.get(id)?;
600
601 let node_type = match node_data {
602 AstNodeData::Literal(value_ref) => {
603 let lit = self.retrieve_value(*value_ref);
604 ASTNodeType::Literal(lit)
605 }
606
607 AstNodeData::Omitted => ASTNodeType::Omitted,
608
609 AstNodeData::Reference {
610 original_id,
611 ref_type,
612 } => {
613 let original = self.asts.resolve_string(*original_id).to_string();
614 let reference = self.reconstruct_reference_type(ref_type, sheet_registry);
615 ASTNodeType::Reference {
616 original,
617 reference,
618 }
619 }
620
621 AstNodeData::UnaryOp { op_id, expr_id } => {
622 let op = self.asts.resolve_string(*op_id).to_string();
623 let expr = Box::new(self.reconstruct_ast_node(*expr_id, sheet_registry)?);
624 ASTNodeType::UnaryOp { op, expr }
625 }
626
627 AstNodeData::BinaryOp {
628 op_id,
629 left_id,
630 right_id,
631 } => {
632 let op = self.asts.resolve_string(*op_id).to_string();
633 let left = Box::new(self.reconstruct_ast_node(*left_id, sheet_registry)?);
634 let right = Box::new(self.reconstruct_ast_node(*right_id, sheet_registry)?);
635 ASTNodeType::BinaryOp { op, left, right }
636 }
637
638 AstNodeData::Function { name_id, .. } => {
639 let name = self.asts.resolve_string(*name_id).to_string();
640 let arg_ids = self.asts.get_function_args(id)?;
641 let args: Vec<ASTNode> = arg_ids
642 .iter()
643 .filter_map(|&arg_id| self.reconstruct_ast_node(arg_id, sheet_registry))
644 .collect();
645 ASTNodeType::Function { name, args }
646 }
647
648 AstNodeData::Array { rows, cols, .. } => {
649 let elements = self.asts.get_array_elements(id)?;
650 let mut result = Vec::with_capacity(*rows as usize);
651
652 for r in 0..*rows {
653 let mut row = Vec::with_capacity(*cols as usize);
654 for c in 0..*cols {
655 let idx = (r * *cols + c) as usize;
656 if let Some(&elem_id) = elements.get(idx)
657 && let Some(node) = self.reconstruct_ast_node(elem_id, sheet_registry)
658 {
659 row.push(node);
660 }
661 }
662 result.push(row);
663 }
664
665 ASTNodeType::Array(result)
666 }
667 };
668
669 Some(ASTNode {
670 node_type,
671 source_token: None, contains_volatile: false,
673 })
674 }
675
676 fn reconstruct_reference_type(
678 &self,
679 ref_type: &CompactRefType,
680 sheet_registry: &SheetRegistry,
681 ) -> ReferenceType {
682 match ref_type {
683 CompactRefType::Cell {
684 sheet,
685 row,
686 col,
687 row_abs,
688 col_abs,
689 } => {
690 let sheet = match sheet {
691 Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
692 Some(SheetKey::Name(name_id)) => {
693 Some(self.asts.resolve_string(*name_id).to_string())
694 }
695 None => None,
696 };
697 ReferenceType::Cell {
698 sheet,
699 row: *row,
700 col: *col,
701 row_abs: *row_abs,
702 col_abs: *col_abs,
703 }
704 }
705
706 CompactRefType::Range {
707 sheet,
708 start_row,
709 start_col,
710 end_row,
711 end_col,
712 start_row_abs,
713 start_col_abs,
714 end_row_abs,
715 end_col_abs,
716 } => {
717 let sheet = match sheet {
718 Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
719 Some(SheetKey::Name(name_id)) => {
720 Some(self.asts.resolve_string(*name_id).to_string())
721 }
722 None => None,
723 };
724 ReferenceType::Range {
726 sheet,
727 start_row: if *start_row == 0 {
728 None
729 } else {
730 Some(*start_row)
731 },
732 start_col: if *start_col == 0 {
733 None
734 } else {
735 Some(*start_col)
736 },
737 end_row: if *end_row == u32::MAX {
738 None
739 } else {
740 Some(*end_row)
741 },
742 end_col: if *end_col == u32::MAX {
743 None
744 } else {
745 Some(*end_col)
746 },
747 start_row_abs: *start_row_abs,
748 start_col_abs: *start_col_abs,
749 end_row_abs: *end_row_abs,
750 end_col_abs: *end_col_abs,
751 }
752 }
753
754 CompactRefType::External {
755 raw_id,
756 book_id,
757 sheet_id,
758 kind,
759 } => {
760 let raw = self.asts.resolve_string(*raw_id).to_string();
761 let book = self.asts.resolve_string(*book_id).to_string();
762 let sheet = self.asts.resolve_string(*sheet_id).to_string();
763 ReferenceType::External(ExternalReference {
764 raw,
765 book: ExternalBookRef::Token(book),
766 sheet,
767 kind: *kind,
768 })
769 }
770
771 CompactRefType::NamedRange(string_id) => {
772 let name = self.asts.resolve_string(*string_id).to_string();
773 ReferenceType::NamedRange(name)
774 }
775
776 CompactRefType::Table {
777 name_id,
778 specifier_id,
779 } => {
780 let name = self.asts.resolve_string(*name_id).to_string();
781 let specifier = specifier_id
782 .and_then(|id| self.asts.resolve_table_specifier(id))
783 .cloned();
784 ReferenceType::Table(TableReference { name, specifier })
785 }
786
787 CompactRefType::Cell3D {
788 sheet_first,
789 sheet_last,
790 row,
791 col,
792 row_abs,
793 col_abs,
794 } => ReferenceType::Cell3D {
795 sheet_first: self.asts.resolve_string(*sheet_first).to_string(),
796 sheet_last: self.asts.resolve_string(*sheet_last).to_string(),
797 row: *row,
798 col: *col,
799 row_abs: *row_abs,
800 col_abs: *col_abs,
801 },
802
803 CompactRefType::Range3D {
804 sheet_first,
805 sheet_last,
806 start_row,
807 start_col,
808 end_row,
809 end_col,
810 start_row_abs,
811 start_col_abs,
812 end_row_abs,
813 end_col_abs,
814 } => ReferenceType::Range3D {
815 sheet_first: self.asts.resolve_string(*sheet_first).to_string(),
816 sheet_last: self.asts.resolve_string(*sheet_last).to_string(),
817 start_row: if *start_row == 0 {
818 None
819 } else {
820 Some(*start_row)
821 },
822 start_col: if *start_col == 0 {
823 None
824 } else {
825 Some(*start_col)
826 },
827 end_row: if *end_row == u32::MAX {
828 None
829 } else {
830 Some(*end_row)
831 },
832 end_col: if *end_col == u32::MAX {
833 None
834 } else {
835 Some(*end_col)
836 },
837 start_row_abs: *start_row_abs,
838 start_col_abs: *start_col_abs,
839 end_row_abs: *end_row_abs,
840 end_col_abs: *end_col_abs,
841 },
842 }
843 }
844
845 fn store_error(&mut self, error: &ExcelError) -> ValueRef {
847 let error_ref = self.errors.insert(error);
848 ValueRef::error(error_ref.as_u32())
849 }
850
851 pub fn memory_usage(&self) -> DataStoreStats {
853 DataStoreStats {
854 scalar_bytes: self.scalars.memory_usage(),
855 string_bytes: self.strings.memory_usage(),
856 array_bytes: self.arrays.memory_usage(),
857 ast_bytes: self.asts.memory_usage(),
858 error_bytes: self.errors.memory_usage(),
859 total_scalars: self.scalars.len(),
860 total_strings: self.strings.len(),
861 total_arrays: self.arrays.len(),
862 total_ast_nodes: self.asts.stats().node_count,
863 total_errors: self.errors.len(),
864 }
865 }
866
867 pub fn clear(&mut self) {
869 self.scalars.clear();
870 self.strings.clear();
871 self.arrays.clear();
872 self.asts.clear();
873 self.errors.clear();
874 }
875}
876
877impl Default for DataStore {
878 fn default() -> Self {
879 Self::new()
880 }
881}
882
883#[derive(Debug, Clone)]
885pub struct DataStoreStats {
886 pub scalar_bytes: usize,
887 pub string_bytes: usize,
888 pub array_bytes: usize,
889 pub ast_bytes: usize,
890 pub error_bytes: usize,
891 pub total_scalars: usize,
892 pub total_strings: usize,
893 pub total_arrays: usize,
894 pub total_ast_nodes: usize,
895 pub total_errors: usize,
896}
897
898impl DataStoreStats {
899 pub fn total_bytes(&self) -> usize {
900 self.scalar_bytes + self.string_bytes + self.array_bytes + self.ast_bytes + self.error_bytes
901 }
902}
903
904impl super::array::ArrayRef {
906 pub fn from_raw(raw: u32) -> Self {
907 super::array::ArrayRef(raw)
908 }
909}
910
911impl super::scalar::ScalarRef {
912 pub fn from_raw(raw: u32) -> Self {
913 Self { raw }
914 }
915
916 pub fn as_u32(self) -> u32 {
917 self.raw
918 }
919}
920
921#[cfg(test)]
922mod tests {
923 use super::*;
924
925 #[test]
926 fn test_data_store_empty_value() {
927 let mut store = DataStore::new();
928 let value_ref = store.store_value(LiteralValue::Empty);
929 assert!(value_ref.is_empty());
930
931 let retrieved = store.retrieve_value(value_ref);
932 assert_eq!(retrieved, LiteralValue::Empty);
933 }
934
935 #[test]
936 fn test_data_store_number() {
937 let mut store = DataStore::new();
938 let value_ref = store.store_value(LiteralValue::Number(42.5));
939
940 let retrieved = store.retrieve_value(value_ref);
941 assert_eq!(retrieved, LiteralValue::Number(42.5));
942 }
943
944 #[test]
945 fn test_data_store_datetime_private_encoding_round_trips() {
946 let mut store = DataStore::new();
947 for datetime in [
948 chrono::NaiveDate::from_ymd_opt(2024, 1, 15)
949 .unwrap()
950 .and_hms_opt(12, 30, 0)
951 .unwrap(),
952 chrono::NaiveDate::from_ymd_opt(1899, 12, 30)
953 .unwrap()
954 .and_hms_opt(0, 0, 0)
955 .unwrap(),
956 ] {
957 let value_ref = store.store_value(LiteralValue::DateTime(datetime));
958 assert_eq!(
959 store.retrieve_value(value_ref),
960 LiteralValue::DateTime(datetime)
961 );
962 }
963 }
964
965 #[test]
966 fn test_data_store_text() {
967 let mut store = DataStore::new();
968 let value_ref = store.store_value(LiteralValue::Text("Hello".to_string()));
969
970 let retrieved = store.retrieve_value(value_ref);
971 assert_eq!(retrieved, LiteralValue::Text("Hello".to_string()));
972 }
973
974 #[test]
975 fn test_data_store_boolean() {
976 let mut store = DataStore::new();
977
978 let true_ref = store.store_value(LiteralValue::Boolean(true));
979 let false_ref = store.store_value(LiteralValue::Boolean(false));
980
981 assert_eq!(store.retrieve_value(true_ref), LiteralValue::Boolean(true));
982 assert_eq!(
983 store.retrieve_value(false_ref),
984 LiteralValue::Boolean(false)
985 );
986 }
987
988 #[test]
989 fn test_data_store_error() {
990 let mut store = DataStore::new();
991
992 let error = ExcelError::new(ExcelErrorKind::Div);
993 let value_ref = store.store_value(LiteralValue::Error(error.clone()));
994
995 let retrieved = store.retrieve_value(value_ref);
996 match retrieved {
997 LiteralValue::Error(e) => assert_eq!(e.kind, ExcelErrorKind::Div),
998 _ => panic!("Expected error"),
999 }
1000 }
1001
1002 #[test]
1003 fn test_data_store_array() {
1004 let mut store = DataStore::new();
1005
1006 let array = vec![
1007 vec![LiteralValue::Number(1.0), LiteralValue::Number(2.0)],
1008 vec![LiteralValue::Number(3.0), LiteralValue::Number(4.0)],
1009 ];
1010
1011 let value_ref = store.store_value(LiteralValue::Array(array.clone()));
1012 let retrieved = store.retrieve_value(value_ref);
1013
1014 assert_eq!(retrieved, LiteralValue::Array(array));
1015 }
1016
1017 #[test]
1018 fn test_data_store_ast_literal() {
1019 let mut store = DataStore::new();
1020 let mut sheet_registry = SheetRegistry::new();
1021 sheet_registry.id_for("Sheet1");
1022
1023 let ast = ASTNode {
1024 node_type: ASTNodeType::Literal(LiteralValue::Number(42.0)),
1025 source_token: None,
1026 contains_volatile: false,
1027 };
1028
1029 let ast_id = store.store_ast(&ast, &sheet_registry);
1030 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
1031
1032 match retrieved.node_type {
1033 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(42.0)),
1034 _ => panic!("Expected literal"),
1035 }
1036 }
1037
1038 #[test]
1039 fn test_data_store_ast_binary_op() {
1040 let mut store = DataStore::new();
1041 let mut sheet_registry = SheetRegistry::new();
1042 sheet_registry.id_for("Sheet1");
1043
1044 let ast = ASTNode {
1045 node_type: ASTNodeType::BinaryOp {
1046 op: "+".to_string(),
1047 left: Box::new(ASTNode {
1048 node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
1049 source_token: None,
1050 contains_volatile: false,
1051 }),
1052 right: Box::new(ASTNode {
1053 node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
1054 source_token: None,
1055 contains_volatile: false,
1056 }),
1057 },
1058 source_token: None,
1059 contains_volatile: false,
1060 };
1061
1062 let ast_id = store.store_ast(&ast, &sheet_registry);
1063 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
1064
1065 match retrieved.node_type {
1066 ASTNodeType::BinaryOp { op, left, right } => {
1067 assert_eq!(op, "+");
1068 match left.node_type {
1069 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(1.0)),
1070 _ => panic!("Expected literal"),
1071 }
1072 match right.node_type {
1073 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(2.0)),
1074 _ => panic!("Expected literal"),
1075 }
1076 }
1077 _ => panic!("Expected binary op"),
1078 }
1079 }
1080
1081 #[test]
1082 fn test_data_store_ast_function() {
1083 let mut store = DataStore::new();
1084 let mut sheet_registry = SheetRegistry::new();
1085 sheet_registry.id_for("Sheet1");
1086
1087 let ast = ASTNode {
1088 node_type: ASTNodeType::Function {
1089 name: "SUM".to_string(),
1090 args: vec![
1091 ASTNode {
1092 node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
1093 source_token: None,
1094 contains_volatile: false,
1095 },
1096 ASTNode {
1097 node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
1098 source_token: None,
1099 contains_volatile: false,
1100 },
1101 ],
1102 },
1103 source_token: None,
1104 contains_volatile: false,
1105 };
1106
1107 let ast_id = store.store_ast(&ast, &sheet_registry);
1108 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
1109
1110 match retrieved.node_type {
1111 ASTNodeType::Function { name, args } => {
1112 assert_eq!(name, "SUM");
1113 assert_eq!(args.len(), 2);
1114 }
1115 _ => panic!("Expected function"),
1116 }
1117 }
1118
1119 #[test]
1120 fn test_data_store_memory_stats() {
1121 let mut store = DataStore::new();
1122
1123 store.store_value(LiteralValue::Number(42.0));
1125 store.store_value(LiteralValue::Text("Hello".to_string()));
1126 store.store_value(LiteralValue::Array(vec![vec![LiteralValue::Number(1.0)]]));
1127
1128 let stats = store.memory_usage();
1129 assert!(stats.total_bytes() > 0);
1130 assert_eq!(stats.total_scalars, 2); assert_eq!(stats.total_strings, 1); assert_eq!(stats.total_arrays, 1);
1133 }
1134
1135 #[test]
1136 fn test_data_store_clear() {
1137 let mut store = DataStore::new();
1138
1139 store.store_value(LiteralValue::Number(42.0));
1140 store.store_value(LiteralValue::Text("Hello".to_string()));
1141
1142 let stats = store.memory_usage();
1143 assert!(stats.total_scalars > 0);
1144 assert!(stats.total_strings > 0);
1145
1146 store.clear();
1147
1148 let stats = store.memory_usage();
1149 assert_eq!(stats.total_scalars, 0);
1150 assert_eq!(stats.total_strings, 0);
1151 }
1152}