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