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 let raw_index = idx.as_u32() & 0x7FFF_FFFF;
149 ValueRef::duration(raw_index)
150 }
151
152 LiteralValue::Int(i) => {
153 if let Some(vref) = ValueRef::small_int(i as i32) {
155 vref
156 } else {
157 let idx = self.scalars.insert_integer(i);
159 ValueRef::large_int(idx.as_u32())
160 }
161 }
162
163 LiteralValue::Pending => ValueRef::pending(),
164 }
165 }
166
167 pub fn retrieve_value(&self, value_ref: ValueRef) -> LiteralValue {
169 use super::value_ref::ValueType;
170
171 match value_ref.value_type() {
172 ValueType::Empty => LiteralValue::Empty,
173
174 ValueType::SmallInt => {
175 if let Some(i) = value_ref.as_small_int() {
177 LiteralValue::Int(i as i64)
178 } else {
179 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
180 }
181 }
182
183 ValueType::LargeInt => {
184 if let Some(idx) = value_ref.arena_index() {
185 let scalar_ref = super::scalar::ScalarRef::from_raw(idx | (1 << 31));
186 if let Some(i) = self.scalars.get_integer(scalar_ref) {
187 LiteralValue::Int(i)
188 } else {
189 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
190 }
191 } else {
192 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
193 }
194 }
195
196 ValueType::Number => {
197 if let Some(idx) = value_ref.arena_index() {
198 let scalar_ref = super::scalar::ScalarRef::from_raw(idx);
199 if let Some(f) = self.scalars.get_float(scalar_ref) {
200 LiteralValue::Number(f)
201 } else {
202 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
203 }
204 } else {
205 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
206 }
207 }
208
209 ValueType::String => {
210 if let Some(idx) = value_ref.arena_index() {
211 let string_id = StringId::from_raw(idx);
212 let s = self.strings.resolve(string_id);
213 LiteralValue::Text(s.to_string())
214 } else {
215 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
216 }
217 }
218
219 ValueType::Boolean => {
220 if let Some(b) = value_ref.as_boolean() {
221 LiteralValue::Boolean(b)
222 } else {
223 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
224 }
225 }
226
227 ValueType::Error => {
228 if let Some(error_ref_raw) = value_ref.as_error_ref() {
229 let error_ref = ErrorRef::from_raw(error_ref_raw);
230 if let Some(error) = self.errors.get(error_ref) {
231 LiteralValue::Error(error)
232 } else {
233 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
234 }
235 } else {
236 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
237 }
238 }
239
240 ValueType::Array => {
241 if let Some(idx) = value_ref.arena_index() {
242 let array_ref = super::array::ArrayRef::from_raw(idx);
243 if let Some(array_2d) = self.arrays.get_2d(array_ref) {
244 let result: Vec<Vec<LiteralValue>> = array_2d
246 .into_iter()
247 .map(|row| row.into_iter().map(|v| self.retrieve_value(v)).collect())
248 .collect();
249 LiteralValue::Array(result)
250 } else {
251 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
252 }
253 } else {
254 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
255 }
256 }
257
258 ValueType::DateTime => {
259 if let Some(idx) = value_ref.arena_index() {
260 let scalar_ref = super::scalar::ScalarRef::from_raw(idx);
261 if let Some(serial) = self.scalars.get_float(scalar_ref) {
262 let dt = formualizer_common::serial_to_datetime(serial);
263 LiteralValue::DateTime(dt)
264 } else {
265 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
266 }
267 } else {
268 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
269 }
270 }
271
272 ValueType::Duration => {
273 if let Some(idx) = value_ref.arena_index() {
274 let scalar_ref = super::scalar::ScalarRef::from_raw(idx | (1 << 31));
275 if let Some(secs) = self.scalars.get_integer(scalar_ref) {
276 let dur = chrono::Duration::seconds(secs);
277 LiteralValue::Duration(dur)
278 } else {
279 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
280 }
281 } else {
282 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
283 }
284 }
285
286 ValueType::Pending => LiteralValue::Pending,
287
288 ValueType::FormulaAst => {
289 LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
291 }
292 }
293 }
294
295 pub fn store_ast(&mut self, ast: &ASTNode, sheet_registry: &SheetRegistry) -> AstNodeId {
297 self.convert_ast_node(ast, sheet_registry)
298 }
299
300 pub fn retrieve_ast(&self, id: AstNodeId, sheet_registry: &SheetRegistry) -> Option<ASTNode> {
302 self.reconstruct_ast_node(id, sheet_registry)
303 }
304
305 pub fn resolve_ast_string(&self, id: StringId) -> &str {
306 self.asts.resolve_string(id)
307 }
308
309 pub fn reconstruct_reference_type_for_eval(
310 &self,
311 ref_type: &CompactRefType,
312 sheet_registry: &SheetRegistry,
313 ) -> ReferenceType {
314 self.reconstruct_reference_type(ref_type, sheet_registry)
315 }
316
317 pub fn get_node(&self, id: AstNodeId) -> Option<&super::ast::AstNodeData> {
318 self.asts.get(id)
319 }
320
321 pub fn get_args(&self, id: AstNodeId) -> Option<&[AstNodeId]> {
322 self.asts.get_function_args(id)
323 }
324
325 pub fn get_array_elems(&self, id: AstNodeId) -> Option<(u16, u16, &[AstNodeId])> {
326 self.asts.get_array_elements_info(id)
327 }
328
329 fn convert_ast_node(&mut self, node: &ASTNode, sheet_registry: &SheetRegistry) -> AstNodeId {
331 match &node.node_type {
332 ASTNodeType::Literal(lit) => {
333 let value_ref = self.store_value(lit.clone());
334 self.asts.insert_literal(value_ref)
335 }
336
337 ASTNodeType::Reference {
338 original,
339 reference,
340 } => {
341 let ref_type = self.convert_reference_type(reference, sheet_registry);
342 self.asts.insert_reference(original, ref_type)
343 }
344
345 ASTNodeType::UnaryOp { op, expr } => {
346 let expr_id = self.convert_ast_node(expr, sheet_registry);
347 self.asts.insert_unary_op(op, expr_id)
348 }
349
350 ASTNodeType::BinaryOp { op, left, right } => {
351 let left_id = self.convert_ast_node(left, sheet_registry);
352 let right_id = self.convert_ast_node(right, sheet_registry);
353 self.asts.insert_binary_op(op, left_id, right_id)
354 }
355
356 ASTNodeType::Function { name, args } => {
357 let arg_ids: Vec<AstNodeId> = args
358 .iter()
359 .map(|arg| self.convert_ast_node(arg, sheet_registry))
360 .collect();
361 self.asts.insert_function(name, arg_ids)
362 }
363
364 ASTNodeType::Array(rows) => {
365 let total_elements = rows.iter().map(|r| r.len()).sum();
366 let mut elements = Vec::with_capacity(total_elements);
367
368 let rows_count = rows.len() as u16;
369 let cols_count = rows.first().map(|r| r.len()).unwrap_or(0) as u16;
370
371 for row in rows {
372 for elem in row {
373 elements.push(self.convert_ast_node(elem, sheet_registry));
374 }
375 }
376
377 self.asts.insert_array(rows_count, cols_count, elements)
378 }
379 }
380 }
381
382 fn convert_reference_type(
384 &mut self,
385 ref_type: &ReferenceType,
386 sheet_registry: &SheetRegistry,
387 ) -> CompactRefType {
388 match ref_type {
389 ReferenceType::Cell { sheet, row, col } => {
390 let sheet = match sheet.as_ref() {
391 Some(s) => match sheet_registry.get_id(s) {
392 Some(id) => Some(SheetKey::Id(id)),
393 None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
394 },
395 None => None,
396 };
397 CompactRefType::Cell {
398 sheet,
399 row: *row,
400 col: *col,
401 }
402 }
403
404 ReferenceType::Range {
405 sheet,
406 start_row,
407 start_col,
408 end_row,
409 end_col,
410 } => {
411 let sheet = match sheet.as_ref() {
412 Some(s) => match sheet_registry.get_id(s) {
413 Some(id) => Some(SheetKey::Id(id)),
414 None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
415 },
416 None => None,
417 };
418 CompactRefType::Range {
420 sheet,
421 start_row: start_row.unwrap_or(0),
422 start_col: start_col.unwrap_or(0),
423 end_row: end_row.unwrap_or(u32::MAX),
424 end_col: end_col.unwrap_or(u32::MAX),
425 }
426 }
427
428 ReferenceType::NamedRange(name) => {
429 let string_id = self.asts.strings_mut().intern(name);
430 CompactRefType::NamedRange(string_id)
431 }
432
433 ReferenceType::Table(table_ref) => {
434 let name_id = self.asts.strings_mut().intern(&table_ref.name);
435 let specifier_id = table_ref
436 .specifier
437 .as_ref()
438 .map(|specifier| self.asts.intern_table_specifier(specifier));
439 CompactRefType::Table {
440 name_id,
441 specifier_id,
442 }
443 }
444 }
445 }
446
447 fn reconstruct_ast_node(
449 &self,
450 id: AstNodeId,
451 sheet_registry: &SheetRegistry,
452 ) -> Option<ASTNode> {
453 use super::ast::AstNodeData;
454
455 let node_data = self.asts.get(id)?;
456
457 let node_type = match node_data {
458 AstNodeData::Literal(value_ref) => {
459 let lit = self.retrieve_value(*value_ref);
460 ASTNodeType::Literal(lit)
461 }
462
463 AstNodeData::Reference {
464 original_id,
465 ref_type,
466 } => {
467 let original = self.asts.resolve_string(*original_id).to_string();
468 let reference = self.reconstruct_reference_type(ref_type, sheet_registry);
469 ASTNodeType::Reference {
470 original,
471 reference,
472 }
473 }
474
475 AstNodeData::UnaryOp { op_id, expr_id } => {
476 let op = self.asts.resolve_string(*op_id).to_string();
477 let expr = Box::new(self.reconstruct_ast_node(*expr_id, sheet_registry)?);
478 ASTNodeType::UnaryOp { op, expr }
479 }
480
481 AstNodeData::BinaryOp {
482 op_id,
483 left_id,
484 right_id,
485 } => {
486 let op = self.asts.resolve_string(*op_id).to_string();
487 let left = Box::new(self.reconstruct_ast_node(*left_id, sheet_registry)?);
488 let right = Box::new(self.reconstruct_ast_node(*right_id, sheet_registry)?);
489 ASTNodeType::BinaryOp { op, left, right }
490 }
491
492 AstNodeData::Function { name_id, .. } => {
493 let name = self.asts.resolve_string(*name_id).to_string();
494 let arg_ids = self.asts.get_function_args(id)?;
495 let args: Vec<ASTNode> = arg_ids
496 .iter()
497 .filter_map(|&arg_id| self.reconstruct_ast_node(arg_id, sheet_registry))
498 .collect();
499 ASTNodeType::Function { name, args }
500 }
501
502 AstNodeData::Array { rows, cols, .. } => {
503 let elements = self.asts.get_array_elements(id)?;
504 let mut result = Vec::with_capacity(*rows as usize);
505
506 for r in 0..*rows {
507 let mut row = Vec::with_capacity(*cols as usize);
508 for c in 0..*cols {
509 let idx = (r * *cols + c) as usize;
510 if let Some(&elem_id) = elements.get(idx)
511 && let Some(node) = self.reconstruct_ast_node(elem_id, sheet_registry)
512 {
513 row.push(node);
514 }
515 }
516 result.push(row);
517 }
518
519 ASTNodeType::Array(result)
520 }
521 };
522
523 Some(ASTNode {
524 node_type,
525 source_token: None, contains_volatile: false,
527 })
528 }
529
530 fn reconstruct_reference_type(
532 &self,
533 ref_type: &CompactRefType,
534 sheet_registry: &SheetRegistry,
535 ) -> ReferenceType {
536 match ref_type {
537 CompactRefType::Cell { sheet, row, col } => {
538 let sheet = match sheet {
539 Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
540 Some(SheetKey::Name(name_id)) => {
541 Some(self.asts.resolve_string(*name_id).to_string())
542 }
543 None => None,
544 };
545 ReferenceType::Cell {
546 sheet,
547 row: *row,
548 col: *col,
549 }
550 }
551
552 CompactRefType::Range {
553 sheet,
554 start_row,
555 start_col,
556 end_row,
557 end_col,
558 } => {
559 let sheet = match sheet {
560 Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
561 Some(SheetKey::Name(name_id)) => {
562 Some(self.asts.resolve_string(*name_id).to_string())
563 }
564 None => None,
565 };
566 ReferenceType::Range {
568 sheet,
569 start_row: if *start_row == 0 {
570 None
571 } else {
572 Some(*start_row)
573 },
574 start_col: if *start_col == 0 {
575 None
576 } else {
577 Some(*start_col)
578 },
579 end_row: if *end_row == u32::MAX {
580 None
581 } else {
582 Some(*end_row)
583 },
584 end_col: if *end_col == u32::MAX {
585 None
586 } else {
587 Some(*end_col)
588 },
589 }
590 }
591
592 CompactRefType::NamedRange(string_id) => {
593 let name = self.asts.resolve_string(*string_id).to_string();
594 ReferenceType::NamedRange(name)
595 }
596
597 CompactRefType::Table {
598 name_id,
599 specifier_id,
600 } => {
601 let name = self.asts.resolve_string(*name_id).to_string();
602 let specifier = specifier_id
603 .and_then(|id| self.asts.resolve_table_specifier(id))
604 .cloned();
605 ReferenceType::Table(TableReference { name, specifier })
606 }
607 }
608 }
609
610 fn store_error(&mut self, error: &ExcelError) -> ValueRef {
612 let error_ref = self.errors.insert(error);
613 ValueRef::error(error_ref.as_u32())
614 }
615
616 pub fn memory_usage(&self) -> DataStoreStats {
618 DataStoreStats {
619 scalar_bytes: self.scalars.memory_usage(),
620 string_bytes: self.strings.memory_usage(),
621 array_bytes: self.arrays.memory_usage(),
622 ast_bytes: self.asts.memory_usage(),
623 error_bytes: self.errors.memory_usage(),
624 total_scalars: self.scalars.len(),
625 total_strings: self.strings.len(),
626 total_arrays: self.arrays.len(),
627 total_ast_nodes: self.asts.stats().node_count,
628 total_errors: self.errors.len(),
629 }
630 }
631
632 pub fn clear(&mut self) {
634 self.scalars.clear();
635 self.strings.clear();
636 self.arrays.clear();
637 self.asts.clear();
638 self.errors.clear();
639 }
640}
641
642impl Default for DataStore {
643 fn default() -> Self {
644 Self::new()
645 }
646}
647
648#[derive(Debug, Clone)]
650pub struct DataStoreStats {
651 pub scalar_bytes: usize,
652 pub string_bytes: usize,
653 pub array_bytes: usize,
654 pub ast_bytes: usize,
655 pub error_bytes: usize,
656 pub total_scalars: usize,
657 pub total_strings: usize,
658 pub total_arrays: usize,
659 pub total_ast_nodes: usize,
660 pub total_errors: usize,
661}
662
663impl DataStoreStats {
664 pub fn total_bytes(&self) -> usize {
665 self.scalar_bytes + self.string_bytes + self.array_bytes + self.ast_bytes + self.error_bytes
666 }
667}
668
669impl super::array::ArrayRef {
671 pub fn from_raw(raw: u32) -> Self {
672 super::array::ArrayRef(raw)
673 }
674}
675
676impl super::scalar::ScalarRef {
677 pub fn from_raw(raw: u32) -> Self {
678 Self { raw }
679 }
680
681 pub fn as_u32(self) -> u32 {
682 self.raw
683 }
684}
685
686#[cfg(test)]
687mod tests {
688 use super::*;
689
690 #[test]
691 fn test_data_store_empty_value() {
692 let mut store = DataStore::new();
693 let value_ref = store.store_value(LiteralValue::Empty);
694 assert!(value_ref.is_empty());
695
696 let retrieved = store.retrieve_value(value_ref);
697 assert_eq!(retrieved, LiteralValue::Empty);
698 }
699
700 #[test]
701 fn test_data_store_number() {
702 let mut store = DataStore::new();
703 let value_ref = store.store_value(LiteralValue::Number(42.5));
704
705 let retrieved = store.retrieve_value(value_ref);
706 assert_eq!(retrieved, LiteralValue::Number(42.5));
707 }
708
709 #[test]
710 fn test_data_store_text() {
711 let mut store = DataStore::new();
712 let value_ref = store.store_value(LiteralValue::Text("Hello".to_string()));
713
714 let retrieved = store.retrieve_value(value_ref);
715 assert_eq!(retrieved, LiteralValue::Text("Hello".to_string()));
716 }
717
718 #[test]
719 fn test_data_store_boolean() {
720 let mut store = DataStore::new();
721
722 let true_ref = store.store_value(LiteralValue::Boolean(true));
723 let false_ref = store.store_value(LiteralValue::Boolean(false));
724
725 assert_eq!(store.retrieve_value(true_ref), LiteralValue::Boolean(true));
726 assert_eq!(
727 store.retrieve_value(false_ref),
728 LiteralValue::Boolean(false)
729 );
730 }
731
732 #[test]
733 fn test_data_store_error() {
734 let mut store = DataStore::new();
735
736 let error = ExcelError::new(ExcelErrorKind::Div);
737 let value_ref = store.store_value(LiteralValue::Error(error.clone()));
738
739 let retrieved = store.retrieve_value(value_ref);
740 match retrieved {
741 LiteralValue::Error(e) => assert_eq!(e.kind, ExcelErrorKind::Div),
742 _ => panic!("Expected error"),
743 }
744 }
745
746 #[test]
747 fn test_data_store_array() {
748 let mut store = DataStore::new();
749
750 let array = vec![
751 vec![LiteralValue::Number(1.0), LiteralValue::Number(2.0)],
752 vec![LiteralValue::Number(3.0), LiteralValue::Number(4.0)],
753 ];
754
755 let value_ref = store.store_value(LiteralValue::Array(array.clone()));
756 let retrieved = store.retrieve_value(value_ref);
757
758 assert_eq!(retrieved, LiteralValue::Array(array));
759 }
760
761 #[test]
762 fn test_data_store_ast_literal() {
763 let mut store = DataStore::new();
764 let mut sheet_registry = SheetRegistry::new();
765 sheet_registry.id_for("Sheet1");
766
767 let ast = ASTNode {
768 node_type: ASTNodeType::Literal(LiteralValue::Number(42.0)),
769 source_token: None,
770 contains_volatile: false,
771 };
772
773 let ast_id = store.store_ast(&ast, &sheet_registry);
774 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
775
776 match retrieved.node_type {
777 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(42.0)),
778 _ => panic!("Expected literal"),
779 }
780 }
781
782 #[test]
783 fn test_data_store_ast_binary_op() {
784 let mut store = DataStore::new();
785 let mut sheet_registry = SheetRegistry::new();
786 sheet_registry.id_for("Sheet1");
787
788 let ast = ASTNode {
789 node_type: ASTNodeType::BinaryOp {
790 op: "+".to_string(),
791 left: Box::new(ASTNode {
792 node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
793 source_token: None,
794 contains_volatile: false,
795 }),
796 right: Box::new(ASTNode {
797 node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
798 source_token: None,
799 contains_volatile: false,
800 }),
801 },
802 source_token: None,
803 contains_volatile: false,
804 };
805
806 let ast_id = store.store_ast(&ast, &sheet_registry);
807 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
808
809 match retrieved.node_type {
810 ASTNodeType::BinaryOp { op, left, right } => {
811 assert_eq!(op, "+");
812 match left.node_type {
813 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(1.0)),
814 _ => panic!("Expected literal"),
815 }
816 match right.node_type {
817 ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(2.0)),
818 _ => panic!("Expected literal"),
819 }
820 }
821 _ => panic!("Expected binary op"),
822 }
823 }
824
825 #[test]
826 fn test_data_store_ast_function() {
827 let mut store = DataStore::new();
828 let mut sheet_registry = SheetRegistry::new();
829 sheet_registry.id_for("Sheet1");
830
831 let ast = ASTNode {
832 node_type: ASTNodeType::Function {
833 name: "SUM".to_string(),
834 args: vec![
835 ASTNode {
836 node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
837 source_token: None,
838 contains_volatile: false,
839 },
840 ASTNode {
841 node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
842 source_token: None,
843 contains_volatile: false,
844 },
845 ],
846 },
847 source_token: None,
848 contains_volatile: false,
849 };
850
851 let ast_id = store.store_ast(&ast, &sheet_registry);
852 let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
853
854 match retrieved.node_type {
855 ASTNodeType::Function { name, args } => {
856 assert_eq!(name, "SUM");
857 assert_eq!(args.len(), 2);
858 }
859 _ => panic!("Expected function"),
860 }
861 }
862
863 #[test]
864 fn test_data_store_memory_stats() {
865 let mut store = DataStore::new();
866
867 store.store_value(LiteralValue::Number(42.0));
869 store.store_value(LiteralValue::Text("Hello".to_string()));
870 store.store_value(LiteralValue::Array(vec![vec![LiteralValue::Number(1.0)]]));
871
872 let stats = store.memory_usage();
873 assert!(stats.total_bytes() > 0);
874 assert_eq!(stats.total_scalars, 2); assert_eq!(stats.total_strings, 1); assert_eq!(stats.total_arrays, 1);
877 }
878
879 #[test]
880 fn test_data_store_clear() {
881 let mut store = DataStore::new();
882
883 store.store_value(LiteralValue::Number(42.0));
884 store.store_value(LiteralValue::Text("Hello".to_string()));
885
886 let stats = store.memory_usage();
887 assert!(stats.total_scalars > 0);
888 assert!(stats.total_strings > 0);
889
890 store.clear();
891
892 let stats = store.memory_usage();
893 assert_eq!(stats.total_scalars, 0);
894 assert_eq!(stats.total_strings, 0);
895 }
896}