golem_scalajs_wit_bindgen/codegen/
function.rs1use std::fmt::Display;
16
17use color_eyre::Result;
18use convert_case::{Case, Casing};
19use wit_parser::{Function as WitFunction, Results as WitResults, Type as WitType};
20
21use super::Render;
22use crate::types::{Type, TypeMap};
23
24struct ParamName(String);
26
27impl Display for ParamName {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 write!(f, "{}", self.0)
30 }
31}
32
33impl From<String> for ParamName {
34 fn from(name: String) -> Self {
35 Self(name.to_case(Case::Camel))
36 }
37}
38
39struct Param {
41 name: ParamName,
43
44 ty: Type,
46}
47
48impl Param {
49 pub fn from_wit(name: String, ty: WitType, type_map: &TypeMap) -> Result<Self> {
51 Ok(Self {
52 name: ParamName::from(name),
53 ty: Type::from_wit(ty, type_map)?,
54 })
55 }
56}
57
58#[derive(Clone)]
60struct FunctionName(String);
61
62impl Display for FunctionName {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 write!(f, "{}", self.0)
65 }
66}
67
68impl From<String> for FunctionName {
69 fn from(name: String) -> Self {
70 Self(name.to_case(Case::Camel))
71 }
72}
73
74pub struct Function {
76 name: FunctionName,
78
79 params: Vec<Param>,
81
82 outs: Vec<Type>,
84}
85
86impl Function {
87 pub fn from_wit(function: WitFunction, type_map: &TypeMap) -> Result<Self> {
89 let params: Result<Vec<Param>> = function
90 .params
91 .into_iter()
92 .map(|(name, ty)| Param::from_wit(name, ty, type_map))
93 .collect();
94
95 let outs: Result<Vec<Type>> = match function.results {
96 WitResults::Named(params) => params
97 .iter()
98 .map(|(_, ty)| Type::from_wit(*ty, type_map))
99 .collect(),
100 WitResults::Anon(ty) => Type::from_wit(ty, type_map).map(|ty| vec![ty]),
101 };
102
103 Ok(Self {
104 name: FunctionName::from(function.name),
105 params: params?,
106 outs: outs?,
107 })
108 }
109}
110
111impl Render for Function {
112 fn render(self) -> Result<String> {
113 let params = self
114 .params
115 .iter()
116 .map(|Param { name, ty }| format!("{name}: {ty}"))
117 .collect::<Vec<_>>()
118 .join(", ");
119
120 let out = {
121 let outs = self.outs.iter().map(Type::to_string).collect::<Vec<_>>();
122
123 if outs.is_empty() {
124 "Unit".to_owned()
125 } else if outs.len() == 1 {
126 outs.first().unwrap().clone()
127 } else {
128 format!("({})", outs.join(", "))
129 }
130 };
131
132 let name = self.name;
133
134 Ok(format!("def {name}({params}): {out}"))
135 }
136}