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