rib/registry/
component_dependencies.rs1use crate::{
16 ComponentDependencyKey, Expr, FullyQualifiedInterfaceName, FunctionDictionary, FunctionName,
17 FunctionType, FunctionTypeRegistry, InstanceCreationType, InterfaceName, PackageName,
18 TypeParameter,
19};
20use golem_wasm_ast::analysis::TypeEnum;
21use golem_wasm_ast::analysis::{AnalysedExport, TypeVariant};
22use std::collections::BTreeMap;
23
24#[derive(Debug, Default, Hash, Clone, Eq, PartialEq, PartialOrd, Ord)]
25pub struct ComponentDependencies {
26 pub dependencies: BTreeMap<ComponentDependencyKey, FunctionDictionary>,
27}
28
29impl ComponentDependencies {
30 pub fn size(&self) -> usize {
31 self.dependencies.len()
32 }
33
34 pub fn get_variants(&self) -> Vec<TypeVariant> {
35 let mut variants = vec![];
36
37 for function_dict in self.dependencies.values() {
38 variants.extend(function_dict.get_all_variants());
39 }
40
41 variants
42 }
43
44 pub fn get_enums(&self) -> Vec<TypeEnum> {
45 let mut enums = vec![];
46
47 for function_dict in self.dependencies.values() {
48 enums.extend(function_dict.get_all_enums());
49 }
50
51 enums
52 }
53
54 pub fn get_function_type(
55 &self,
56 component_info: &Option<ComponentDependencyKey>,
57 function_name: &FunctionName,
58 ) -> Result<FunctionType, String> {
59 match component_info {
62 None => {
63 let mut function_types_in_component = vec![];
64
65 for (component_info, function_dict) in &self.dependencies {
66 let types = function_dict
67 .name_and_types
68 .iter()
69 .filter_map(|(f_name, function_type)| {
70 if f_name == function_name {
71 Some(function_type)
72 } else {
73 None
74 }
75 })
76 .collect::<Vec<_>>();
77
78 function_types_in_component.push((component_info.clone(), types));
79 }
80
81 if function_types_in_component.is_empty() {
82 Err("unknown function".to_string())
83 } else if function_types_in_component.len() > 1 {
84 Err(format!(
85 "function `{function_name}` is ambiguous across components"
86 ))
87 } else {
88 let function_types = function_types_in_component.pop().unwrap();
89 let function_type = function_types.1;
90
91 if function_type.is_empty() {
92 Err("unknown function".to_string())
93 } else {
94 Ok(function_type[0].clone())
95 }
96 }
97 }
98 Some(component_info) => {
99 let function_dictionary = self
100 .dependencies
101 .get(component_info)
102 .cloned()
103 .ok_or_else(|| {
104 format!(
105 "component dependency for `{}` not found",
106 component_info.component_name
107 )
108 })?;
109
110 let function_type = function_dictionary.name_and_types.iter().find_map(
111 |(f_name, function_type)| {
112 if f_name == function_name {
113 Some(function_type.clone())
114 } else {
115 None
116 }
117 },
118 );
119
120 if let Some(function_type) = function_type {
121 Ok(function_type)
122 } else {
123 Err(format!(
124 "function `{}` not found in component `{}`",
125 function_name, component_info.component_name
126 ))
127 }
128 }
129 }
130 }
131
132 pub fn narrow_to_component(&mut self, component_dependency_key: &ComponentDependencyKey) {
133 if let Some(function_dict) = self.dependencies.remove(component_dependency_key) {
135 self.dependencies.clear();
136 self.dependencies
137 .insert(component_dependency_key.clone(), function_dict);
138 }
139 }
140
141 pub fn function_dictionary(&self) -> Vec<&FunctionDictionary> {
142 self.dependencies.values().collect::<Vec<_>>()
143 }
144
145 pub fn filter_by_interface(
146 &self,
147 interface_name: &InterfaceName,
148 ) -> Result<crate::ComponentDependencies, String> {
149 let mut tree = BTreeMap::new();
150
151 for (component_info, function_dict) in self.dependencies.iter() {
152 let name_and_types: Vec<&(FunctionName, FunctionType)> = function_dict
153 .name_and_types
154 .iter()
155 .filter(|(f, _)| f.interface_name().as_ref() == Some(interface_name))
156 .collect::<Vec<_>>();
157
158 if !name_and_types.is_empty() {
159 tree.insert(
160 component_info.clone(),
161 FunctionDictionary {
162 name_and_types: name_and_types.into_iter().cloned().collect(),
163 },
164 );
165 }
166 }
167
168 if tree.is_empty() {
169 return Err(format!("interface `{interface_name}` not found"));
170 }
171
172 Ok(ComponentDependencies { dependencies: tree })
173 }
174
175 pub fn filter_by_package_name(
176 &self,
177 package_name: &PackageName,
178 ) -> Result<crate::ComponentDependencies, String> {
179 let mut tree = BTreeMap::new();
181
182 for (component_info, function_dict) in self.dependencies.iter() {
183 if let Some(root_package_name) = &component_info.root_package_name {
184 if root_package_name == &package_name.to_string() {
185 tree.insert(component_info.clone(), function_dict.clone());
186 }
187 } else {
188 let name_and_types = function_dict
191 .name_and_types
192 .iter()
193 .filter(|(f, _)| f.package_name() == Some(package_name.clone()))
194 .collect::<Vec<_>>();
195
196 if !name_and_types.is_empty() {
197 tree.insert(
198 component_info.clone(),
199 FunctionDictionary {
200 name_and_types: name_and_types.into_iter().cloned().collect(),
201 },
202 );
203 }
204 }
205 }
206
207 if tree.is_empty() {
208 return Err(format!("package `{package_name}` not found"));
209 }
210
211 Ok(crate::ComponentDependencies { dependencies: tree })
212 }
213
214 pub fn filter_by_fully_qualified_interface(
215 &self,
216 fqi: &FullyQualifiedInterfaceName,
217 ) -> Result<Self, String> {
218 let mut tree = BTreeMap::new();
219
220 for (component_info, function_dict) in self.dependencies.iter() {
221 if let Some(root_package_name) = &component_info.root_package_name {
222 if root_package_name == &fqi.package_name.to_string() {
223 tree.insert(component_info.clone(), function_dict.clone());
224 }
225 } else {
226 let name_and_types = function_dict
229 .name_and_types
230 .iter()
231 .filter(|(f, _)| {
232 f.package_name() == Some(fqi.package_name.clone())
233 && f.interface_name() == Some(fqi.interface_name.clone())
234 })
235 .collect::<Vec<_>>();
236
237 if !name_and_types.is_empty() {
238 tree.insert(
239 component_info.clone(),
240 FunctionDictionary {
241 name_and_types: name_and_types.into_iter().cloned().collect(),
242 },
243 );
244 }
245 }
246 }
247
248 if tree.is_empty() {
249 return Err(format!("`{fqi}` not found"));
250 }
251
252 Ok(ComponentDependencies { dependencies: tree })
253 }
254
255 pub fn get_worker_instance_type(
259 &self,
260 type_parameter: Option<TypeParameter>,
261 worker_name: Option<Expr>,
262 ) -> Result<InstanceCreationType, String> {
263 match type_parameter {
264 None => Ok(InstanceCreationType::WitWorker {
265 component_info: None,
266 worker_name: worker_name.map(Box::new),
267 }),
268
269 Some(TypeParameter::PackageName(package_name)) => {
270 let result = self
272 .dependencies
273 .iter()
274 .find(|(x, _)| match &x.root_package_name {
275 Some(name) => {
276 let pkg = match &x.root_package_version {
277 None => name.to_string(),
278 Some(version) => format!("{name}@{version}"),
279 };
280
281 pkg == package_name.to_string()
282 }
283
284 None => false,
285 });
286
287 if let Some(result) = result {
288 Ok(InstanceCreationType::WitWorker {
289 component_info: Some(result.0.clone()),
290 worker_name: worker_name.map(Box::new),
291 })
292 } else {
293 Ok(InstanceCreationType::WitWorker {
294 component_info: None,
295 worker_name: worker_name.map(Box::new),
296 })
297 }
298 }
299
300 _ => Ok(InstanceCreationType::WitWorker {
301 component_info: None,
302 worker_name: worker_name.map(Box::new),
303 }),
304 }
305 }
306
307 pub fn from_raw(
308 component_and_exports: Vec<(ComponentDependencyKey, &Vec<AnalysedExport>)>,
309 ) -> Result<Self, String> {
310 let mut dependencies = BTreeMap::new();
311
312 for (component_info, exports) in component_and_exports {
313 let function_type_registry = FunctionTypeRegistry::from_export_metadata(exports);
314 let function_dictionary =
315 FunctionDictionary::from_function_type_registry(&function_type_registry)?;
316 dependencies.insert(component_info, function_dictionary);
317 }
318
319 Ok(ComponentDependencies { dependencies })
320 }
321}