1use crate::call_type::CallType;
16use crate::DynamicParsedFunctionName;
17use golem_wasm_ast::analysis::AnalysedType;
18use golem_wasm_ast::analysis::{AnalysedExport, TypeVariant};
19use std::collections::{HashMap, HashSet};
20use std::fmt::{Display, Formatter};
21
22#[derive(Debug, PartialEq, Eq, Clone)]
27pub struct FunctionTypeRegistry {
28 pub types: HashMap<RegistryKey, RegistryValue>,
29}
30
31impl FunctionTypeRegistry {
32 pub fn get_from_keys(&self, keys: HashSet<RegistryKey>) -> FunctionTypeRegistry {
33 let mut types = HashMap::new();
34 for key in keys {
35 let registry_value = self.lookup(&key);
36 if let Some(registry_value) = registry_value {
37 types.insert(key, registry_value);
38 }
39 }
40
41 FunctionTypeRegistry { types }
42 }
43
44 pub fn get_variants(&self) -> Vec<TypeVariant> {
45 let mut variants = vec![];
46
47 for registry_value in self.types.values() {
48 if let RegistryValue::Variant { variant_type, .. } = registry_value {
49 variants.push(variant_type.clone())
50 }
51 }
52
53 variants
54 }
55
56 pub fn get(&self, key: &CallType) -> Option<&RegistryValue> {
57 match key {
58 CallType::Function { function_name, .. } => self
59 .types
60 .get(&RegistryKey::fqn_registry_key(function_name)),
61 CallType::VariantConstructor(variant_name) => self
62 .types
63 .get(&RegistryKey::FunctionName(variant_name.clone())),
64 CallType::EnumConstructor(enum_name) => self
65 .types
66 .get(&RegistryKey::FunctionName(enum_name.clone())),
67 CallType::InstanceCreation(_) => None,
68 }
69 }
70
71 pub fn empty() -> Self {
72 Self {
73 types: HashMap::new(),
74 }
75 }
76
77 pub fn from_export_metadata(exports: &Vec<AnalysedExport>) -> Self {
78 let mut map = HashMap::new();
79
80 let mut types = HashSet::new();
81
82 for export in exports {
83 match export {
84 AnalysedExport::Instance(ty) => {
85 let interface_name = &ty.name;
86 for fun in ty.functions.clone() {
87 let function_name = fun.name;
88 let parameter_types = fun
89 .parameters
90 .into_iter()
91 .map(|parameter| {
92 let analysed_type = parameter.typ;
93 types.insert(analysed_type.clone());
94 analysed_type
95 })
96 .collect::<Vec<_>>();
97
98 let return_types = fun
99 .results
100 .into_iter()
101 .map(|result| {
102 let analysed_type = result.typ;
103 types.insert(analysed_type.clone());
104 analysed_type
105 })
106 .collect::<Vec<_>>();
107
108 let registry_key = RegistryKey::FunctionNameWithInterface {
109 interface_name: interface_name.clone(),
110 function_name: function_name.clone(),
111 };
112
113 let registry_value = RegistryValue::Function {
114 parameter_types,
115 return_types,
116 };
117
118 map.insert(registry_key, registry_value);
119 }
120 }
121 AnalysedExport::Function(fun0) => {
122 let fun = fun0.clone();
123 let function_name = fun.name;
124 let parameter_types = fun
125 .parameters
126 .into_iter()
127 .map(|parameter| {
128 let analysed_type = parameter.typ;
129 types.insert(analysed_type.clone());
130 analysed_type
131 })
132 .collect::<Vec<_>>();
133
134 let return_types = fun
135 .results
136 .into_iter()
137 .map(|result| {
138 let analysed_type = result.typ;
139 types.insert(analysed_type.clone());
140 analysed_type
141 })
142 .collect::<Vec<_>>();
143
144 let registry_value = RegistryValue::Function {
145 parameter_types,
146 return_types,
147 };
148
149 let registry_key = RegistryKey::FunctionName(function_name.clone());
150
151 map.insert(registry_key, registry_value);
152 }
153 }
154 }
155
156 for ty in types {
157 internal::update_registry(&ty, &mut map);
158 }
159
160 Self { types: map }
161 }
162
163 pub fn lookup(&self, registry_key: &RegistryKey) -> Option<RegistryValue> {
164 self.types.get(registry_key).cloned()
165 }
166}
167
168#[derive(Hash, Eq, PartialEq, PartialOrd, Ord, Clone, Debug)]
170pub enum RegistryKey {
171 FunctionName(String),
172 FunctionNameWithInterface {
173 interface_name: String,
174 function_name: String,
175 },
176}
177
178impl Display for RegistryKey {
179 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
180 match self {
181 RegistryKey::FunctionName(name) => write!(f, "Function Name: {}", name),
182 RegistryKey::FunctionNameWithInterface {
183 interface_name,
184 function_name,
185 } => write!(
186 f,
187 "Interface: {}, Function: {}",
188 interface_name, function_name
189 ),
190 }
191 }
192}
193
194impl RegistryKey {
195 pub fn get_function_name(&self) -> String {
203 match self {
204 Self::FunctionName(str) => str.clone(),
205 Self::FunctionNameWithInterface { function_name, .. } => function_name.clone(),
206 }
207 }
208
209 pub fn get_interface_name(&self) -> Option<String> {
210 match self {
211 Self::FunctionName(_) => None,
212 Self::FunctionNameWithInterface { interface_name, .. } => Some(interface_name.clone()),
213 }
214 }
215
216 pub fn registry_keys_of_function(
221 function_name: &DynamicParsedFunctionName,
222 ) -> Vec<RegistryKey> {
223 let resource_constructor_key = Self::resource_constructor_registry_key(function_name);
224 let function_name_registry_key = Self::fqn_registry_key(function_name);
225 if let Some(resource_constructor_key) = resource_constructor_key {
226 vec![resource_constructor_key, function_name_registry_key]
227 } else {
228 vec![function_name_registry_key]
229 }
230 }
231
232 pub fn fqn_registry_key(function: &DynamicParsedFunctionName) -> RegistryKey {
236 let resource_method_name_in_metadata = function.function_name_with_prefix_identifiers();
237
238 match function.site.interface_name() {
239 None => RegistryKey::FunctionName(resource_method_name_in_metadata),
240 Some(interface) => RegistryKey::FunctionNameWithInterface {
241 interface_name: interface.to_string(),
242 function_name: resource_method_name_in_metadata,
243 },
244 }
245 }
246
247 pub fn resource_constructor_registry_key(
249 function: &DynamicParsedFunctionName,
250 ) -> Option<RegistryKey> {
251 let resource_name_without_prefixes = function.resource_name_simplified();
252
253 resource_name_without_prefixes.map(|resource_name_without_prefix| {
254 let resource_constructor_with_prefix =
255 format!["[constructor]{}", resource_name_without_prefix];
256
257 match function.site.interface_name() {
258 None => RegistryKey::FunctionName(resource_constructor_with_prefix),
259 Some(interface) => RegistryKey::FunctionNameWithInterface {
260 interface_name: interface.to_string(),
261 function_name: resource_constructor_with_prefix,
262 },
263 }
264 })
265 }
266
267 pub fn from_call_type(call_type: &CallType) -> Option<RegistryKey> {
268 match call_type {
269 CallType::VariantConstructor(variant_name) => {
270 Some(RegistryKey::FunctionName(variant_name.clone()))
271 }
272 CallType::EnumConstructor(enum_name) => {
273 Some(RegistryKey::FunctionName(enum_name.clone()))
274 }
275 CallType::Function { function_name, .. } => match function_name.site.interface_name() {
276 None => Some(RegistryKey::FunctionName(
277 function_name.function_name_with_prefix_identifiers(),
278 )),
279 Some(interface_name) => Some(RegistryKey::FunctionNameWithInterface {
280 interface_name: interface_name.to_string(),
281 function_name: function_name.function_name_with_prefix_identifiers(),
282 }),
283 },
284 CallType::InstanceCreation(_) => None,
285 }
286 }
287}
288
289#[derive(PartialEq, Eq, Clone, Debug)]
290pub enum RegistryValue {
291 Value(AnalysedType),
292 Variant {
293 parameter_types: Vec<AnalysedType>,
294 variant_type: TypeVariant,
295 },
296 Function {
297 parameter_types: Vec<AnalysedType>,
298 return_types: Vec<AnalysedType>,
299 },
300}
301
302impl RegistryValue {
303 pub fn argument_types(&self) -> Vec<AnalysedType> {
304 match self {
305 RegistryValue::Function {
306 parameter_types,
307 return_types: _,
308 } => parameter_types.clone(),
309 RegistryValue::Variant {
310 parameter_types,
311 variant_type: _,
312 } => parameter_types.clone(),
313 RegistryValue::Value(_) => vec![],
314 }
315 }
316}
317
318mod internal {
319 use crate::{RegistryKey, RegistryValue};
320 use golem_wasm_ast::analysis::{AnalysedType, TypeResult};
321 use std::collections::HashMap;
322
323 pub(crate) fn update_registry(
324 ty: &AnalysedType,
325 registry: &mut HashMap<RegistryKey, RegistryValue>,
326 ) {
327 match ty.clone() {
328 AnalysedType::Variant(variant) => {
329 let type_variant = variant.clone();
330 for name_type_pair in &type_variant.cases {
331 registry.insert(RegistryKey::FunctionName(name_type_pair.name.clone()), {
332 name_type_pair.typ.clone().map_or(
333 RegistryValue::Value(ty.clone()),
334 |variant_parameter_typ| RegistryValue::Variant {
335 parameter_types: vec![variant_parameter_typ],
336 variant_type: type_variant.clone(),
337 },
338 )
339 });
340 }
341 }
342
343 AnalysedType::Enum(type_enum) => {
344 for name_type_pair in type_enum.cases {
345 registry.insert(
346 RegistryKey::FunctionName(name_type_pair.clone()),
347 RegistryValue::Value(ty.clone()),
348 );
349 }
350 }
351
352 AnalysedType::Tuple(tuple) => {
353 for element in tuple.items {
354 update_registry(&element, registry);
355 }
356 }
357
358 AnalysedType::List(list) => {
359 update_registry(list.inner.as_ref(), registry);
360 }
361
362 AnalysedType::Record(record) => {
363 for name_type in record.fields.iter() {
364 update_registry(&name_type.typ, registry);
365 }
366 }
367
368 AnalysedType::Result(TypeResult {
369 ok: Some(ok_type),
370 err: Some(err_type),
371 }) => {
372 update_registry(ok_type.as_ref(), registry);
373 update_registry(err_type.as_ref(), registry);
374 }
375 AnalysedType::Result(TypeResult {
376 ok: None,
377 err: Some(err_type),
378 }) => {
379 update_registry(err_type.as_ref(), registry);
380 }
381 AnalysedType::Result(TypeResult {
382 ok: Some(ok_type),
383 err: None,
384 }) => {
385 update_registry(ok_type.as_ref(), registry);
386 }
387 AnalysedType::Option(type_option) => {
388 update_registry(type_option.inner.as_ref(), registry);
389 }
390 AnalysedType::Result(TypeResult {
391 ok: None,
392 err: None,
393 }) => {}
394 AnalysedType::Flags(_) => {}
395 AnalysedType::Str(_) => {}
396 AnalysedType::Chr(_) => {}
397 AnalysedType::F64(_) => {}
398 AnalysedType::F32(_) => {}
399 AnalysedType::U64(_) => {}
400 AnalysedType::S64(_) => {}
401 AnalysedType::U32(_) => {}
402 AnalysedType::S32(_) => {}
403 AnalysedType::U16(_) => {}
404 AnalysedType::S16(_) => {}
405 AnalysedType::U8(_) => {}
406 AnalysedType::S8(_) => {}
407 AnalysedType::Bool(_) => {}
408 AnalysedType::Handle(_) => {}
409 }
410 }
411}
412
413#[cfg(feature = "protobuf")]
414mod protobuf {
415
416 use crate::RegistryKey;
417 use golem_api_grpc::proto::golem::rib::registry_key::KeyType;
418
419 impl TryFrom<golem_api_grpc::proto::golem::rib::RegistryKey> for RegistryKey {
420 type Error = String;
421
422 fn try_from(
423 value: golem_api_grpc::proto::golem::rib::RegistryKey,
424 ) -> Result<Self, Self::Error> {
425 let key_type = value.key_type.ok_or("key type missing")?;
426
427 let registry_key = match key_type {
428 KeyType::FunctionName(string) => RegistryKey::FunctionName(string.name),
429 KeyType::FunctionNameWithInterface(function_with_interface) => {
430 let interface_name = function_with_interface.interface_name.clone();
431 let function_name = function_with_interface.function_name;
432
433 RegistryKey::FunctionNameWithInterface {
434 interface_name,
435 function_name,
436 }
437 }
438 };
439
440 Ok(registry_key)
441 }
442 }
443
444 impl From<&RegistryKey> for golem_api_grpc::proto::golem::rib::RegistryKey {
445 fn from(value: &RegistryKey) -> Self {
446 match value {
447 RegistryKey::FunctionName(name) => golem_api_grpc::proto::golem::rib::RegistryKey {
448 key_type: Some(KeyType::FunctionName(
449 golem_api_grpc::proto::golem::rib::FunctionName {
450 name: name.to_string(),
451 },
452 )),
453 },
454 RegistryKey::FunctionNameWithInterface {
455 function_name,
456 interface_name,
457 } => golem_api_grpc::proto::golem::rib::RegistryKey {
458 key_type: Some(KeyType::FunctionNameWithInterface(
459 golem_api_grpc::proto::golem::rib::FunctionNameWithInterface {
460 interface_name: interface_name.clone(),
461 function_name: function_name.clone(),
462 },
463 )),
464 },
465 }
466 }
467 }
468}