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