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