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(crate) fn compact_asts(
334 &mut self,
335 roots: impl IntoIterator<Item = AstNodeId>,
336 ) -> (Vec<u32>, super::string_interner::StringGarbage) {
337 self.asts.compact(roots)
338 }
339
340 pub(crate) fn ast_node_count(&self) -> usize {
341 self.asts.node_count()
342 }
343
344 pub fn get_node(&self, id: AstNodeId) -> Option<&super::ast::AstNodeData> {
345 self.asts.get(id)
346 }
347
348 pub fn get_args(&self, id: AstNodeId) -> Option<&[AstNodeId]> {
349 self.asts.get_function_args(id)
350 }
351
352 pub fn get_array_elems(&self, id: AstNodeId) -> Option<(u16, u16, &[AstNodeId])> {
353 self.asts.get_array_elements_info(id)
354 }
355
356 pub fn ast_needs_structural_rewrite(&self, id: AstNodeId) -> bool {
357 let mut stack = vec![id];
358 while let Some(node_id) = stack.pop() {
359 let Some(node) = self.get_node(node_id) else {
360 continue;
361 };
362 match node {
363 super::ast::AstNodeData::Reference { ref_type, .. } => {
364 if let CompactRefType::Table { name_id, .. } = ref_type
365 && self.resolve_ast_string(*name_id).is_empty()
366 {
367 return true;
368 }
369 }
370 super::ast::AstNodeData::UnaryOp { expr_id, .. } => stack.push(*expr_id),
371 super::ast::AstNodeData::BinaryOp {
372 left_id, right_id, ..
373 } => {
374 stack.push(*right_id);
375 stack.push(*left_id);
376 }
377 super::ast::AstNodeData::Function { .. } => {
378 if let Some(args) = self.get_args(node_id) {
379 stack.extend(args.iter().rev().copied());
380 }
381 }
382 super::ast::AstNodeData::Array { .. } => {
383 if let Some((_, _, elems)) = self.get_array_elems(node_id) {
384 stack.extend(elems.iter().rev().copied());
385 }
386 }
387 super::ast::AstNodeData::Literal(_) | super::ast::AstNodeData::Omitted => {}
388 }
389 }
390 false
391 }
392
393 fn convert_ast_node(&mut self, node: &ASTNode, sheet_registry: &SheetRegistry) -> AstNodeId {
395 match &node.node_type {
396 ASTNodeType::Literal(lit) => {
397 let value_ref = self.store_value(lit.clone());
398 self.asts.insert_literal(value_ref)
399 }
400
401 ASTNodeType::Omitted => self.asts.insert_omitted(),
402
403 ASTNodeType::Reference {
404 original,
405 reference,
406 } => {
407 let ref_type = self.convert_reference_type(reference, sheet_registry);
408 self.asts.insert_reference(original, ref_type)
409 }
410
411 ASTNodeType::UnaryOp { op, expr } => {
412 let expr_id = self.convert_ast_node(expr, sheet_registry);
413 self.asts.insert_unary_op(op, expr_id)
414 }
415
416 ASTNodeType::BinaryOp { op, left, right } => {
417 let left_id = self.convert_ast_node(left, sheet_registry);
418 let right_id = self.convert_ast_node(right, sheet_registry);
419 self.asts.insert_binary_op(op, left_id, right_id)
420 }
421
422 ASTNodeType::Function { name, args } => {
423 let arg_ids: Vec<AstNodeId> = args
424 .iter()
425 .map(|arg| self.convert_ast_node(arg, sheet_registry))
426 .collect();
427 self.asts.insert_function(name, arg_ids)
428 }
429
430 ASTNodeType::Array(rows) => {
431 let total_elements = rows.iter().map(|r| r.len()).sum();
432 let mut elements = Vec::with_capacity(total_elements);
433
434 let rows_count = rows.len() as u16;
435 let cols_count = rows.first().map(|r| r.len()).unwrap_or(0) as u16;
436
437 for row in rows {
438 for elem in row {
439 elements.push(self.convert_ast_node(elem, sheet_registry));
440 }
441 }
442
443 self.asts.insert_array(rows_count, cols_count, elements)
444 }
445
446 ASTNodeType::Call { callee, args } => {
449 let mut arg_ids = Vec::with_capacity(args.len() + 1);
450 arg_ids.push(self.convert_ast_node(callee, sheet_registry));
451 arg_ids.extend(
452 args.iter()
453 .map(|arg| self.convert_ast_node(arg, sheet_registry)),
454 );
455 self.asts
456 .insert_function(super::ast::CALL_NODE_NAME, arg_ids)
457 }
458 }
459 }
460
461 fn convert_reference_type(
463 &mut self,
464 ref_type: &ReferenceType,
465 sheet_registry: &SheetRegistry,
466 ) -> CompactRefType {
467 match ref_type {
468 ReferenceType::Cell {
469 sheet,
470 row,
471 col,
472 row_abs,
473 col_abs,
474 } => {
475 let sheet = match sheet.as_ref() {
476 Some(s) => match sheet_registry.get_id(s) {
477 Some(id) => Some(SheetKey::Id(id)),
478 None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
479 },
480 None => None,
481 };
482 CompactRefType::Cell {
483 sheet,
484 row: *row,
485 col: *col,
486 row_abs: *row_abs,
487 col_abs: *col_abs,
488 }
489 }
490
491 ReferenceType::Range {
492 sheet,
493 start_row,
494 start_col,
495 end_row,
496 end_col,
497 start_row_abs,
498 start_col_abs,
499 end_row_abs,
500 end_col_abs,
501 } => {
502 let sheet = match sheet.as_ref() {
503 Some(s) => match sheet_registry.get_id(s) {
504 Some(id) => Some(SheetKey::Id(id)),
505 None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
506 },
507 None => None,
508 };
509 CompactRefType::Range {
511 sheet,
512 start_row: start_row.unwrap_or(0),
513 start_col: start_col.unwrap_or(0),
514 end_row: end_row.unwrap_or(u32::MAX),
515 end_col: end_col.unwrap_or(u32::MAX),
516 start_row_abs: *start_row_abs,
517 start_col_abs: *start_col_abs,
518 end_row_abs: *end_row_abs,
519 end_col_abs: *end_col_abs,
520 }
521 }
522
523 ReferenceType::External(ext) => {
524 let raw_id = self.asts.strings_mut().intern(&ext.raw);
525 let book_id = self.asts.strings_mut().intern(ext.book.token());
526 let sheet_id = self.asts.strings_mut().intern(&ext.sheet);
527 CompactRefType::External {
528 raw_id,
529 book_id,
530 sheet_id,
531 kind: ext.kind,
532 }
533 }
534
535 ReferenceType::NamedRange(name) => {
536 let string_id = self.asts.strings_mut().intern(name);
537 CompactRefType::NamedRange(string_id)
538 }
539
540 ReferenceType::Table(table_ref) => {
541 let name_id = self.asts.strings_mut().intern(&table_ref.name);
542 let specifier_id = table_ref
543 .specifier
544 .as_ref()
545 .map(|specifier| self.asts.intern_table_specifier(specifier));
546 CompactRefType::Table {
547 name_id,
548 specifier_id,
549 }
550 }
551
552 ReferenceType::Cell3D {
553 sheet_first,
554 sheet_last,
555 row,
556 col,
557 row_abs,
558 col_abs,
559 } => {
560 let sheet_first = self.asts.strings_mut().intern(sheet_first);
561 let sheet_last = self.asts.strings_mut().intern(sheet_last);
562 CompactRefType::Cell3D {
563 sheet_first,
564 sheet_last,
565 row: *row,
566 col: *col,
567 row_abs: *row_abs,
568 col_abs: *col_abs,
569 }
570 }
571
572 ReferenceType::Range3D {
573 sheet_first,
574 sheet_last,
575 start_row,
576 start_col,
577 end_row,
578 end_col,
579 start_row_abs,
580 start_col_abs,
581 end_row_abs,
582 end_col_abs,
583 } => {
584 let sheet_first = self.asts.strings_mut().intern(sheet_first);
585 let sheet_last = self.asts.strings_mut().intern(sheet_last);
586 CompactRefType::Range3D {
587 sheet_first,
588 sheet_last,
589 start_row: start_row.unwrap_or(0),
590 start_col: start_col.unwrap_or(0),
591 end_row: end_row.unwrap_or(u32::MAX),
592 end_col: end_col.unwrap_or(u32::MAX),
593 start_row_abs: *start_row_abs,
594 start_col_abs: *start_col_abs,
595 end_row_abs: *end_row_abs,
596 end_col_abs: *end_col_abs,
597 }
598 }
599 }
600 }
601
602 pub(crate) fn reconstruct_ast_node(
604 &self,
605 id: AstNodeId,
606 sheet_registry: &SheetRegistry,
607 ) -> Option<ASTNode> {
608 use super::ast::AstNodeData;
609
610 let node_data = self.asts.get(id)?;
611
612 let node_type = match node_data {
613 AstNodeData::Literal(value_ref) => {
614 let lit = self.retrieve_value(*value_ref);
615 ASTNodeType::Literal(lit)
616 }
617
618 AstNodeData::Omitted => ASTNodeType::Omitted,
619
620 AstNodeData::Reference {
621 original_id,
622 ref_type,
623 } => {
624 let original = self.asts.resolve_string(*original_id).to_string();
625 let reference = self.reconstruct_reference_type(ref_type, sheet_registry);
626 ASTNodeType::Reference {
627 original,
628 reference,
629 }
630 }
631
632 AstNodeData::UnaryOp { op_id, expr_id } => {
633 let op = self.asts.resolve_string(*op_id).to_string();
634 let expr = Box::new(self.reconstruct_ast_node(*expr_id, sheet_registry)?);
635 ASTNodeType::UnaryOp { op, expr }
636 }
637
638 AstNodeData::BinaryOp {
639 op_id,
640 left_id,
641 right_id,
642 } => {
643 let op = self.asts.resolve_string(*op_id).to_string();
644 let left = Box::new(self.reconstruct_ast_node(*left_id, sheet_registry)?);
645 let right = Box::new(self.reconstruct_ast_node(*right_id, sheet_registry)?);
646 ASTNodeType::BinaryOp { op, left, right }
647 }
648
649 AstNodeData::Function { name_id, .. } => {
650 let name = self.asts.resolve_string(*name_id).to_string();
651 let arg_ids = self.asts.get_function_args(id)?;
652 let mut args: Vec<ASTNode> = arg_ids
653 .iter()
654 .filter_map(|&arg_id| self.reconstruct_ast_node(arg_id, sheet_registry))
655 .collect();
656 if name == super::ast::CALL_NODE_NAME && !args.is_empty() {
657 let callee = Box::new(args.remove(0));
658 ASTNodeType::Call { callee, args }
659 } else {
660 ASTNodeType::Function { name, args }
661 }
662 }
663
664 AstNodeData::Array { rows, cols, .. } => {
665 let elements = self.asts.get_array_elements(id)?;
666 let mut result = Vec::with_capacity(*rows as usize);
667
668 for r in 0..*rows {
669 let mut row = Vec::with_capacity(*cols as usize);
670 for c in 0..*cols {
671 let idx = (r * *cols + c) as usize;
672 if let Some(&elem_id) = elements.get(idx)
673 && let Some(node) = self.reconstruct_ast_node(elem_id, sheet_registry)
674 {
675 row.push(node);
676 }
677 }
678 result.push(row);
679 }
680
681 ASTNodeType::Array(result)
682 }
683 };
684
685 Some(ASTNode {
686 node_type,
687 source_token: None, contains_volatile: false,
689 })
690 }
691
692 fn reconstruct_reference_type(
694 &self,
695 ref_type: &CompactRefType,
696 sheet_registry: &SheetRegistry,
697 ) -> ReferenceType {
698 match ref_type {
699 CompactRefType::Cell {
700 sheet,
701 row,
702 col,
703 row_abs,
704 col_abs,
705 } => {
706 let sheet = match sheet {
707 Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
708 Some(SheetKey::Name(name_id)) => {
709 Some(self.asts.resolve_string(*name_id).to_string())
710 }
711 None => None,
712 };
713 ReferenceType::Cell {
714 sheet,
715 row: *row,
716 col: *col,
717 row_abs: *row_abs,
718 col_abs: *col_abs,
719 }
720 }
721
722 CompactRefType::Range {
723 sheet,
724 start_row,
725 start_col,
726 end_row,
727 end_col,
728 start_row_abs,
729 start_col_abs,
730 end_row_abs,
731 end_col_abs,
732 } => {
733 let sheet = match sheet {
734 Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
735 Some(SheetKey::Name(name_id)) => {
736 Some(self.asts.resolve_string(*name_id).to_string())
737 }
738 None => None,
739 };
740 ReferenceType::Range {
742 sheet,
743 start_row: if *start_row == 0 {
744 None
745 } else {
746 Some(*start_row)
747 },
748 start_col: if *start_col == 0 {
749 None
750 } else {
751 Some(*start_col)
752 },
753 end_row: if *end_row == u32::MAX {
754 None
755 } else {
756 Some(*end_row)
757 },
758 end_col: if *end_col == u32::MAX {
759 None
760 } else {
761 Some(*end_col)
762 },
763 start_row_abs: *start_row_abs,
764 start_col_abs: *start_col_abs,
765 end_row_abs: *end_row_abs,
766 end_col_abs: *end_col_abs,
767 }
768 }
769
770 CompactRefType::External {
771 raw_id,
772 book_id,
773 sheet_id,
774 kind,
775 } => {
776 let raw = self.asts.resolve_string(*raw_id).to_string();
777 let book = self.asts.resolve_string(*book_id).to_string();
778 let sheet = self.asts.resolve_string(*sheet_id).to_string();
779 ReferenceType::External(ExternalReference {
780 raw,
781 book: ExternalBookRef::Token(book),
782 sheet,
783 kind: *kind,
784 })
785 }
786
787 CompactRefType::NamedRange(string_id) => {
788 let name = self.asts.resolve_string(*string_id).to_string();
789 ReferenceType::NamedRange(name)
790 }
791
792 CompactRefType::Table {
793 name_id,
794 specifier_id,
795 } => {
796 let name = self.asts.resolve_string(*name_id).to_string();
797 let specifier = specifier_id
798 .and_then(|id| self.asts.resolve_table_specifier(id))
799 .cloned();
800 ReferenceType::Table(TableReference { name, specifier })
801 }
802
803 CompactRefType::Cell3D {
804 sheet_first,
805 sheet_last,
806 row,
807 col,
808 row_abs,
809 col_abs,
810 } => ReferenceType::Cell3D {
811 sheet_first: self.asts.resolve_string(*sheet_first).to_string(),
812 sheet_last: self.asts.resolve_string(*sheet_last).to_string(),
813 row: *row,
814 col: *col,
815 row_abs: *row_abs,
816 col_abs: *col_abs,
817 },
818
819 CompactRefType::Range3D {
820 sheet_first,
821 sheet_last,
822 start_row,
823 start_col,
824 end_row,
825 end_col,
826 start_row_abs,
827 start_col_abs,
828 end_row_abs,
829 end_col_abs,
830 } => ReferenceType::Range3D {
831 sheet_first: self.asts.resolve_string(*sheet_first).to_string(),
832 sheet_last: self.asts.resolve_string(*sheet_last).to_string(),
833 start_row: if *start_row == 0 {
834 None
835 } else {
836 Some(*start_row)
837 },
838 start_col: if *start_col == 0 {
839 None
840 } else {
841 Some(*start_col)
842 },
843 end_row: if *end_row == u32::MAX {
844 None
845 } else {
846 Some(*end_row)
847 },
848 end_col: if *end_col == u32::MAX {
849 None
850 } else {
851 Some(*end_col)
852 },
853 start_row_abs: *start_row_abs,
854 start_col_abs: *start_col_abs,
855 end_row_abs: *end_row_abs,
856 end_col_abs: *end_col_abs,
857 },
858 }
859 }
860
861 fn store_error(&mut self, error: &ExcelError) -> ValueRef {
863 let error_ref = self.errors.insert(error);
864 ValueRef::error(error_ref.as_u32())
865 }
866
867 pub fn memory_usage(&self) -> DataStoreStats {
869 DataStoreStats {
870 scalar_bytes: self.scalars.memory_usage(),
871 string_bytes: self.strings.memory_usage(),
872 array_bytes: self.arrays.memory_usage(),
873 ast_bytes: self.asts.memory_usage(),
874 error_bytes: self.errors.memory_usage(),
875 total_scalars: self.scalars.len(),
876 total_strings: self.strings.len(),
877 total_arrays: self.arrays.len(),
878 total_ast_nodes: self.asts.stats().node_count,
879 total_errors: self.errors.len(),
880 }
881 }
882
883 pub fn clear(&mut self) {
885 self.scalars.clear();
886 self.strings.clear();
887 self.arrays.clear();
888 self.asts.clear();
889 self.errors.clear();
890 }
891}
892
893impl Default for DataStore {
894 fn default() -> Self {
895 Self::new()
896 }
897}
898
899#[derive(Debug, Clone)]
901pub struct DataStoreStats {
902 pub scalar_bytes: usize,
903 pub string_bytes: usize,
904 pub array_bytes: usize,
905 pub ast_bytes: usize,
906 pub error_bytes: usize,
907 pub total_scalars: usize,
908 pub total_strings: usize,
909 pub total_arrays: usize,
910 pub total_ast_nodes: usize,
911 pub total_errors: usize,
912}
913
914impl DataStoreStats {
915 pub fn total_bytes(&self) -> usize {
916 self.scalar_bytes + self.string_bytes + self.array_bytes + self.ast_bytes + self.error_bytes
917 }
918}
919
920impl super::array::ArrayRef {
922 pub fn from_raw(raw: u32) -> Self {
923 super::array::ArrayRef(raw)
924 }
925}
926
927impl super::scalar::ScalarRef {
928 pub fn from_raw(raw: u32) -> Self {
929 Self { raw }
930 }
931
932 pub fn as_u32(self) -> u32 {
933 self.raw
934 }
935}
936
937#[cfg(test)]
938mod tests {
939 use super::*;
940
941 #[test]
942 fn test_data_store_empty_value() {
943 let mut store = DataStore::new();
944 let value_ref = store.store_value(LiteralValue::Empty);
945 assert!(value_ref.is_empty());
946
947 let retrieved = store.retrieve_value(value_ref);
948 assert_eq!(retrieved, LiteralValue::Empty);
949 }
950
951 #[test]
952 fn test_data_store_number() {
953 let mut store = DataStore::new();
954 let value_ref = store.store_value(LiteralValue::Number(42.5));
955
956 let retrieved = store.retrieve_value(value_ref);
957 assert_eq!(retrieved, LiteralValue::Number(42.5));
958 }
959
960 #[test]
961 fn test_data_store_datetime_private_encoding_round_trips() {
962 let mut store = DataStore::new();
963 for datetime in [
964 chrono::NaiveDate::from_ymd_opt(2024, 1, 15)
965 .unwrap()
966 .and_hms_opt(12, 30, 0)
967 .unwrap(),
968 chrono::NaiveDate::from_ymd_opt(1899, 12, 30)
969 .unwrap()
970 .and_hms_opt(0, 0, 0)
971 .unwrap(),
972 ] {
973 let value_ref = store.store_value(LiteralValue::DateTime(datetime));
974 assert_eq!(
975 store.retrieve_value(value_ref),
976 LiteralValue::DateTime(datetime)
977 );
978 }
979 }
980
981 #[test]
982 fn test_data_store_text() {
983 let mut store = DataStore::new();
984 let value_ref = store.store_value(LiteralValue::Text("Hello".to_string()));
985
986 let retrieved = store.retrieve_value(value_ref);
987 assert_eq!(retrieved, LiteralValue::Text("Hello".to_string()));
988 }
989
990 #[test]
991 fn test_data_store_boolean() {
992 let mut store = DataStore::new();
993
994 let true_ref = store.store_value(LiteralValue::Boolean(true));
995 let false_ref = store.store_value(LiteralValue::Boolean(false));
996
997 assert_eq!(store.retrieve_value(true_ref), LiteralValue::Boolean(true));
998 assert_eq!(
999 store.retrieve_value(false_ref),
1000 LiteralValue::Boolean(false)
1001 );
1002 }
1003
1004 #[test]
1005 fn test_data_store_error() {
1006 let mut store = DataStore::new();
1007
1008 let error = ExcelError::new(ExcelErrorKind::Div);
1009 let value_ref = store.store_value(LiteralValue::Error(error.clone()));
1010
1011 let retrieved = store.retrieve_value(value_ref);
1012 match retrieved {
1013 LiteralValue::Error(e) => assert_eq!(e.kind, ExcelErrorKind::Div),
1014 _ => panic!("Expected error"),
1015 }
1016 }
1017
1018 #[test]
1019 fn test_data_store_array() {
1020 let mut store = DataStore::new();
1021
1022 let array = vec![
1023 vec![LiteralValue::Number(1.0), LiteralValue::Number(2.0)],
1024 vec![LiteralValue::Number(3.0), LiteralValue::Number(4.0)],
1025 ];
1026
1027 let value_ref = store.store_value(LiteralValue::Array(array.clone()));
1028 let retrieved = store.retrieve_value(value_ref);
1029
1030 assert_eq!(retrieved, LiteralValue::Array(array));
1031 }
1032
1033 #[test]
1034 fn test_data_store_ast_literal() {
1035 let mut store = DataStore::new();
1036 let mut sheet_registry = SheetRegistry::new();
1037 sheet_registry.id_for("Sheet1");
1038
1039 let ast = ASTNode {
1040 node_type: ASTNodeType::Literal(LiteralValue::Number(42.0)),
1041 source_token: None,
1042 contains_volatile: false,
1043 };
1044
1045 let ast_id = store.store_ast(&ast, &sheet_registry);
1046 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
1047
1048 match retrieved.node_type {
1049 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(42.0)),
1050 _ => panic!("Expected literal"),
1051 }
1052 }
1053
1054 #[test]
1055 fn test_data_store_ast_binary_op() {
1056 let mut store = DataStore::new();
1057 let mut sheet_registry = SheetRegistry::new();
1058 sheet_registry.id_for("Sheet1");
1059
1060 let ast = ASTNode {
1061 node_type: ASTNodeType::BinaryOp {
1062 op: "+".to_string(),
1063 left: Box::new(ASTNode {
1064 node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
1065 source_token: None,
1066 contains_volatile: false,
1067 }),
1068 right: Box::new(ASTNode {
1069 node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
1070 source_token: None,
1071 contains_volatile: false,
1072 }),
1073 },
1074 source_token: None,
1075 contains_volatile: false,
1076 };
1077
1078 let ast_id = store.store_ast(&ast, &sheet_registry);
1079 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
1080
1081 match retrieved.node_type {
1082 ASTNodeType::BinaryOp { op, left, right } => {
1083 assert_eq!(op, "+");
1084 match left.node_type {
1085 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(1.0)),
1086 _ => panic!("Expected literal"),
1087 }
1088 match right.node_type {
1089 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(2.0)),
1090 _ => panic!("Expected literal"),
1091 }
1092 }
1093 _ => panic!("Expected binary op"),
1094 }
1095 }
1096
1097 #[test]
1098 fn test_data_store_ast_function() {
1099 let mut store = DataStore::new();
1100 let mut sheet_registry = SheetRegistry::new();
1101 sheet_registry.id_for("Sheet1");
1102
1103 let ast = ASTNode {
1104 node_type: ASTNodeType::Function {
1105 name: "SUM".to_string(),
1106 args: vec![
1107 ASTNode {
1108 node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
1109 source_token: None,
1110 contains_volatile: false,
1111 },
1112 ASTNode {
1113 node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
1114 source_token: None,
1115 contains_volatile: false,
1116 },
1117 ],
1118 },
1119 source_token: None,
1120 contains_volatile: false,
1121 };
1122
1123 let ast_id = store.store_ast(&ast, &sheet_registry);
1124 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
1125
1126 match retrieved.node_type {
1127 ASTNodeType::Function { name, args } => {
1128 assert_eq!(name, "SUM");
1129 assert_eq!(args.len(), 2);
1130 }
1131 _ => panic!("Expected function"),
1132 }
1133 }
1134
1135 #[test]
1136 fn test_data_store_memory_stats() {
1137 let mut store = DataStore::new();
1138
1139 store.store_value(LiteralValue::Number(42.0));
1141 store.store_value(LiteralValue::Text("Hello".to_string()));
1142 store.store_value(LiteralValue::Array(vec![vec![LiteralValue::Number(1.0)]]));
1143
1144 let stats = store.memory_usage();
1145 assert!(stats.total_bytes() > 0);
1146 assert_eq!(stats.total_scalars, 2); assert_eq!(stats.total_strings, 1); assert_eq!(stats.total_arrays, 1);
1149 }
1150
1151 #[test]
1152 fn test_data_store_clear() {
1153 let mut store = DataStore::new();
1154
1155 store.store_value(LiteralValue::Number(42.0));
1156 store.store_value(LiteralValue::Text("Hello".to_string()));
1157
1158 let stats = store.memory_usage();
1159 assert!(stats.total_scalars > 0);
1160 assert!(stats.total_strings > 0);
1161
1162 store.clear();
1163
1164 let stats = store.memory_usage();
1165 assert_eq!(stats.total_scalars, 0);
1166 assert_eq!(stats.total_strings, 0);
1167 }
1168}