formualizer_eval/engine/graph/
sources.rs1use crate::SheetId;
2use crate::engine::graph::DependencyGraph;
3use crate::engine::named_range::NameScope;
4use crate::engine::vertex::{VertexId, VertexKind};
5use formualizer_common::{ExcelError, ExcelErrorKind};
6
7#[derive(Debug, Clone)]
8pub struct SourceScalarEntry {
9 pub name: String,
10 pub vertex: VertexId,
11 pub version: Option<u64>,
12}
13
14#[derive(Debug, Clone)]
15pub struct SourceTableEntry {
16 pub name: String,
17 pub vertex: VertexId,
18 pub version: Option<u64>,
19}
20
21impl DependencyGraph {
22 fn allocate_source_vertex(&mut self) -> VertexId {
23 let scope_sheet_id: SheetId = self.default_sheet_id;
26 self.allocate_symbol_vertex(VertexKind::External, scope_sheet_id)
27 }
28
29 pub fn resolve_source_scalar_entry(&self, name: &str) -> Option<&SourceScalarEntry> {
30 self.source_scalars.get(name)
31 }
32
33 pub fn resolve_source_table_entry(&self, name: &str) -> Option<&SourceTableEntry> {
34 self.source_tables.get(name)
35 }
36
37 pub fn define_source_scalar(
38 &mut self,
39 name: &str,
40 version: Option<u64>,
41 ) -> Result<(), ExcelError> {
42 if name.is_empty() {
43 return Err(ExcelError::new(ExcelErrorKind::Name)
44 .with_message("Source name cannot be empty".to_string()));
45 }
46 if self.source_scalars.contains_key(name) || self.source_tables.contains_key(name) {
47 return Err(ExcelError::new(ExcelErrorKind::Name)
48 .with_message(format!("Source already defined: {name}")));
49 }
50
51 let vertex = self.allocate_source_vertex();
52 self.source_vertex_lookup.insert(vertex, name.to_string());
53 self.mark_volatile(vertex, version.is_none());
54
55 let entry = SourceScalarEntry {
56 name: name.to_string(),
57 vertex,
58 version,
59 };
60 self.source_scalars.insert(name.to_string(), entry);
61 self.resolve_pending_name_references(NameScope::Workbook, name);
62 self.bump_symbol_revision();
63 Ok(())
64 }
65
66 pub fn define_source_table(
67 &mut self,
68 name: &str,
69 version: Option<u64>,
70 ) -> Result<(), ExcelError> {
71 if name.is_empty() {
72 return Err(ExcelError::new(ExcelErrorKind::Name)
73 .with_message("Source name cannot be empty".to_string()));
74 }
75 if self.source_tables.contains_key(name) || self.source_scalars.contains_key(name) {
76 return Err(ExcelError::new(ExcelErrorKind::Name)
77 .with_message(format!("Source already defined: {name}")));
78 }
79
80 let vertex = self.allocate_source_vertex();
81 self.source_vertex_lookup.insert(vertex, name.to_string());
82 self.mark_volatile(vertex, version.is_none());
83
84 let entry = SourceTableEntry {
85 name: name.to_string(),
86 vertex,
87 version,
88 };
89 self.source_tables.insert(name.to_string(), entry);
90 self.bump_symbol_revision();
91 Ok(())
92 }
93
94 pub fn set_source_scalar_version(
95 &mut self,
96 name: &str,
97 version: Option<u64>,
98 ) -> Result<(), ExcelError> {
99 let vertex = {
100 let entry = self.source_scalars.get_mut(name).ok_or_else(|| {
101 ExcelError::new(ExcelErrorKind::Name)
102 .with_message(format!("Unknown source: {name}"))
103 })?;
104
105 if entry.version == version {
106 return Ok(());
107 }
108
109 entry.version = version;
110 entry.vertex
111 };
112
113 self.mark_volatile(vertex, version.is_none());
114 self.mark_dirty(vertex);
115 Ok(())
116 }
117
118 pub fn set_source_table_version(
119 &mut self,
120 name: &str,
121 version: Option<u64>,
122 ) -> Result<(), ExcelError> {
123 let vertex = {
124 let entry = self.source_tables.get_mut(name).ok_or_else(|| {
125 ExcelError::new(ExcelErrorKind::Name)
126 .with_message(format!("Unknown source: {name}"))
127 })?;
128
129 if entry.version == version {
130 return Ok(());
131 }
132
133 entry.version = version;
134 entry.vertex
135 };
136
137 self.mark_volatile(vertex, version.is_none());
138 self.mark_dirty(vertex);
139 Ok(())
140 }
141
142 pub fn invalidate_source(&mut self, name: &str) -> Result<(), ExcelError> {
143 if let Some(s) = self.source_scalars.get(name) {
144 self.mark_dirty(s.vertex);
145 return Ok(());
146 }
147 if let Some(t) = self.source_tables.get(name) {
148 self.mark_dirty(t.vertex);
149 return Ok(());
150 }
151 Err(ExcelError::new(ExcelErrorKind::Name).with_message(format!("Unknown source: {name}")))
152 }
153}