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::{ASTNode, ASTNodeType, ReferenceType, TableReference};
12
13#[derive(Debug)]
15pub struct DataStore {
16 scalars: ScalarArena,
18
19 strings: StringInterner,
21
22 arrays: ArrayArena,
24
25 asts: AstArena,
27
28 errors: ErrorArena,
30}
31
32impl DataStore {
33 pub fn new() -> Self {
34 Self {
35 scalars: ScalarArena::new(),
36 strings: StringInterner::new(),
37 arrays: ArrayArena::new(),
38 asts: AstArena::new(),
39 errors: ErrorArena::new(),
40 }
41 }
42
43 pub fn store_values_batch<I>(&mut self, values: I) -> Vec<ValueRef>
45 where
46 I: IntoIterator<Item = LiteralValue>,
47 {
48 let iter = values.into_iter();
49 let (lower, _) = iter.size_hint();
50 let mut out = Vec::with_capacity(lower);
51 for v in iter {
52 out.push(self.store_value(v));
53 }
54 out
55 }
56
57 pub fn store_asts_batch<'a, I>(
59 &mut self,
60 asts: I,
61 sheet_registry: &SheetRegistry,
62 ) -> Vec<AstNodeId>
63 where
64 I: IntoIterator<Item = &'a ASTNode>,
65 {
66 let iter = asts.into_iter();
67 let (lower, _) = iter.size_hint();
68 let mut out = Vec::with_capacity(lower);
69 for ast in iter {
70 out.push(self.store_ast(ast, sheet_registry));
71 }
72 out
73 }
74
75 pub fn with_capacity(estimated_cells: usize) -> Self {
76 Self {
77 scalars: ScalarArena::with_capacity(estimated_cells),
78 strings: StringInterner::with_capacity(estimated_cells / 10),
79 arrays: ArrayArena::with_capacity(estimated_cells / 100),
80 asts: AstArena::with_capacity(estimated_cells / 2),
81 errors: ErrorArena::with_capacity(estimated_cells / 20),
82 }
83 }
84
85 pub fn store_value(&mut self, value: LiteralValue) -> ValueRef {
87 match value {
88 LiteralValue::Empty => ValueRef::empty(),
89
90 LiteralValue::Number(n) => {
91 let idx = self.scalars.insert_float(n);
93 ValueRef::number(idx.as_u32())
94 }
95
96 LiteralValue::Text(s) => {
97 let id = self.strings.intern(&s);
98 ValueRef::string(id.as_u32())
99 }
100
101 LiteralValue::Boolean(b) => ValueRef::boolean(b),
102
103 LiteralValue::Error(err) => self.store_error(&err),
104
105 LiteralValue::Array(array) => {
106 let rows = array.len() as u32;
108 let cols = array.first().map(|r| r.len()).unwrap_or(0) as u32;
109
110 let elements: Vec<ValueRef> = array
111 .into_iter()
112 .flatten()
113 .map(|v| self.store_value(v))
114 .collect();
115
116 let array_ref = self.arrays.insert(rows, cols, elements);
117 ValueRef::array(array_ref.as_u32())
118 }
119
120 LiteralValue::DateTime(dt) => {
121 let serial = formualizer_common::datetime_to_serial(&dt);
123 let idx = self.scalars.insert_float(serial);
124 ValueRef::date_time(idx.as_u32())
125 }
126
127 LiteralValue::Date(d) => {
128 let dt = d.and_hms_opt(0, 0, 0).unwrap();
130 let serial = formualizer_common::datetime_to_serial(&dt);
131 let idx = self.scalars.insert_float(serial);
132 ValueRef::date_time(idx.as_u32())
133 }
134
135 LiteralValue::Time(t) => {
136 use chrono::Timelike;
138 let seconds = (t.hour() * 3600 + t.minute() * 60 + t.second()) as f64;
139 let fraction = seconds / 86400.0;
140 let idx = self.scalars.insert_float(fraction);
141 ValueRef::date_time(idx.as_u32())
142 }
143
144 LiteralValue::Duration(dur) => {
145 let secs = dur.num_seconds();
147 let idx = self.scalars.insert_integer(secs);
148 ValueRef::duration(idx.as_u32())
149 }
150
151 LiteralValue::Int(i) => {
152 if let Some(vref) = ValueRef::small_int(i as i32) {
154 vref
155 } else {
156 let idx = self.scalars.insert_integer(i);
158 ValueRef::large_int(idx.as_u32())
159 }
160 }
161
162 LiteralValue::Pending => ValueRef::pending(),
163 }
164 }
165
166 pub fn retrieve_value(&self, value_ref: ValueRef) -> LiteralValue {
168 use super::value_ref::ValueType;
169
170 match value_ref.value_type() {
171 ValueType::Empty => LiteralValue::Empty,
172
173 ValueType::SmallInt => {
174 if let Some(i) = value_ref.as_small_int() {
176 LiteralValue::Int(i as i64)
177 } else {
178 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
179 }
180 }
181
182 ValueType::LargeInt => {
183 if let Some(idx) = value_ref.arena_index() {
184 let scalar_ref = super::scalar::ScalarRef::from_raw(idx | (1 << 31));
185 if let Some(i) = self.scalars.get_integer(scalar_ref) {
186 LiteralValue::Int(i)
187 } else {
188 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
189 }
190 } else {
191 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
192 }
193 }
194
195 ValueType::Number => {
196 if let Some(idx) = value_ref.arena_index() {
197 let scalar_ref = super::scalar::ScalarRef::from_raw(idx);
198 if let Some(f) = self.scalars.get_float(scalar_ref) {
199 LiteralValue::Number(f)
200 } else {
201 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
202 }
203 } else {
204 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
205 }
206 }
207
208 ValueType::String => {
209 if let Some(idx) = value_ref.arena_index() {
210 let string_id = StringId::from_raw(idx);
211 let s = self.strings.resolve(string_id);
212 LiteralValue::Text(s.to_string())
213 } else {
214 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
215 }
216 }
217
218 ValueType::Boolean => {
219 if let Some(b) = value_ref.as_boolean() {
220 LiteralValue::Boolean(b)
221 } else {
222 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
223 }
224 }
225
226 ValueType::Error => {
227 if let Some(error_ref_raw) = value_ref.as_error_ref() {
228 let error_ref = ErrorRef::from_raw(error_ref_raw);
229 if let Some(error) = self.errors.get(error_ref) {
230 LiteralValue::Error(error)
231 } else {
232 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
233 }
234 } else {
235 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
236 }
237 }
238
239 ValueType::Array => {
240 if let Some(idx) = value_ref.arena_index() {
241 let array_ref = super::array::ArrayRef::from_raw(idx);
242 if let Some(array_2d) = self.arrays.get_2d(array_ref) {
243 let result: Vec<Vec<LiteralValue>> = array_2d
245 .into_iter()
246 .map(|row| row.into_iter().map(|v| self.retrieve_value(v)).collect())
247 .collect();
248 LiteralValue::Array(result)
249 } else {
250 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
251 }
252 } else {
253 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
254 }
255 }
256
257 ValueType::DateTime => {
258 if let Some(idx) = value_ref.arena_index() {
259 let scalar_ref = super::scalar::ScalarRef::from_raw(idx);
260 if let Some(serial) = self.scalars.get_float(scalar_ref) {
261 let dt = formualizer_common::serial_to_datetime(serial);
262 LiteralValue::DateTime(dt)
263 } else {
264 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
265 }
266 } else {
267 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
268 }
269 }
270
271 ValueType::Duration => {
272 if let Some(idx) = value_ref.arena_index() {
273 let scalar_ref = super::scalar::ScalarRef::from_raw(idx | (1 << 31));
274 if let Some(secs) = self.scalars.get_integer(scalar_ref) {
275 let dur = chrono::Duration::seconds(secs);
276 LiteralValue::Duration(dur)
277 } else {
278 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
279 }
280 } else {
281 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
282 }
283 }
284
285 ValueType::Pending => LiteralValue::Pending,
286
287 ValueType::FormulaAst => {
288 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
290 }
291 }
292 }
293
294 pub fn store_ast(&mut self, ast: &ASTNode, sheet_registry: &SheetRegistry) -> AstNodeId {
296 self.convert_ast_node(ast, sheet_registry)
297 }
298
299 pub fn retrieve_ast(&self, id: AstNodeId, sheet_registry: &SheetRegistry) -> Option<ASTNode> {
301 self.reconstruct_ast_node(id, sheet_registry)
302 }
303
304 fn convert_ast_node(&mut self, node: &ASTNode, sheet_registry: &SheetRegistry) -> AstNodeId {
306 match &node.node_type {
307 ASTNodeType::Literal(lit) => {
308 let value_ref = self.store_value(lit.clone());
309 self.asts.insert_literal(value_ref)
310 }
311
312 ASTNodeType::Reference {
313 original,
314 reference,
315 } => {
316 let ref_type = self.convert_reference_type(reference, sheet_registry);
317 self.asts.insert_reference(original, ref_type)
318 }
319
320 ASTNodeType::UnaryOp { op, expr } => {
321 let expr_id = self.convert_ast_node(expr, sheet_registry);
322 self.asts.insert_unary_op(op, expr_id)
323 }
324
325 ASTNodeType::BinaryOp { op, left, right } => {
326 let left_id = self.convert_ast_node(left, sheet_registry);
327 let right_id = self.convert_ast_node(right, sheet_registry);
328 self.asts.insert_binary_op(op, left_id, right_id)
329 }
330
331 ASTNodeType::Function { name, args } => {
332 let arg_ids: Vec<AstNodeId> = args
333 .iter()
334 .map(|arg| self.convert_ast_node(arg, sheet_registry))
335 .collect();
336 self.asts.insert_function(name, arg_ids)
337 }
338
339 ASTNodeType::Array(rows) => {
340 let total_elements = rows.iter().map(|r| r.len()).sum();
341 let mut elements = Vec::with_capacity(total_elements);
342
343 let rows_count = rows.len() as u16;
344 let cols_count = rows.first().map(|r| r.len()).unwrap_or(0) as u16;
345
346 for row in rows {
347 for elem in row {
348 elements.push(self.convert_ast_node(elem, sheet_registry));
349 }
350 }
351
352 self.asts.insert_array(rows_count, cols_count, elements)
353 }
354 }
355 }
356
357 fn convert_reference_type(
359 &mut self,
360 ref_type: &ReferenceType,
361 sheet_registry: &SheetRegistry,
362 ) -> CompactRefType {
363 match ref_type {
364 ReferenceType::Cell { sheet, row, col } => {
365 let sheet = match sheet.as_ref() {
366 Some(s) => match sheet_registry.get_id(s) {
367 Some(id) => Some(SheetKey::Id(id)),
368 None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
369 },
370 None => None,
371 };
372 CompactRefType::Cell {
373 sheet,
374 row: *row,
375 col: *col,
376 }
377 }
378
379 ReferenceType::Range {
380 sheet,
381 start_row,
382 start_col,
383 end_row,
384 end_col,
385 } => {
386 let sheet = match sheet.as_ref() {
387 Some(s) => match sheet_registry.get_id(s) {
388 Some(id) => Some(SheetKey::Id(id)),
389 None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
390 },
391 None => None,
392 };
393 CompactRefType::Range {
395 sheet,
396 start_row: start_row.unwrap_or(0),
397 start_col: start_col.unwrap_or(0),
398 end_row: end_row.unwrap_or(u32::MAX),
399 end_col: end_col.unwrap_or(u32::MAX),
400 }
401 }
402
403 ReferenceType::NamedRange(name) => {
404 let string_id = self.asts.strings_mut().intern(name);
405 CompactRefType::NamedRange(string_id)
406 }
407
408 ReferenceType::Table(table_ref) => {
409 let string_id = self.asts.strings_mut().intern(&table_ref.name);
411 CompactRefType::Table(string_id)
412 }
413 }
414 }
415
416 fn reconstruct_ast_node(
418 &self,
419 id: AstNodeId,
420 sheet_registry: &SheetRegistry,
421 ) -> Option<ASTNode> {
422 use super::ast::AstNodeData;
423
424 let node_data = self.asts.get(id)?;
425
426 let node_type = match node_data {
427 AstNodeData::Literal(value_ref) => {
428 let lit = self.retrieve_value(*value_ref);
429 ASTNodeType::Literal(lit)
430 }
431
432 AstNodeData::Reference {
433 original_id,
434 ref_type,
435 } => {
436 let original = self.asts.resolve_string(*original_id).to_string();
437 let reference = match ref_type {
440 super::ast::CompactRefType::Table(_) => {
441 formualizer_parse::parser::ReferenceType::from_string(&original)
442 .unwrap_or_else(|_| {
443 self.reconstruct_reference_type(ref_type, sheet_registry)
445 })
446 }
447 _ => self.reconstruct_reference_type(ref_type, sheet_registry),
448 };
449 ASTNodeType::Reference {
450 original,
451 reference,
452 }
453 }
454
455 AstNodeData::UnaryOp { op_id, expr_id } => {
456 let op = self.asts.resolve_string(*op_id).to_string();
457 let expr = Box::new(self.reconstruct_ast_node(*expr_id, sheet_registry)?);
458 ASTNodeType::UnaryOp { op, expr }
459 }
460
461 AstNodeData::BinaryOp {
462 op_id,
463 left_id,
464 right_id,
465 } => {
466 let op = self.asts.resolve_string(*op_id).to_string();
467 let left = Box::new(self.reconstruct_ast_node(*left_id, sheet_registry)?);
468 let right = Box::new(self.reconstruct_ast_node(*right_id, sheet_registry)?);
469 ASTNodeType::BinaryOp { op, left, right }
470 }
471
472 AstNodeData::Function { name_id, .. } => {
473 let name = self.asts.resolve_string(*name_id).to_string();
474 let arg_ids = self.asts.get_function_args(id)?;
475 let args: Vec<ASTNode> = arg_ids
476 .iter()
477 .filter_map(|&arg_id| self.reconstruct_ast_node(arg_id, sheet_registry))
478 .collect();
479 ASTNodeType::Function { name, args }
480 }
481
482 AstNodeData::Array { rows, cols, .. } => {
483 let elements = self.asts.get_array_elements(id)?;
484 let mut result = Vec::with_capacity(*rows as usize);
485
486 for r in 0..*rows {
487 let mut row = Vec::with_capacity(*cols as usize);
488 for c in 0..*cols {
489 let idx = (r * *cols + c) as usize;
490 if let Some(&elem_id) = elements.get(idx) {
491 if let Some(node) = self.reconstruct_ast_node(elem_id, sheet_registry) {
492 row.push(node);
493 }
494 }
495 }
496 result.push(row);
497 }
498
499 ASTNodeType::Array(result)
500 }
501 };
502
503 Some(ASTNode {
504 node_type,
505 source_token: None, contains_volatile: false,
507 })
508 }
509
510 fn reconstruct_reference_type(
512 &self,
513 ref_type: &CompactRefType,
514 sheet_registry: &SheetRegistry,
515 ) -> ReferenceType {
516 match ref_type {
517 CompactRefType::Cell { sheet, row, col } => {
518 let sheet = match sheet {
519 Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
520 Some(SheetKey::Name(name_id)) => {
521 Some(self.asts.resolve_string(*name_id).to_string())
522 }
523 None => None,
524 };
525 ReferenceType::Cell {
526 sheet,
527 row: *row,
528 col: *col,
529 }
530 }
531
532 CompactRefType::Range {
533 sheet,
534 start_row,
535 start_col,
536 end_row,
537 end_col,
538 } => {
539 let sheet = match sheet {
540 Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
541 Some(SheetKey::Name(name_id)) => {
542 Some(self.asts.resolve_string(*name_id).to_string())
543 }
544 None => None,
545 };
546 ReferenceType::Range {
548 sheet,
549 start_row: if *start_row == 0 {
550 None
551 } else {
552 Some(*start_row)
553 },
554 start_col: if *start_col == 0 {
555 None
556 } else {
557 Some(*start_col)
558 },
559 end_row: if *end_row == u32::MAX {
560 None
561 } else {
562 Some(*end_row)
563 },
564 end_col: if *end_col == u32::MAX {
565 None
566 } else {
567 Some(*end_col)
568 },
569 }
570 }
571
572 CompactRefType::NamedRange(string_id) => {
573 let name = self.asts.resolve_string(*string_id).to_string();
574 ReferenceType::NamedRange(name)
575 }
576
577 CompactRefType::Table(string_id) => {
578 let name = self.asts.resolve_string(*string_id).to_string();
579 ReferenceType::Table(TableReference {
580 name,
581 specifier: None, })
583 }
584 }
585 }
586
587 fn store_error(&mut self, error: &ExcelError) -> ValueRef {
589 let error_ref = self.errors.insert(error);
590 ValueRef::error(error_ref.as_u32())
591 }
592
593 pub fn memory_usage(&self) -> DataStoreStats {
595 DataStoreStats {
596 scalar_bytes: self.scalars.memory_usage(),
597 string_bytes: self.strings.memory_usage(),
598 array_bytes: self.arrays.memory_usage(),
599 ast_bytes: self.asts.memory_usage(),
600 error_bytes: self.errors.memory_usage(),
601 total_scalars: self.scalars.len(),
602 total_strings: self.strings.len(),
603 total_arrays: self.arrays.len(),
604 total_ast_nodes: self.asts.stats().node_count,
605 total_errors: self.errors.len(),
606 }
607 }
608
609 pub fn clear(&mut self) {
611 self.scalars.clear();
612 self.strings.clear();
613 self.arrays.clear();
614 self.asts.clear();
615 self.errors.clear();
616 }
617}
618
619impl Default for DataStore {
620 fn default() -> Self {
621 Self::new()
622 }
623}
624
625#[derive(Debug, Clone)]
627pub struct DataStoreStats {
628 pub scalar_bytes: usize,
629 pub string_bytes: usize,
630 pub array_bytes: usize,
631 pub ast_bytes: usize,
632 pub error_bytes: usize,
633 pub total_scalars: usize,
634 pub total_strings: usize,
635 pub total_arrays: usize,
636 pub total_ast_nodes: usize,
637 pub total_errors: usize,
638}
639
640impl DataStoreStats {
641 pub fn total_bytes(&self) -> usize {
642 self.scalar_bytes + self.string_bytes + self.array_bytes + self.ast_bytes + self.error_bytes
643 }
644}
645
646impl super::array::ArrayRef {
648 pub fn from_raw(raw: u32) -> Self {
649 super::array::ArrayRef(raw)
650 }
651}
652
653impl super::scalar::ScalarRef {
654 pub fn from_raw(raw: u32) -> Self {
655 Self { raw }
656 }
657
658 pub fn as_u32(self) -> u32 {
659 self.raw
660 }
661}
662
663#[cfg(test)]
664mod tests {
665 use super::*;
666
667 #[test]
668 fn test_data_store_empty_value() {
669 let mut store = DataStore::new();
670 let value_ref = store.store_value(LiteralValue::Empty);
671 assert!(value_ref.is_empty());
672
673 let retrieved = store.retrieve_value(value_ref);
674 assert_eq!(retrieved, LiteralValue::Empty);
675 }
676
677 #[test]
678 fn test_data_store_number() {
679 let mut store = DataStore::new();
680 let value_ref = store.store_value(LiteralValue::Number(42.5));
681
682 let retrieved = store.retrieve_value(value_ref);
683 assert_eq!(retrieved, LiteralValue::Number(42.5));
684 }
685
686 #[test]
687 fn test_data_store_text() {
688 let mut store = DataStore::new();
689 let value_ref = store.store_value(LiteralValue::Text("Hello".to_string()));
690
691 let retrieved = store.retrieve_value(value_ref);
692 assert_eq!(retrieved, LiteralValue::Text("Hello".to_string()));
693 }
694
695 #[test]
696 fn test_data_store_boolean() {
697 let mut store = DataStore::new();
698
699 let true_ref = store.store_value(LiteralValue::Boolean(true));
700 let false_ref = store.store_value(LiteralValue::Boolean(false));
701
702 assert_eq!(store.retrieve_value(true_ref), LiteralValue::Boolean(true));
703 assert_eq!(
704 store.retrieve_value(false_ref),
705 LiteralValue::Boolean(false)
706 );
707 }
708
709 #[test]
710 fn test_data_store_error() {
711 let mut store = DataStore::new();
712
713 let error = ExcelError::new(ExcelErrorKind::Div);
714 let value_ref = store.store_value(LiteralValue::Error(error.clone()));
715
716 let retrieved = store.retrieve_value(value_ref);
717 match retrieved {
718 LiteralValue::Error(e) => assert_eq!(e.kind, ExcelErrorKind::Div),
719 _ => panic!("Expected error"),
720 }
721 }
722
723 #[test]
724 fn test_data_store_array() {
725 let mut store = DataStore::new();
726
727 let array = vec![
728 vec![LiteralValue::Number(1.0), LiteralValue::Number(2.0)],
729 vec![LiteralValue::Number(3.0), LiteralValue::Number(4.0)],
730 ];
731
732 let value_ref = store.store_value(LiteralValue::Array(array.clone()));
733 let retrieved = store.retrieve_value(value_ref);
734
735 assert_eq!(retrieved, LiteralValue::Array(array));
736 }
737
738 #[test]
739 fn test_data_store_ast_literal() {
740 let mut store = DataStore::new();
741 let mut sheet_registry = SheetRegistry::new();
742 sheet_registry.id_for("Sheet1");
743
744 let ast = ASTNode {
745 node_type: ASTNodeType::Literal(LiteralValue::Number(42.0)),
746 source_token: None,
747 contains_volatile: false,
748 };
749
750 let ast_id = store.store_ast(&ast, &sheet_registry);
751 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
752
753 match retrieved.node_type {
754 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(42.0)),
755 _ => panic!("Expected literal"),
756 }
757 }
758
759 #[test]
760 fn test_data_store_ast_binary_op() {
761 let mut store = DataStore::new();
762 let mut sheet_registry = SheetRegistry::new();
763 sheet_registry.id_for("Sheet1");
764
765 let ast = ASTNode {
766 node_type: ASTNodeType::BinaryOp {
767 op: "+".to_string(),
768 left: Box::new(ASTNode {
769 node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
770 source_token: None,
771 contains_volatile: false,
772 }),
773 right: Box::new(ASTNode {
774 node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
775 source_token: None,
776 contains_volatile: false,
777 }),
778 },
779 source_token: None,
780 contains_volatile: false,
781 };
782
783 let ast_id = store.store_ast(&ast, &sheet_registry);
784 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
785
786 match retrieved.node_type {
787 ASTNodeType::BinaryOp { op, left, right } => {
788 assert_eq!(op, "+");
789 match left.node_type {
790 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(1.0)),
791 _ => panic!("Expected literal"),
792 }
793 match right.node_type {
794 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(2.0)),
795 _ => panic!("Expected literal"),
796 }
797 }
798 _ => panic!("Expected binary op"),
799 }
800 }
801
802 #[test]
803 fn test_data_store_ast_function() {
804 let mut store = DataStore::new();
805 let mut sheet_registry = SheetRegistry::new();
806 sheet_registry.id_for("Sheet1");
807
808 let ast = ASTNode {
809 node_type: ASTNodeType::Function {
810 name: "SUM".to_string(),
811 args: vec![
812 ASTNode {
813 node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
814 source_token: None,
815 contains_volatile: false,
816 },
817 ASTNode {
818 node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
819 source_token: None,
820 contains_volatile: false,
821 },
822 ],
823 },
824 source_token: None,
825 contains_volatile: false,
826 };
827
828 let ast_id = store.store_ast(&ast, &sheet_registry);
829 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
830
831 match retrieved.node_type {
832 ASTNodeType::Function { name, args } => {
833 assert_eq!(name, "SUM");
834 assert_eq!(args.len(), 2);
835 }
836 _ => panic!("Expected function"),
837 }
838 }
839
840 #[test]
841 fn test_data_store_memory_stats() {
842 let mut store = DataStore::new();
843
844 store.store_value(LiteralValue::Number(42.0));
846 store.store_value(LiteralValue::Text("Hello".to_string()));
847 store.store_value(LiteralValue::Array(vec![vec![LiteralValue::Number(1.0)]]));
848
849 let stats = store.memory_usage();
850 assert!(stats.total_bytes() > 0);
851 assert_eq!(stats.total_scalars, 2); assert_eq!(stats.total_strings, 1); assert_eq!(stats.total_arrays, 1);
854 }
855
856 #[test]
857 fn test_data_store_clear() {
858 let mut store = DataStore::new();
859
860 store.store_value(LiteralValue::Number(42.0));
861 store.store_value(LiteralValue::Text("Hello".to_string()));
862
863 let stats = store.memory_usage();
864 assert!(stats.total_scalars > 0);
865 assert!(stats.total_strings > 0);
866
867 store.clear();
868
869 let stats = store.memory_usage();
870 assert_eq!(stats.total_scalars, 0);
871 assert_eq!(stats.total_strings, 0);
872 }
873}