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