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 }
383
384 fn convert_reference_type(
386 &mut self,
387 ref_type: &ReferenceType,
388 sheet_registry: &SheetRegistry,
389 ) -> CompactRefType {
390 match ref_type {
391 ReferenceType::Cell {
392 sheet,
393 row,
394 col,
395 row_abs,
396 col_abs,
397 } => {
398 let sheet = match sheet.as_ref() {
399 Some(s) => match sheet_registry.get_id(s) {
400 Some(id) => Some(SheetKey::Id(id)),
401 None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
402 },
403 None => None,
404 };
405 CompactRefType::Cell {
406 sheet,
407 row: *row,
408 col: *col,
409 row_abs: *row_abs,
410 col_abs: *col_abs,
411 }
412 }
413
414 ReferenceType::Range {
415 sheet,
416 start_row,
417 start_col,
418 end_row,
419 end_col,
420 start_row_abs,
421 start_col_abs,
422 end_row_abs,
423 end_col_abs,
424 } => {
425 let sheet = match sheet.as_ref() {
426 Some(s) => match sheet_registry.get_id(s) {
427 Some(id) => Some(SheetKey::Id(id)),
428 None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
429 },
430 None => None,
431 };
432 CompactRefType::Range {
434 sheet,
435 start_row: start_row.unwrap_or(0),
436 start_col: start_col.unwrap_or(0),
437 end_row: end_row.unwrap_or(u32::MAX),
438 end_col: end_col.unwrap_or(u32::MAX),
439 start_row_abs: *start_row_abs,
440 start_col_abs: *start_col_abs,
441 end_row_abs: *end_row_abs,
442 end_col_abs: *end_col_abs,
443 }
444 }
445
446 ReferenceType::External(ext) => {
447 let raw_id = self.asts.strings_mut().intern(&ext.raw);
448 let book_id = self.asts.strings_mut().intern(ext.book.token());
449 let sheet_id = self.asts.strings_mut().intern(&ext.sheet);
450 CompactRefType::External {
451 raw_id,
452 book_id,
453 sheet_id,
454 kind: ext.kind,
455 }
456 }
457
458 ReferenceType::NamedRange(name) => {
459 let string_id = self.asts.strings_mut().intern(name);
460 CompactRefType::NamedRange(string_id)
461 }
462
463 ReferenceType::Table(table_ref) => {
464 let name_id = self.asts.strings_mut().intern(&table_ref.name);
465 let specifier_id = table_ref
466 .specifier
467 .as_ref()
468 .map(|specifier| self.asts.intern_table_specifier(specifier));
469 CompactRefType::Table {
470 name_id,
471 specifier_id,
472 }
473 }
474 }
475 }
476
477 fn reconstruct_ast_node(
479 &self,
480 id: AstNodeId,
481 sheet_registry: &SheetRegistry,
482 ) -> Option<ASTNode> {
483 use super::ast::AstNodeData;
484
485 let node_data = self.asts.get(id)?;
486
487 let node_type = match node_data {
488 AstNodeData::Literal(value_ref) => {
489 let lit = self.retrieve_value(*value_ref);
490 ASTNodeType::Literal(lit)
491 }
492
493 AstNodeData::Reference {
494 original_id,
495 ref_type,
496 } => {
497 let original = self.asts.resolve_string(*original_id).to_string();
498 let reference = self.reconstruct_reference_type(ref_type, sheet_registry);
499 ASTNodeType::Reference {
500 original,
501 reference,
502 }
503 }
504
505 AstNodeData::UnaryOp { op_id, expr_id } => {
506 let op = self.asts.resolve_string(*op_id).to_string();
507 let expr = Box::new(self.reconstruct_ast_node(*expr_id, sheet_registry)?);
508 ASTNodeType::UnaryOp { op, expr }
509 }
510
511 AstNodeData::BinaryOp {
512 op_id,
513 left_id,
514 right_id,
515 } => {
516 let op = self.asts.resolve_string(*op_id).to_string();
517 let left = Box::new(self.reconstruct_ast_node(*left_id, sheet_registry)?);
518 let right = Box::new(self.reconstruct_ast_node(*right_id, sheet_registry)?);
519 ASTNodeType::BinaryOp { op, left, right }
520 }
521
522 AstNodeData::Function { name_id, .. } => {
523 let name = self.asts.resolve_string(*name_id).to_string();
524 let arg_ids = self.asts.get_function_args(id)?;
525 let args: Vec<ASTNode> = arg_ids
526 .iter()
527 .filter_map(|&arg_id| self.reconstruct_ast_node(arg_id, sheet_registry))
528 .collect();
529 ASTNodeType::Function { name, args }
530 }
531
532 AstNodeData::Array { rows, cols, .. } => {
533 let elements = self.asts.get_array_elements(id)?;
534 let mut result = Vec::with_capacity(*rows as usize);
535
536 for r in 0..*rows {
537 let mut row = Vec::with_capacity(*cols as usize);
538 for c in 0..*cols {
539 let idx = (r * *cols + c) as usize;
540 if let Some(&elem_id) = elements.get(idx)
541 && let Some(node) = self.reconstruct_ast_node(elem_id, sheet_registry)
542 {
543 row.push(node);
544 }
545 }
546 result.push(row);
547 }
548
549 ASTNodeType::Array(result)
550 }
551 };
552
553 Some(ASTNode {
554 node_type,
555 source_token: None, contains_volatile: false,
557 })
558 }
559
560 fn reconstruct_reference_type(
562 &self,
563 ref_type: &CompactRefType,
564 sheet_registry: &SheetRegistry,
565 ) -> ReferenceType {
566 match ref_type {
567 CompactRefType::Cell {
568 sheet,
569 row,
570 col,
571 row_abs,
572 col_abs,
573 } => {
574 let sheet = match sheet {
575 Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
576 Some(SheetKey::Name(name_id)) => {
577 Some(self.asts.resolve_string(*name_id).to_string())
578 }
579 None => None,
580 };
581 ReferenceType::Cell {
582 sheet,
583 row: *row,
584 col: *col,
585 row_abs: *row_abs,
586 col_abs: *col_abs,
587 }
588 }
589
590 CompactRefType::Range {
591 sheet,
592 start_row,
593 start_col,
594 end_row,
595 end_col,
596 start_row_abs,
597 start_col_abs,
598 end_row_abs,
599 end_col_abs,
600 } => {
601 let sheet = match sheet {
602 Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
603 Some(SheetKey::Name(name_id)) => {
604 Some(self.asts.resolve_string(*name_id).to_string())
605 }
606 None => None,
607 };
608 ReferenceType::Range {
610 sheet,
611 start_row: if *start_row == 0 {
612 None
613 } else {
614 Some(*start_row)
615 },
616 start_col: if *start_col == 0 {
617 None
618 } else {
619 Some(*start_col)
620 },
621 end_row: if *end_row == u32::MAX {
622 None
623 } else {
624 Some(*end_row)
625 },
626 end_col: if *end_col == u32::MAX {
627 None
628 } else {
629 Some(*end_col)
630 },
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 CompactRefType::External {
639 raw_id,
640 book_id,
641 sheet_id,
642 kind,
643 } => {
644 let raw = self.asts.resolve_string(*raw_id).to_string();
645 let book = self.asts.resolve_string(*book_id).to_string();
646 let sheet = self.asts.resolve_string(*sheet_id).to_string();
647 ReferenceType::External(ExternalReference {
648 raw,
649 book: ExternalBookRef::Token(book),
650 sheet,
651 kind: *kind,
652 })
653 }
654
655 CompactRefType::NamedRange(string_id) => {
656 let name = self.asts.resolve_string(*string_id).to_string();
657 ReferenceType::NamedRange(name)
658 }
659
660 CompactRefType::Table {
661 name_id,
662 specifier_id,
663 } => {
664 let name = self.asts.resolve_string(*name_id).to_string();
665 let specifier = specifier_id
666 .and_then(|id| self.asts.resolve_table_specifier(id))
667 .cloned();
668 ReferenceType::Table(TableReference { name, specifier })
669 }
670 }
671 }
672
673 fn store_error(&mut self, error: &ExcelError) -> ValueRef {
675 let error_ref = self.errors.insert(error);
676 ValueRef::error(error_ref.as_u32())
677 }
678
679 pub fn memory_usage(&self) -> DataStoreStats {
681 DataStoreStats {
682 scalar_bytes: self.scalars.memory_usage(),
683 string_bytes: self.strings.memory_usage(),
684 array_bytes: self.arrays.memory_usage(),
685 ast_bytes: self.asts.memory_usage(),
686 error_bytes: self.errors.memory_usage(),
687 total_scalars: self.scalars.len(),
688 total_strings: self.strings.len(),
689 total_arrays: self.arrays.len(),
690 total_ast_nodes: self.asts.stats().node_count,
691 total_errors: self.errors.len(),
692 }
693 }
694
695 pub fn clear(&mut self) {
697 self.scalars.clear();
698 self.strings.clear();
699 self.arrays.clear();
700 self.asts.clear();
701 self.errors.clear();
702 }
703}
704
705impl Default for DataStore {
706 fn default() -> Self {
707 Self::new()
708 }
709}
710
711#[derive(Debug, Clone)]
713pub struct DataStoreStats {
714 pub scalar_bytes: usize,
715 pub string_bytes: usize,
716 pub array_bytes: usize,
717 pub ast_bytes: usize,
718 pub error_bytes: usize,
719 pub total_scalars: usize,
720 pub total_strings: usize,
721 pub total_arrays: usize,
722 pub total_ast_nodes: usize,
723 pub total_errors: usize,
724}
725
726impl DataStoreStats {
727 pub fn total_bytes(&self) -> usize {
728 self.scalar_bytes + self.string_bytes + self.array_bytes + self.ast_bytes + self.error_bytes
729 }
730}
731
732impl super::array::ArrayRef {
734 pub fn from_raw(raw: u32) -> Self {
735 super::array::ArrayRef(raw)
736 }
737}
738
739impl super::scalar::ScalarRef {
740 pub fn from_raw(raw: u32) -> Self {
741 Self { raw }
742 }
743
744 pub fn as_u32(self) -> u32 {
745 self.raw
746 }
747}
748
749#[cfg(test)]
750mod tests {
751 use super::*;
752
753 #[test]
754 fn test_data_store_empty_value() {
755 let mut store = DataStore::new();
756 let value_ref = store.store_value(LiteralValue::Empty);
757 assert!(value_ref.is_empty());
758
759 let retrieved = store.retrieve_value(value_ref);
760 assert_eq!(retrieved, LiteralValue::Empty);
761 }
762
763 #[test]
764 fn test_data_store_number() {
765 let mut store = DataStore::new();
766 let value_ref = store.store_value(LiteralValue::Number(42.5));
767
768 let retrieved = store.retrieve_value(value_ref);
769 assert_eq!(retrieved, LiteralValue::Number(42.5));
770 }
771
772 #[test]
773 fn test_data_store_text() {
774 let mut store = DataStore::new();
775 let value_ref = store.store_value(LiteralValue::Text("Hello".to_string()));
776
777 let retrieved = store.retrieve_value(value_ref);
778 assert_eq!(retrieved, LiteralValue::Text("Hello".to_string()));
779 }
780
781 #[test]
782 fn test_data_store_boolean() {
783 let mut store = DataStore::new();
784
785 let true_ref = store.store_value(LiteralValue::Boolean(true));
786 let false_ref = store.store_value(LiteralValue::Boolean(false));
787
788 assert_eq!(store.retrieve_value(true_ref), LiteralValue::Boolean(true));
789 assert_eq!(
790 store.retrieve_value(false_ref),
791 LiteralValue::Boolean(false)
792 );
793 }
794
795 #[test]
796 fn test_data_store_error() {
797 let mut store = DataStore::new();
798
799 let error = ExcelError::new(ExcelErrorKind::Div);
800 let value_ref = store.store_value(LiteralValue::Error(error.clone()));
801
802 let retrieved = store.retrieve_value(value_ref);
803 match retrieved {
804 LiteralValue::Error(e) => assert_eq!(e.kind, ExcelErrorKind::Div),
805 _ => panic!("Expected error"),
806 }
807 }
808
809 #[test]
810 fn test_data_store_array() {
811 let mut store = DataStore::new();
812
813 let array = vec![
814 vec![LiteralValue::Number(1.0), LiteralValue::Number(2.0)],
815 vec![LiteralValue::Number(3.0), LiteralValue::Number(4.0)],
816 ];
817
818 let value_ref = store.store_value(LiteralValue::Array(array.clone()));
819 let retrieved = store.retrieve_value(value_ref);
820
821 assert_eq!(retrieved, LiteralValue::Array(array));
822 }
823
824 #[test]
825 fn test_data_store_ast_literal() {
826 let mut store = DataStore::new();
827 let mut sheet_registry = SheetRegistry::new();
828 sheet_registry.id_for("Sheet1");
829
830 let ast = ASTNode {
831 node_type: ASTNodeType::Literal(LiteralValue::Number(42.0)),
832 source_token: None,
833 contains_volatile: false,
834 };
835
836 let ast_id = store.store_ast(&ast, &sheet_registry);
837 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
838
839 match retrieved.node_type {
840 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(42.0)),
841 _ => panic!("Expected literal"),
842 }
843 }
844
845 #[test]
846 fn test_data_store_ast_binary_op() {
847 let mut store = DataStore::new();
848 let mut sheet_registry = SheetRegistry::new();
849 sheet_registry.id_for("Sheet1");
850
851 let ast = ASTNode {
852 node_type: ASTNodeType::BinaryOp {
853 op: "+".to_string(),
854 left: Box::new(ASTNode {
855 node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
856 source_token: None,
857 contains_volatile: false,
858 }),
859 right: Box::new(ASTNode {
860 node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
861 source_token: None,
862 contains_volatile: false,
863 }),
864 },
865 source_token: None,
866 contains_volatile: false,
867 };
868
869 let ast_id = store.store_ast(&ast, &sheet_registry);
870 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
871
872 match retrieved.node_type {
873 ASTNodeType::BinaryOp { op, left, right } => {
874 assert_eq!(op, "+");
875 match left.node_type {
876 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(1.0)),
877 _ => panic!("Expected literal"),
878 }
879 match right.node_type {
880 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(2.0)),
881 _ => panic!("Expected literal"),
882 }
883 }
884 _ => panic!("Expected binary op"),
885 }
886 }
887
888 #[test]
889 fn test_data_store_ast_function() {
890 let mut store = DataStore::new();
891 let mut sheet_registry = SheetRegistry::new();
892 sheet_registry.id_for("Sheet1");
893
894 let ast = ASTNode {
895 node_type: ASTNodeType::Function {
896 name: "SUM".to_string(),
897 args: vec![
898 ASTNode {
899 node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
900 source_token: None,
901 contains_volatile: false,
902 },
903 ASTNode {
904 node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
905 source_token: None,
906 contains_volatile: false,
907 },
908 ],
909 },
910 source_token: None,
911 contains_volatile: false,
912 };
913
914 let ast_id = store.store_ast(&ast, &sheet_registry);
915 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
916
917 match retrieved.node_type {
918 ASTNodeType::Function { name, args } => {
919 assert_eq!(name, "SUM");
920 assert_eq!(args.len(), 2);
921 }
922 _ => panic!("Expected function"),
923 }
924 }
925
926 #[test]
927 fn test_data_store_memory_stats() {
928 let mut store = DataStore::new();
929
930 store.store_value(LiteralValue::Number(42.0));
932 store.store_value(LiteralValue::Text("Hello".to_string()));
933 store.store_value(LiteralValue::Array(vec![vec![LiteralValue::Number(1.0)]]));
934
935 let stats = store.memory_usage();
936 assert!(stats.total_bytes() > 0);
937 assert_eq!(stats.total_scalars, 2); assert_eq!(stats.total_strings, 1); assert_eq!(stats.total_arrays, 1);
940 }
941
942 #[test]
943 fn test_data_store_clear() {
944 let mut store = DataStore::new();
945
946 store.store_value(LiteralValue::Number(42.0));
947 store.store_value(LiteralValue::Text("Hello".to_string()));
948
949 let stats = store.memory_usage();
950 assert!(stats.total_scalars > 0);
951 assert!(stats.total_strings > 0);
952
953 store.clear();
954
955 let stats = store.memory_usage();
956 assert_eq!(stats.total_scalars, 0);
957 assert_eq!(stats.total_strings, 0);
958 }
959}