1use serde::Serialize;
10use tera::{Context, Tera};
11
12use crate::traits::SrcCode;
13use crate::{Generic, Generics};
14
15#[derive(Default, Serialize, Clone)]
17pub struct Function {
18 signature: FunctionSignature,
19 body: FunctionBody,
20}
21
22#[derive(Default, Serialize, Clone)]
24pub struct FunctionSignature {
25 name: String,
26 is_pub: bool,
27 is_async: bool,
28 parameters: Vec<Parameter>,
29 generics: Generics,
30 return_ty: Option<String>,
31}
32
33impl FunctionSignature {
34 pub fn new<S: ToString>(name: S) -> Self {
36 let mut f = Self::default();
37 f.name = name.to_string();
38 f
39 }
40
41 pub fn set_is_async(&mut self, is_async: bool) -> &mut Self {
43 self.is_async = is_async;
44 self
45 }
46
47 pub fn add_parameter(&mut self, param: Parameter) -> &mut Self {
49 self.parameters.push(param);
50 self
51 }
52
53 pub fn add_generic(&mut self, generic: Generic) -> &mut Self {
55 self.generics.add_generic(generic);
56 self
57 }
58
59 pub fn set_return_ty<S: ToString>(&mut self, ty: Option<S>) -> &mut Self {
61 self.return_ty = ty.map(|s| s.to_string());
62 self
63 }
64
65 pub fn set_is_pub(&mut self, is_pub: bool) -> &mut Self {
67 self.is_pub = is_pub;
68 self
69 }
70
71 pub fn set_name<S: ToString>(&mut self, name: S) -> &mut Self {
73 self.name = name.to_string();
74 self
75 }
76}
77
78impl SrcCode for FunctionSignature {
79 fn generate(&self) -> String {
80 let template = r#"
81 {% if self.is_pub %}pub {% endif %}{% if self.is_async %}async {% endif %}fn {{ self.name }}{% if has_generics %}<{{ generic_keys | join(sep=", ") }}>{% endif %}({{ parameters | join(sep=", ") }}) -> {{ return_ty }}{% if has_generics %}
82 where
83 {% for generic in generics %}{{ generic.generic }}: {{ generic.traits | join(sep=" + ") }},
84 {% endfor %}{% endif %}"#;
85 let mut context = Context::new();
86 context.insert("self", &self);
87 context.insert(
88 "return_ty",
89 &self.return_ty.as_ref().unwrap_or(&"()".to_string()),
90 );
91 context.insert("has_generics", &!self.generics.is_empty());
92 context.insert("generics", &self.generics.generics);
93 context.insert(
94 "generic_keys",
95 &self
96 .generics
97 .generics
98 .iter()
99 .map(|g| g.generic.clone())
100 .collect::<Vec<String>>(),
101 );
102 context.insert(
103 "parameters",
104 &self
105 .parameters
106 .iter()
107 .map(|param| format!("{}: {}", param.name, param.ty))
108 .collect::<Vec<String>>(),
109 );
110 Tera::one_off(template, &context, false).unwrap()
111 }
112}
113
114#[derive(Default, Serialize, Clone)]
116pub struct FunctionBody {
117 body: String,
118}
119
120impl SrcCode for FunctionBody {
121 fn generate(&self) -> String {
122 let template = r#"
123 {{ body }}
124 "#;
125 let mut ctx = Context::new();
126 ctx.insert("body", &self.body);
127 Tera::one_off(template, &ctx, false).unwrap()
128 }
129}
130
131impl<S> From<S> for FunctionBody
132where
133 S: ToString,
134{
135 fn from(body: S) -> FunctionBody {
136 FunctionBody {
137 body: body.to_string(),
138 }
139 }
140}
141
142impl Function {
143 pub fn new<S: ToString>(name: S) -> Self {
145 let mut f = Self::default();
146 f.signature.name = name.to_string();
147 f
148 }
149
150 pub fn add_parameter(&mut self, param: Parameter) -> &mut Self {
152 self.signature.parameters.push(param);
153 self
154 }
155 pub fn add_generic(&mut self, generic: Generic) -> &mut Self {
157 self.signature.generics.add_generic(generic);
158 self
159 }
160 pub fn set_return_ty<S: ToString>(&mut self, ty: S) -> &mut Self {
162 self.signature.return_ty = Some(ty.to_string());
163 self
164 }
165 pub fn set_is_pub(&mut self, is_pub: bool) -> &mut Self {
167 self.signature.set_is_pub(is_pub);
168 self
169 }
170 pub fn set_is_async(&mut self, is_async: bool) -> &mut Self {
172 self.signature.set_is_async(is_async);
173 self
174 }
175 pub fn set_body<S: Into<FunctionBody>>(&mut self, body: S) -> &mut Self {
177 self.body = body.into();
178 self
179 }
180}
181
182#[derive(Serialize, Default, Clone)]
184pub struct Parameter {
185 name: String,
186 ty: String,
187}
188impl Parameter {
189 pub fn new<S: ToString>(name: S, ty: S) -> Self {
202 Self {
203 name: name.to_string(),
204 ty: ty.to_string(),
205 }
206 }
207}
208
209impl SrcCode for Parameter {
210 fn generate(&self) -> String {
211 let template = "{{ self.name }}: {{ self.ty }}";
212 let mut ctx = Context::new();
213 ctx.insert("self", &self);
214 Tera::one_off(template, &ctx, false).unwrap()
215 }
216}
217
218impl SrcCode for Function {
219 fn generate(&self) -> String {
220 let template = r#"
221 {{ function_signature }}
222 {
223 {{ body }}
224 }
225 "#;
226 let mut context = Context::new();
227 context.insert("body", &self.body.generate());
228 context.insert("function_signature", &self.signature.generate());
229 Tera::one_off(template, &context, false).unwrap()
230 }
231}