1use crate::parser::{PackageName, TypeParameter};
16use crate::type_parameter::InterfaceName;
17use crate::FunctionName;
18use crate::{
19 ComponentDependencies, ComponentDependencyKey, Expr, FullyQualifiedResourceConstructor,
20 FunctionDictionary, FunctionType, InferredType, ResourceMethodDictionary,
21};
22use golem_api_grpc::proto::golem::rib::{
23 FullyQualifiedResourceConstructor as ProtoFullyQualifiedResourceConstructor,
24 FunctionType as ProtoFunctionType, InterfaceName as ProtoInterfaceName,
25 PackageName as ProtoPackageName,
26};
27use golem_wasm_ast::analysis::AnalysedType;
28use std::collections::{BTreeMap, HashMap, HashSet};
29use std::convert::TryFrom;
30use std::fmt::Debug;
31use std::ops::Deref;
32
33#[derive(Debug, Hash, Clone, Eq, PartialEq, PartialOrd, Ord)]
41pub enum InstanceType {
42 Global {
44 worker_name: Option<Box<Expr>>,
45 component_dependency: ComponentDependencies,
46 },
47
48 Package {
50 worker_name: Option<Box<Expr>>,
51 package_name: PackageName,
52 component_dependency: ComponentDependencies,
53 },
54
55 Interface {
57 worker_name: Option<Box<Expr>>,
58 interface_name: InterfaceName,
59 component_dependency: ComponentDependencies,
60 },
61
62 PackageInterface {
65 worker_name: Option<Box<Expr>>,
66 package_name: PackageName,
67 interface_name: InterfaceName,
68 component_dependency: ComponentDependencies,
69 },
70
71 Resource {
74 analysed_resource_id: u64,
75 analysed_resource_mode: u8,
76 worker_name: Option<Box<Expr>>,
77 package_name: Option<PackageName>,
78 interface_name: Option<InterfaceName>,
79 resource_constructor: String,
80 resource_args: Vec<Expr>,
81 component_dependency_key: ComponentDependencyKey,
82 resource_method_dictionary: ResourceMethodDictionary,
83 },
84}
85
86impl InstanceType {
87 pub fn narrow_to_single_component(
88 &mut self,
89 component_dependency_key: &ComponentDependencyKey,
90 ) {
91 match self {
92 InstanceType::Global {
93 component_dependency,
94 ..
95 } => {
96 component_dependency.narrow_to_component(component_dependency_key);
97 }
98 InstanceType::Package {
99 component_dependency,
100 ..
101 } => {
102 component_dependency.narrow_to_component(component_dependency_key);
103 }
104 InstanceType::Interface {
105 component_dependency,
106 ..
107 } => {
108 component_dependency.narrow_to_component(component_dependency_key);
109 }
110 InstanceType::PackageInterface {
111 component_dependency,
112 ..
113 } => {
114 component_dependency.narrow_to_component(component_dependency_key);
115 }
116 InstanceType::Resource { .. } => {}
118 }
119 }
120
121 pub fn set_worker_name(&mut self, worker_name: Expr) {
122 match self {
123 InstanceType::Global {
124 worker_name: wn, ..
125 } => {
126 *wn = Some(Box::new(worker_name));
127 }
128 InstanceType::Package {
129 worker_name: wn, ..
130 } => {
131 *wn = Some(Box::new(worker_name));
132 }
133 InstanceType::Interface {
134 worker_name: wn, ..
135 } => {
136 *wn = Some(Box::new(worker_name));
137 }
138 InstanceType::PackageInterface {
139 worker_name: wn, ..
140 } => {
141 *wn = Some(Box::new(worker_name));
142 }
143 InstanceType::Resource {
144 worker_name: wn, ..
145 } => {
146 *wn = Some(Box::new(worker_name));
147 }
148 }
149 }
150
151 pub fn worker_mut(&mut self) -> Option<&mut Box<Expr>> {
152 match self {
153 InstanceType::Global { worker_name, .. } => worker_name.as_mut(),
154 InstanceType::Package { worker_name, .. } => worker_name.as_mut(),
155 InstanceType::Interface { worker_name, .. } => worker_name.as_mut(),
156 InstanceType::PackageInterface { worker_name, .. } => worker_name.as_mut(),
157 InstanceType::Resource { worker_name, .. } => worker_name.as_mut(),
158 }
159 }
160
161 pub fn worker(&self) -> Option<&Expr> {
162 match self {
163 InstanceType::Global { worker_name, .. } => worker_name.as_ref().map(|v| v.deref()),
164 InstanceType::Package { worker_name, .. } => worker_name.as_ref().map(|v| v.deref()),
165 InstanceType::Interface { worker_name, .. } => worker_name.as_ref().map(|v| v.deref()),
166 InstanceType::PackageInterface { worker_name, .. } => {
167 worker_name.as_ref().map(|v| v.deref())
168 }
169 InstanceType::Resource { worker_name, .. } => worker_name.as_ref().map(|v| v.deref()),
170 }
171 }
172
173 pub fn get_resource_instance_type(
174 &self,
175 fully_qualified_resource_constructor: FullyQualifiedResourceConstructor,
176 resource_args: Vec<Expr>,
177 worker_name: Option<Box<Expr>>,
178 analysed_resource_id: u64,
179 analysed_resource_mode: u8,
180 ) -> Result<InstanceType, String> {
181 let interface_name = fully_qualified_resource_constructor.interface_name.clone();
182 let package_name = fully_qualified_resource_constructor.package_name.clone();
183 let resource_constructor_name = fully_qualified_resource_constructor.resource_name.clone();
184
185 let mut tree = vec![];
186 for (component_info, function_type) in self.component_dependencies().dependencies.iter() {
187 let mut resource_method_dict = BTreeMap::new();
188
189 for (name, typ) in function_type.name_and_types.iter() {
190 if let FunctionName::ResourceMethod(resource_method) = name {
191 if resource_method.resource_name == resource_constructor_name
192 && resource_method.interface_name == interface_name
193 && resource_method.package_name == package_name
194 {
195 resource_method_dict.insert(resource_method.clone(), typ.clone());
196 }
197 }
198 }
199
200 tree.push((component_info.clone(), resource_method_dict));
201 }
202
203 if tree.len() == 1 {
204 let (component_dependency_key, resource_methods) = tree.pop().unwrap();
205
206 let resource_method_dict = ResourceMethodDictionary {
207 map: resource_methods,
208 };
209
210 Ok(InstanceType::Resource {
211 worker_name,
212 package_name,
213 interface_name,
214 resource_constructor: resource_constructor_name,
215 resource_args,
216 component_dependency_key,
217 resource_method_dictionary: resource_method_dict,
218 analysed_resource_id,
219 analysed_resource_mode,
220 })
221 } else if tree.is_empty() {
222 Err(format!(
223 "No components found have the resource constructor '{resource_constructor_name}'"
224 ))
225 } else {
226 Err(format!(
227 "Multiple components found with the resource constructor '{resource_constructor_name}'. Please specify the type parameter"
228 ))
229 }
230 }
231
232 pub fn interface_name(&self) -> Option<InterfaceName> {
233 match self {
234 InstanceType::Global { .. } => None,
235 InstanceType::Package { .. } => None,
236 InstanceType::Interface { interface_name, .. } => Some(interface_name.clone()),
237 InstanceType::PackageInterface { interface_name, .. } => Some(interface_name.clone()),
238 InstanceType::Resource { interface_name, .. } => interface_name.clone(),
239 }
240 }
241
242 pub fn package_name(&self) -> Option<PackageName> {
243 match self {
244 InstanceType::Global { .. } => None,
245 InstanceType::Package { package_name, .. } => Some(package_name.clone()),
246 InstanceType::Interface { .. } => None,
247 InstanceType::PackageInterface { package_name, .. } => Some(package_name.clone()),
248 InstanceType::Resource { package_name, .. } => package_name.clone(),
249 }
250 }
251
252 pub fn worker_name(&self) -> Option<Box<Expr>> {
253 match self {
254 InstanceType::Global { worker_name, .. } => worker_name.clone(),
255 InstanceType::Package { worker_name, .. } => worker_name.clone(),
256 InstanceType::Interface { worker_name, .. } => worker_name.clone(),
257 InstanceType::PackageInterface { worker_name, .. } => worker_name.clone(),
258 InstanceType::Resource { worker_name, .. } => worker_name.clone(),
259 }
260 }
261 pub fn get_function(
262 &self,
263 method_name: &str,
264 type_parameter: Option<TypeParameter>,
265 ) -> Result<(ComponentDependencyKey, Function), String> {
266 match type_parameter {
267 Some(tp) => match tp {
268 TypeParameter::Interface(iface) => {
269 let component_dependency =
270 self.component_dependencies().filter_by_interface(&iface)?;
271
272 if component_dependency.dependencies.len() == 1 {
273 let (info, function_dictionary) =
274 component_dependency.dependencies.first_key_value().unwrap();
275
276 let functions = function_dictionary
277 .name_and_types
278 .iter()
279 .filter(|(f, _)| f.name() == method_name)
280 .collect::<Vec<_>>();
281
282 if functions.is_empty() {
283 return Err(format!(
284 "Function '{method_name}' not found in interface '{iface}'"
285 ));
286 }
287
288 if functions.len() == 1 {
289 let (fqfn, ftype) = &functions[0];
290 Ok((
291 info.clone(),
292 Function {
293 function_name: fqfn.clone(),
294 function_type: ftype.clone(),
295 },
296 ))
297 } else {
298 search_function_in_instance(self, method_name, Some(info))
299 }
300 } else {
301 Err(format!("Interface '{iface}' found in multiple components"))
302 }
303 }
304
305 TypeParameter::PackageName(pkg) => {
306 let component_dependency =
307 self.component_dependencies().filter_by_package_name(&pkg)?;
308
309 if component_dependency.dependencies.len() == 1 {
310 let (info, function_dictionary) =
311 component_dependency.dependencies.first_key_value().unwrap();
312
313 let packages = function_dictionary
314 .name_and_types
315 .iter()
316 .filter(|(f, _)| f.package_name() == Some(pkg.clone()))
317 .collect::<Vec<_>>();
318
319 if packages.is_empty() {
320 return Err(format!("package '{pkg}' not found"));
321 }
322
323 let functions = packages
324 .into_iter()
325 .filter(|(f, _)| f.name() == method_name)
326 .collect::<Vec<_>>();
327
328 if functions.is_empty() {
329 return Err(format!(
330 "function '{method_name}' not found in package '{pkg}'"
331 ));
332 }
333
334 if functions.len() == 1 {
335 let (fqfn, ftype) = &functions[0];
336 Ok((
337 info.clone(),
338 Function {
339 function_name: fqfn.clone(),
340 function_type: ftype.clone(),
341 },
342 ))
343 } else {
344 search_function_in_instance(self, method_name, Some(info))
345 }
346 } else {
347 Err(format!(
348 "package '{pkg}' found in multiple components. Please specify the root package name instead"
349 ))
350 }
351 }
352
353 TypeParameter::FullyQualifiedInterface(fq_iface) => {
354 let component_dependency = self
355 .component_dependencies()
356 .filter_by_fully_qualified_interface(&fq_iface)?;
357
358 if component_dependency.dependencies.len() == 1 {
359 let (info, function_dictionary) =
360 component_dependency.dependencies.first_key_value().unwrap();
361
362 let functions = function_dictionary
363 .name_and_types
364 .iter()
365 .filter(|(f, _)| {
366 f.package_name() == Some(fq_iface.package_name.clone())
367 && f.interface_name() == Some(fq_iface.interface_name.clone())
368 && f.name() == method_name
369 })
370 .collect::<Vec<_>>();
371
372 if functions.is_empty() {
373 return Err(format!(
374 "function '{method_name}' not found in interface '{fq_iface}'"
375 ));
376 }
377
378 if functions.len() == 1 {
379 let (fqfn, ftype) = &functions[0];
380 Ok((
381 info.clone(),
382 Function {
383 function_name: fqfn.clone(),
384 function_type: ftype.clone(),
385 },
386 ))
387 } else {
388 search_function_in_instance(self, method_name, Some(info))
389 }
390 } else {
391 Err(format!(
392 "interface '{fq_iface}' found in multiple components. Please specify the root package name instead"
393 ))
394 }
395 }
396 },
397 None => search_function_in_instance(self, method_name, None),
398 }
399 }
400
401 pub fn resource_method_dictionary(&self) -> FunctionDictionary {
403 let name_and_types = self
404 .component_dependencies()
405 .dependencies
406 .values()
407 .flat_map(|function_dictionary| {
408 function_dictionary
409 .name_and_types
410 .iter()
411 .filter(|(f, _)| matches!(f, FunctionName::ResourceMethod(_)))
412 .map(|(f, t)| (f.clone(), t.clone()))
413 .collect::<Vec<_>>()
414 })
415 .collect();
416
417 FunctionDictionary { name_and_types }
418 }
419
420 pub fn function_dict_without_resource_methods(&self) -> FunctionDictionary {
421 let name_and_types = self
422 .component_dependencies()
423 .dependencies
424 .values()
425 .flat_map(|function_dictionary| {
426 function_dictionary
427 .name_and_types
428 .iter()
429 .filter(|(f, _)| {
430 !matches!(f, FunctionName::ResourceMethod(_))
431 && !matches!(f, FunctionName::Variant(_))
432 && !matches!(f, FunctionName::Enum(_))
433 })
434 .map(|(f, t)| (f.clone(), t.clone()))
435 .collect::<Vec<_>>()
436 })
437 .collect();
438
439 FunctionDictionary { name_and_types }
440 }
441
442 pub fn component_dependencies(&self) -> ComponentDependencies {
443 match self {
444 InstanceType::Global {
445 component_dependency,
446 ..
447 } => component_dependency.clone(),
448 InstanceType::Package {
449 component_dependency,
450 ..
451 } => component_dependency.clone(),
452 InstanceType::Interface {
453 component_dependency,
454 ..
455 } => component_dependency.clone(),
456 InstanceType::PackageInterface {
457 component_dependency,
458 ..
459 } => component_dependency.clone(),
460 InstanceType::Resource {
461 resource_method_dictionary,
462 component_dependency_key,
463 ..
464 } => {
465 let function_dictionary = FunctionDictionary::from(resource_method_dictionary);
466 let mut dependencies = BTreeMap::new();
467 dependencies.insert(component_dependency_key.clone(), function_dictionary);
468
469 ComponentDependencies { dependencies }
470 }
471 }
472 }
473
474 pub fn from(
475 dependency: &ComponentDependencies,
476 worker_name: Option<&Expr>,
477 type_parameter: Option<TypeParameter>,
478 ) -> Result<InstanceType, String> {
479 match type_parameter {
480 None => Ok(InstanceType::Global {
481 worker_name: worker_name.cloned().map(Box::new),
482 component_dependency: dependency.clone(),
483 }),
484 Some(type_parameter) => match type_parameter {
485 TypeParameter::Interface(interface_name) => {
486 let new_dependency = dependency.filter_by_interface(&interface_name)?;
487
488 Ok(InstanceType::Interface {
489 worker_name: worker_name.cloned().map(Box::new),
490 interface_name,
491 component_dependency: new_dependency,
492 })
493 }
494 TypeParameter::PackageName(package_name) => {
495 let new_dependency = dependency.filter_by_package_name(&package_name)?;
496
497 Ok(InstanceType::Package {
498 worker_name: worker_name.cloned().map(Box::new),
499 package_name,
500 component_dependency: new_dependency,
501 })
502 }
503 TypeParameter::FullyQualifiedInterface(fqi) => {
504 let component_dependency =
505 dependency.filter_by_fully_qualified_interface(&fqi)?;
506
507 Ok(InstanceType::PackageInterface {
508 worker_name: worker_name.cloned().map(Box::new),
509 package_name: fqi.package_name,
510 interface_name: fqi.interface_name,
511 component_dependency,
512 })
513 }
514 },
515 }
516 }
517}
518
519#[derive(Debug, Clone)]
520pub struct Function {
521 pub function_name: FunctionName,
522 pub function_type: FunctionType,
523}
524
525fn search_function_in_instance(
526 instance: &InstanceType,
527 function_name: &str,
528 component_info: Option<&ComponentDependencyKey>,
529) -> Result<(ComponentDependencyKey, Function), String> {
530 match component_info {
531 Some(component_info) => {
532 let dependencies = instance.component_dependencies();
533
534 let function_dictionary =
535 dependencies
536 .dependencies
537 .get(component_info)
538 .ok_or(format!(
539 "component '{component_info}' not found in dependencies"
540 ))?;
541
542 let functions = function_dictionary
543 .name_and_types
544 .iter()
545 .filter(|(f, _)| f.name() == function_name)
546 .collect::<Vec<_>>();
547
548 if functions.is_empty() {
549 return Err(format!(
550 "function '{function_name}' not found in component '{component_info}'"
551 ));
552 }
553
554 let mut package_map: HashMap<Option<PackageName>, HashSet<Option<InterfaceName>>> =
555 HashMap::new();
556
557 for (fqfn, _) in &functions {
558 package_map
559 .entry(fqfn.package_name())
560 .or_default()
561 .insert(fqfn.interface_name());
562 }
563
564 match package_map.len() {
565 1 => {
566 let interfaces = package_map.values().flatten().cloned().collect();
567 let function =
568 search_function_in_single_package(interfaces, functions, function_name)?;
569
570 Ok((component_info.clone(), function))
571 }
572 _ => {
573 let function =
574 search_function_in_multiple_packages(function_name, package_map)?;
575 Ok((component_info.clone(), function))
576 }
577 }
578 }
579 None => {
580 let mut component_info_functions = vec![];
581
582 for (info, function_dictionary) in instance.component_dependencies().dependencies.iter()
583 {
584 let functions = function_dictionary
585 .name_and_types
586 .iter()
587 .filter(|(f, _)| f.name() == function_name)
588 .collect::<Vec<_>>();
589
590 if functions.is_empty() {
591 continue;
592 }
593
594 let mut package_map: HashMap<Option<PackageName>, HashSet<Option<InterfaceName>>> =
595 HashMap::new();
596
597 for (fqfn, _) in &functions {
598 package_map
599 .entry(fqfn.package_name())
600 .or_default()
601 .insert(fqfn.interface_name());
602 }
603
604 match package_map.len() {
605 1 => {
606 let interfaces = package_map.values().flatten().cloned().collect();
607 let function = search_function_in_single_package(
608 interfaces,
609 functions,
610 function_name,
611 )?;
612
613 component_info_functions.push((info.clone(), function));
614 }
615 _ => {
616 let function =
617 search_function_in_multiple_packages(function_name, package_map)?;
618
619 component_info_functions.push((info.clone(), function));
620 }
621 }
622 }
623
624 if component_info_functions.len() == 1 {
625 let (info, function) = &component_info_functions[0];
626 Ok((info.clone(), function.clone()))
627 } else if component_info_functions.is_empty() {
628 Err(format!("function '{function_name}' not found"))
629 } else {
630 Err(format!(
631 "function '{function_name}' found in multiple components. Please specify the type parameter"
632 ))
633 }
634 }
635 }
636}
637
638fn search_function_in_single_package(
639 interfaces: HashSet<Option<InterfaceName>>,
640 functions: Vec<&(FunctionName, FunctionType)>,
641 function_name: &str,
642) -> Result<Function, String> {
643 if interfaces.len() == 1 {
644 let (fqfn, ftype) = &functions[0];
645 Ok(Function {
646 function_name: fqfn.clone(),
647 function_type: ftype.clone(),
648 })
649 } else {
650 let mut interfaces = interfaces
651 .into_iter()
652 .filter_map(|iface| iface.map(|i| i.name))
653 .collect::<Vec<_>>();
654
655 interfaces.sort();
656
657 Err(format!(
659 "multiple interfaces contain function '{}'. specify an interface name as type parameter from: {}",
660 function_name,
661 interfaces
662 .join(", ")
663 ))
664 }
665}
666
667fn search_function_in_multiple_packages(
668 function_name: &str,
669 package_map: HashMap<Option<PackageName>, HashSet<Option<InterfaceName>>>,
670) -> Result<Function, String> {
671 let mut error_msg = format!(
672 "function '{function_name}' exists in multiple packages. specify a package name as type parameter from: "
673 );
674
675 let mut package_interface_list = package_map
676 .into_iter()
677 .filter_map(|(pkg, interfaces)| {
678 pkg.map(|p| {
679 let mut interface_list = interfaces
680 .into_iter()
681 .filter_map(|iface| iface.map(|i| i.name))
682 .collect::<Vec<_>>();
683
684 interface_list.sort();
685
686 if interface_list.is_empty() {
687 format!("{p}")
688 } else {
689 format!("{} (interfaces: {})", p, interface_list.join(", "))
690 }
691 })
692 })
693 .collect::<Vec<_>>();
694
695 package_interface_list.sort();
696
697 error_msg.push_str(&package_interface_list.join(", "));
698 Err(error_msg)
699}
700
701#[cfg(feature = "protobuf")]
702mod protobuf {
703 use crate::{
704 FullyQualifiedFunctionName, FullyQualifiedResourceConstructor,
705 FullyQualifiedResourceMethod, InterfaceName, PackageName,
706 };
707 use golem_api_grpc::proto::golem::rib::FullyQualifiedFunctionName as ProtoFullyQualifiedFunctionName;
708 use golem_api_grpc::proto::golem::rib::FullyQualifiedResourceConstructor as ProtoFullyQualifiedResourceConstructor;
709 use golem_api_grpc::proto::golem::rib::FullyQualifiedResourceMethod as ProtoFullyQualifiedResourceMethod;
710 use golem_api_grpc::proto::golem::rib::InterfaceName as ProtoInterfaceName;
711 use golem_api_grpc::proto::golem::rib::PackageName as ProtoPackageName;
712
713 impl TryFrom<ProtoPackageName> for PackageName {
714 type Error = String;
715
716 fn try_from(proto: ProtoPackageName) -> Result<Self, Self::Error> {
717 Ok(PackageName {
718 namespace: proto.namespace,
719 package_name: proto.package_name,
720 version: proto.version,
721 })
722 }
723 }
724
725 impl TryFrom<ProtoInterfaceName> for InterfaceName {
726 type Error = String;
727
728 fn try_from(value: ProtoInterfaceName) -> Result<Self, Self::Error> {
729 Ok(InterfaceName {
730 name: value.name,
731 version: value.version,
732 })
733 }
734 }
735
736 impl TryFrom<ProtoFullyQualifiedFunctionName> for FullyQualifiedFunctionName {
737 type Error = String;
738
739 fn try_from(proto: ProtoFullyQualifiedFunctionName) -> Result<Self, Self::Error> {
740 Ok(FullyQualifiedFunctionName {
741 package_name: proto.package_name.map(TryFrom::try_from).transpose()?,
742 interface_name: proto.interface_name.map(TryFrom::try_from).transpose()?,
743 function_name: proto.function_name,
744 })
745 }
746 }
747
748 impl From<FullyQualifiedFunctionName> for ProtoFullyQualifiedFunctionName {
749 fn from(value: FullyQualifiedFunctionName) -> Self {
750 ProtoFullyQualifiedFunctionName {
751 package_name: value.package_name.map(ProtoPackageName::from),
752 interface_name: value.interface_name.map(ProtoInterfaceName::from),
753 function_name: value.function_name,
754 }
755 }
756 }
757
758 impl TryFrom<ProtoFullyQualifiedResourceMethod> for FullyQualifiedResourceMethod {
759 type Error = String;
760
761 fn try_from(proto: ProtoFullyQualifiedResourceMethod) -> Result<Self, Self::Error> {
762 Ok(FullyQualifiedResourceMethod {
763 resource_name: proto.resource_name,
764 method_name: proto.method_name,
765 package_name: proto.package_name.map(TryFrom::try_from).transpose()?,
766 interface_name: proto.interface_name.map(TryFrom::try_from).transpose()?,
767 static_function: false, })
769 }
770 }
771
772 impl From<FullyQualifiedResourceMethod> for ProtoFullyQualifiedResourceMethod {
773 fn from(value: FullyQualifiedResourceMethod) -> Self {
774 ProtoFullyQualifiedResourceMethod {
775 resource_name: value.resource_name,
776 method_name: value.method_name,
777 package_name: value.package_name.map(ProtoPackageName::from),
778 interface_name: value.interface_name.map(ProtoInterfaceName::from),
779 }
780 }
781 }
782
783 impl TryFrom<ProtoFullyQualifiedResourceConstructor> for FullyQualifiedResourceConstructor {
784 type Error = String;
785
786 fn try_from(proto: ProtoFullyQualifiedResourceConstructor) -> Result<Self, Self::Error> {
787 Ok(FullyQualifiedResourceConstructor {
788 package_name: proto.package_name.map(TryFrom::try_from).transpose()?,
789 interface_name: proto.interface_name.map(TryFrom::try_from).transpose()?,
790 resource_name: proto.resource_name,
791 })
792 }
793 }
794}
795
796impl TryFrom<ProtoFunctionType> for FunctionType {
797 type Error = String;
798
799 fn try_from(proto: ProtoFunctionType) -> Result<Self, Self::Error> {
800 let mut parameter_types = Vec::new();
801 for param in proto.parameter_types {
802 parameter_types.push(InferredType::from(&AnalysedType::try_from(¶m)?));
803 }
804
805 let return_type = proto
806 .return_type
807 .as_ref()
808 .map(|ret| AnalysedType::try_from(ret).map(|ret| InferredType::from(&ret)))
809 .transpose()?;
810
811 Ok(Self {
812 parameter_types,
813 return_type,
814 })
815 }
816}
817
818impl From<PackageName> for ProtoPackageName {
819 fn from(value: PackageName) -> Self {
820 ProtoPackageName {
821 namespace: value.namespace,
822 package_name: value.package_name,
823 version: value.version,
824 }
825 }
826}
827
828impl From<InterfaceName> for ProtoInterfaceName {
829 fn from(value: InterfaceName) -> Self {
830 ProtoInterfaceName {
831 name: value.name,
832 version: value.version,
833 }
834 }
835}
836
837impl From<FullyQualifiedResourceConstructor> for ProtoFullyQualifiedResourceConstructor {
838 fn from(value: FullyQualifiedResourceConstructor) -> Self {
839 ProtoFullyQualifiedResourceConstructor {
840 package_name: value.package_name.map(ProtoPackageName::from),
841 interface_name: value.interface_name.map(ProtoInterfaceName::from),
842 resource_name: value.resource_name,
843 }
844 }
845}