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