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(
176 &self,
177 fully_qualified_resource_constructor: FullyQualifiedResourceConstructor,
178 resource_args: Vec<Expr>,
179 worker_name: Option<Box<Expr>>,
180 analysed_resource_id: u64,
181 analysed_resource_mode: u8,
182 ) -> Result<InstanceType, String> {
183 let interface_name = fully_qualified_resource_constructor.interface_name.clone();
184 let package_name = fully_qualified_resource_constructor.package_name.clone();
185 let resource_constructor_name = fully_qualified_resource_constructor.resource_name.clone();
186
187 let mut tree = vec![];
188 for (component_info, function_type) in self.component_dependencies().dependencies.iter() {
189 let mut resource_method_dict = BTreeMap::new();
190
191 for (name, typ) in function_type.name_and_types.iter() {
192 if let FunctionName::ResourceMethod(resource_method) = name {
193 if resource_method.resource_name == resource_constructor_name
194 && resource_method.interface_name == interface_name
195 && resource_method.package_name == package_name
196 {
197 resource_method_dict.insert(resource_method.clone(), typ.clone());
198 }
199 }
200 }
201
202 tree.push((component_info.clone(), resource_method_dict));
203 }
204
205 if tree.len() == 1 {
206 let (component_dependency_key, resource_methods) = tree.pop().unwrap();
207
208 let resource_method_dict = ResourceMethodDictionary {
209 map: resource_methods,
210 };
211
212 Ok(InstanceType::Resource {
213 worker_name,
214 package_name,
215 interface_name,
216 resource_constructor: resource_constructor_name,
217 resource_args,
218 component_dependency_key,
219 resource_method_dictionary: resource_method_dict,
220 analysed_resource_id,
221 analysed_resource_mode,
222 })
223 } else if tree.is_empty() {
224 Err(format!(
225 "No components found have the resource constructor '{resource_constructor_name}'"
226 ))
227 } else {
228 Err(format!(
229 "Multiple components found with the resource constructor '{resource_constructor_name}'. Please specify the type parameter"
230 ))
231 }
232 }
233
234 pub fn interface_name(&self) -> Option<InterfaceName> {
235 match self {
236 InstanceType::Global { .. } => None,
237 InstanceType::Package { .. } => None,
238 InstanceType::Interface { interface_name, .. } => Some(interface_name.clone()),
239 InstanceType::PackageInterface { interface_name, .. } => Some(interface_name.clone()),
240 InstanceType::Resource { interface_name, .. } => interface_name.clone(),
241 }
242 }
243
244 pub fn package_name(&self) -> Option<PackageName> {
245 match self {
246 InstanceType::Global { .. } => None,
247 InstanceType::Package { package_name, .. } => Some(package_name.clone()),
248 InstanceType::Interface { .. } => None,
249 InstanceType::PackageInterface { package_name, .. } => Some(package_name.clone()),
250 InstanceType::Resource { package_name, .. } => package_name.clone(),
251 }
252 }
253
254 pub fn worker_name(&self) -> Option<Box<Expr>> {
255 match self {
256 InstanceType::Global { worker_name, .. } => worker_name.clone(),
257 InstanceType::Package { worker_name, .. } => worker_name.clone(),
258 InstanceType::Interface { worker_name, .. } => worker_name.clone(),
259 InstanceType::PackageInterface { worker_name, .. } => worker_name.clone(),
260 InstanceType::Resource { worker_name, .. } => worker_name.clone(),
261 }
262 }
263 pub fn get_function(
264 &self,
265 method_name: &str,
266 type_parameter: Option<TypeParameter>,
267 ) -> Result<(ComponentDependencyKey, Function), String> {
268 match type_parameter {
269 Some(tp) => match tp {
270 TypeParameter::Interface(iface) => {
271 let component_dependency =
272 self.component_dependencies().filter_by_interface(&iface)?;
273
274 if component_dependency.size() == 1 {
275 let (info, function_dictionary) =
276 component_dependency.dependencies.first_key_value().unwrap();
277
278 let functions = function_dictionary
279 .name_and_types
280 .iter()
281 .filter(|(f, _)| f.name() == method_name)
282 .collect::<Vec<_>>();
283
284 if functions.is_empty() {
285 return Err(format!(
286 "Function '{method_name}' not found in interface '{iface}'"
287 ));
288 }
289
290 if functions.len() == 1 {
291 let (fqfn, ftype) = &functions[0];
292 Ok((
293 info.clone(),
294 Function {
295 function_name: fqfn.clone(),
296 function_type: ftype.clone(),
297 },
298 ))
299 } else {
300 search_function_in_instance(self, method_name, Some(info))
301 }
302 } else {
303 Err(format!("Interface '{iface}' found in multiple components"))
304 }
305 }
306
307 TypeParameter::PackageName(pkg) => {
308 let component_dependency =
309 self.component_dependencies().filter_by_package_name(&pkg)?;
310
311 if component_dependency.size() == 1 {
312 let (info, function_dictionary) =
313 component_dependency.dependencies.first_key_value().unwrap();
314
315 let packages = function_dictionary
316 .name_and_types
317 .iter()
318 .filter(|(f, _)| f.package_name() == Some(pkg.clone()))
319 .collect::<Vec<_>>();
320
321 if packages.is_empty() {
322 return Err(format!("package '{pkg}' not found"));
323 }
324
325 let functions = packages
326 .into_iter()
327 .filter(|(f, _)| f.name() == method_name)
328 .collect::<Vec<_>>();
329
330 if functions.is_empty() {
331 return Err(format!(
332 "function '{method_name}' not found in package '{pkg}'"
333 ));
334 }
335
336 if functions.len() == 1 {
337 let (fqfn, ftype) = &functions[0];
338 Ok((
339 info.clone(),
340 Function {
341 function_name: fqfn.clone(),
342 function_type: ftype.clone(),
343 },
344 ))
345 } else {
346 search_function_in_instance(self, method_name, Some(info))
347 }
348 } else {
349 Err(format!(
350 "package '{pkg}' found in multiple components. Please specify the root package name instead"
351 ))
352 }
353 }
354
355 TypeParameter::FullyQualifiedInterface(fq_iface) => {
356 let component_dependency = self
357 .component_dependencies()
358 .filter_by_fully_qualified_interface(&fq_iface)?;
359
360 if component_dependency.size() == 1 {
361 let (info, function_dictionary) =
362 component_dependency.dependencies.first_key_value().unwrap();
363
364 let functions = function_dictionary
365 .name_and_types
366 .iter()
367 .filter(|(f, _)| {
368 f.package_name() == Some(fq_iface.package_name.clone())
369 && f.interface_name() == Some(fq_iface.interface_name.clone())
370 && f.name() == method_name
371 })
372 .collect::<Vec<_>>();
373
374 if functions.is_empty() {
375 return Err(format!(
376 "function '{method_name}' not found in interface '{fq_iface}'"
377 ));
378 }
379
380 if functions.len() == 1 {
381 let (fqfn, ftype) = &functions[0];
382 Ok((
383 info.clone(),
384 Function {
385 function_name: fqfn.clone(),
386 function_type: ftype.clone(),
387 },
388 ))
389 } else {
390 search_function_in_instance(self, method_name, Some(info))
391 }
392 } else {
393 Err(format!(
394 "interface '{fq_iface}' found in multiple components. Please specify the root package name instead"
395 ))
396 }
397 }
398 },
399 None => search_function_in_instance(self, method_name, None),
400 }
401 }
402
403 pub fn resource_method_dictionary(&self) -> FunctionDictionary {
405 let name_and_types = self
406 .component_dependencies()
407 .dependencies
408 .values()
409 .flat_map(|function_dictionary| {
410 function_dictionary
411 .name_and_types
412 .iter()
413 .filter(|(f, _)| matches!(f, FunctionName::ResourceMethod(_)))
414 .map(|(f, t)| (f.clone(), t.clone()))
415 .collect::<Vec<_>>()
416 })
417 .collect();
418
419 FunctionDictionary { name_and_types }
420 }
421
422 pub fn function_dict_without_resource_methods(&self) -> FunctionDictionary {
423 let name_and_types = self
424 .component_dependencies()
425 .dependencies
426 .values()
427 .flat_map(|function_dictionary| {
428 function_dictionary
429 .name_and_types
430 .iter()
431 .filter(|(f, _)| {
432 !matches!(f, FunctionName::ResourceMethod(_))
433 && !matches!(f, FunctionName::Variant(_))
434 && !matches!(f, FunctionName::Enum(_))
435 })
436 .map(|(f, t)| (f.clone(), t.clone()))
437 .collect::<Vec<_>>()
438 })
439 .collect();
440
441 FunctionDictionary { name_and_types }
442 }
443
444 pub fn component_dependencies(&self) -> ComponentDependencies {
445 match self {
446 InstanceType::Global {
447 component_dependency,
448 ..
449 } => component_dependency.clone(),
450 InstanceType::Package {
451 component_dependency,
452 ..
453 } => component_dependency.clone(),
454 InstanceType::Interface {
455 component_dependency,
456 ..
457 } => component_dependency.clone(),
458 InstanceType::PackageInterface {
459 component_dependency,
460 ..
461 } => component_dependency.clone(),
462 InstanceType::Resource {
463 resource_method_dictionary,
464 component_dependency_key,
465 ..
466 } => {
467 let function_dictionary = FunctionDictionary::from(resource_method_dictionary);
468 let mut dependencies = BTreeMap::new();
469 dependencies.insert(component_dependency_key.clone(), function_dictionary);
470
471 ComponentDependencies { dependencies }
472 }
473 }
474 }
475
476 pub fn from(
477 dependency: &ComponentDependencies,
478 worker_name: Option<&Expr>,
479 type_parameter: Option<TypeParameter>,
480 ) -> Result<InstanceType, String> {
481 match type_parameter {
482 None => Ok(InstanceType::Global {
483 worker_name: worker_name.cloned().map(Box::new),
484 component_dependency: dependency.clone(),
485 }),
486 Some(type_parameter) => match type_parameter {
487 TypeParameter::Interface(interface_name) => {
488 let new_dependency = dependency.filter_by_interface(&interface_name)?;
489
490 Ok(InstanceType::Interface {
491 worker_name: worker_name.cloned().map(Box::new),
492 interface_name,
493 component_dependency: new_dependency,
494 })
495 }
496 TypeParameter::PackageName(package_name) => {
497 let new_dependency = dependency.filter_by_package_name(&package_name)?;
498
499 Ok(InstanceType::Package {
500 worker_name: worker_name.cloned().map(Box::new),
501 package_name,
502 component_dependency: new_dependency,
503 })
504 }
505 TypeParameter::FullyQualifiedInterface(fqi) => {
506 let component_dependency =
507 dependency.filter_by_fully_qualified_interface(&fqi)?;
508
509 Ok(InstanceType::PackageInterface {
510 worker_name: worker_name.cloned().map(Box::new),
511 package_name: fqi.package_name,
512 interface_name: fqi.interface_name,
513 component_dependency,
514 })
515 }
516 },
517 }
518 }
519}
520
521#[derive(Debug, Clone)]
522pub struct Function {
523 pub function_name: FunctionName,
524 pub function_type: FunctionType,
525}
526
527fn search_function_in_instance(
528 instance: &InstanceType,
529 function_name: &str,
530 component_info: Option<&ComponentDependencyKey>,
531) -> Result<(ComponentDependencyKey, Function), String> {
532 match component_info {
533 Some(component_info) => {
534 let dependencies = instance.component_dependencies();
535
536 let function_dictionary =
537 dependencies
538 .dependencies
539 .get(component_info)
540 .ok_or(format!(
541 "component '{component_info}' not found in dependencies"
542 ))?;
543
544 let functions = function_dictionary
545 .name_and_types
546 .iter()
547 .filter(|(f, _)| f.name() == function_name)
548 .collect::<Vec<_>>();
549
550 if functions.is_empty() {
551 return Err(format!(
552 "function '{function_name}' not found in component '{component_info}'"
553 ));
554 }
555
556 let mut package_map: HashMap<Option<PackageName>, HashSet<Option<InterfaceName>>> =
557 HashMap::new();
558
559 for (fqfn, _) in &functions {
560 package_map
561 .entry(fqfn.package_name())
562 .or_default()
563 .insert(fqfn.interface_name());
564 }
565
566 match package_map.len() {
567 1 => {
568 let interfaces = package_map.values().flatten().cloned().collect();
569 let function =
570 search_function_in_single_package(interfaces, functions, function_name)?;
571
572 Ok((component_info.clone(), function))
573 }
574 _ => {
575 let function =
576 search_function_in_multiple_packages(function_name, package_map)?;
577 Ok((component_info.clone(), function))
578 }
579 }
580 }
581 None => {
582 let mut component_info_functions = vec![];
583
584 for (info, function_dictionary) in instance.component_dependencies().dependencies.iter()
585 {
586 let functions = function_dictionary
587 .name_and_types
588 .iter()
589 .filter(|(f, _)| f.name() == function_name)
590 .collect::<Vec<_>>();
591
592 if functions.is_empty() {
593 continue;
594 }
595
596 let mut package_map: HashMap<Option<PackageName>, HashSet<Option<InterfaceName>>> =
597 HashMap::new();
598
599 for (fqfn, _) in &functions {
600 package_map
601 .entry(fqfn.package_name())
602 .or_default()
603 .insert(fqfn.interface_name());
604 }
605
606 match package_map.len() {
607 1 => {
608 let interfaces = package_map.values().flatten().cloned().collect();
609 let function = search_function_in_single_package(
610 interfaces,
611 functions,
612 function_name,
613 )?;
614
615 component_info_functions.push((info.clone(), function));
616 }
617 _ => {
618 let function =
619 search_function_in_multiple_packages(function_name, package_map)?;
620 component_info_functions.push((info.clone(), function));
621 }
622 }
623 }
624
625 if component_info_functions.len() == 1 {
626 let (info, function) = &component_info_functions[0];
627 Ok((info.clone(), function.clone()))
628 } else if component_info_functions.is_empty() {
629 Err(format!("function '{function_name}' not found"))
630 } else {
631 Err(format!(
632 "function '{function_name}' found in multiple components. Please specify the type parameter"
633 ))
634 }
635 }
636 }
637}
638
639fn search_function_in_single_package(
640 interfaces: HashSet<Option<InterfaceName>>,
641 functions: Vec<&(FunctionName, FunctionType)>,
642 function_name: &str,
643) -> Result<Function, String> {
644 if interfaces.len() == 1 {
645 let (fqfn, ftype) = &functions[0];
646 Ok(Function {
647 function_name: fqfn.clone(),
648 function_type: ftype.clone(),
649 })
650 } else {
651 let mut interfaces = interfaces
652 .into_iter()
653 .filter_map(|iface| iface.map(|i| i.name))
654 .collect::<Vec<_>>();
655
656 interfaces.sort();
657
658 Err(format!(
660 "multiple interfaces contain function '{}'. specify an interface name as type parameter from: {}",
661 function_name,
662 interfaces
663 .join(", ")
664 ))
665 }
666}
667
668fn search_function_in_multiple_packages(
669 function_name: &str,
670 package_map: HashMap<Option<PackageName>, HashSet<Option<InterfaceName>>>,
671) -> Result<Function, String> {
672 let mut error_msg = format!(
673 "function '{function_name}' exists in multiple packages. specify a package name as type parameter from: "
674 );
675
676 let mut package_interface_list = package_map
677 .into_iter()
678 .filter_map(|(pkg, interfaces)| {
679 pkg.map(|p| {
680 let mut interface_list = interfaces
681 .into_iter()
682 .filter_map(|iface| iface.map(|i| i.name))
683 .collect::<Vec<_>>();
684
685 interface_list.sort();
686
687 if interface_list.is_empty() {
688 format!("{p}")
689 } else {
690 format!("{} (interfaces: {})", p, interface_list.join(", "))
691 }
692 })
693 })
694 .collect::<Vec<_>>();
695
696 package_interface_list.sort();
697
698 error_msg.push_str(&package_interface_list.join(", "));
699 Err(error_msg)
700}
701
702#[cfg(feature = "protobuf")]
703mod protobuf {
704 use crate::{
705 FullyQualifiedFunctionName, FullyQualifiedResourceConstructor,
706 FullyQualifiedResourceMethod, InterfaceName, PackageName,
707 };
708 use golem_api_grpc::proto::golem::rib::FullyQualifiedFunctionName as ProtoFullyQualifiedFunctionName;
709 use golem_api_grpc::proto::golem::rib::FullyQualifiedResourceConstructor as ProtoFullyQualifiedResourceConstructor;
710 use golem_api_grpc::proto::golem::rib::FullyQualifiedResourceMethod as ProtoFullyQualifiedResourceMethod;
711 use golem_api_grpc::proto::golem::rib::InterfaceName as ProtoInterfaceName;
712 use golem_api_grpc::proto::golem::rib::PackageName as ProtoPackageName;
713
714 impl TryFrom<ProtoPackageName> for PackageName {
715 type Error = String;
716
717 fn try_from(proto: ProtoPackageName) -> Result<Self, Self::Error> {
718 Ok(PackageName {
719 namespace: proto.namespace,
720 package_name: proto.package_name,
721 version: proto.version,
722 })
723 }
724 }
725
726 impl TryFrom<ProtoInterfaceName> for InterfaceName {
727 type Error = String;
728
729 fn try_from(value: ProtoInterfaceName) -> Result<Self, Self::Error> {
730 Ok(InterfaceName {
731 name: value.name,
732 version: value.version,
733 })
734 }
735 }
736
737 impl TryFrom<ProtoFullyQualifiedFunctionName> for FullyQualifiedFunctionName {
738 type Error = String;
739
740 fn try_from(proto: ProtoFullyQualifiedFunctionName) -> Result<Self, Self::Error> {
741 Ok(FullyQualifiedFunctionName {
742 package_name: proto.package_name.map(TryFrom::try_from).transpose()?,
743 interface_name: proto.interface_name.map(TryFrom::try_from).transpose()?,
744 function_name: proto.function_name,
745 })
746 }
747 }
748
749 impl From<FullyQualifiedFunctionName> for ProtoFullyQualifiedFunctionName {
750 fn from(value: FullyQualifiedFunctionName) -> Self {
751 ProtoFullyQualifiedFunctionName {
752 package_name: value.package_name.map(ProtoPackageName::from),
753 interface_name: value.interface_name.map(ProtoInterfaceName::from),
754 function_name: value.function_name,
755 }
756 }
757 }
758
759 impl TryFrom<ProtoFullyQualifiedResourceMethod> for FullyQualifiedResourceMethod {
760 type Error = String;
761
762 fn try_from(proto: ProtoFullyQualifiedResourceMethod) -> Result<Self, Self::Error> {
763 Ok(FullyQualifiedResourceMethod {
764 resource_name: proto.resource_name,
765 method_name: proto.method_name,
766 package_name: proto.package_name.map(TryFrom::try_from).transpose()?,
767 interface_name: proto.interface_name.map(TryFrom::try_from).transpose()?,
768 })
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}