tetsy_wasm/builder/
code.rs

1use alloc::vec::Vec;
2use crate::elements;
3use super::{
4	invoke::{Invoke, Identity},
5	misc::{ValueTypeBuilder, ValueTypesBuilder},
6};
7
8/// Signature template description
9pub enum Signature {
10	TypeReference(u32),
11	Inline(elements::FunctionType),
12}
13
14/// Signature builder
15pub struct SignatureBuilder<F=Identity> {
16	callback: F,
17	signature: elements::FunctionType,
18}
19
20impl SignatureBuilder {
21	/// New signature builder
22	pub fn new() -> Self {
23		SignatureBuilder::with_callback(Identity)
24	}
25}
26
27impl<F> SignatureBuilder<F> where F: Invoke<elements::FunctionType> {
28	/// New builder with callback function specified
29	pub fn with_callback(callback: F) -> Self {
30		SignatureBuilder {
31			callback: callback,
32			signature: elements::FunctionType::default(),
33		}
34	}
35
36	/// Add argument to signature builder
37	pub fn with_param(mut self, value_type: elements::ValueType) -> Self {
38		self.signature.params_mut().push(value_type);
39		self
40	}
41
42	/// Add multiple arguments to signature builder
43	pub fn with_params(mut self, value_types: Vec<elements::ValueType>) -> Self {
44		self.signature.params_mut().extend(value_types);
45		self
46	}
47
48	/// Start build new argument
49	pub fn param(self) -> ValueTypeBuilder<Self> {
50		ValueTypeBuilder::with_callback(self)
51	}
52
53	/// Start build multiple arguments
54	pub fn params(self) -> ValueTypesBuilder<Self> {
55		ValueTypesBuilder::with_callback(self)
56	}
57
58	/// Add result to signature builder
59	pub fn with_result(mut self, value_type: elements::ValueType) -> Self {
60		self.signature.results_mut().push(value_type);
61		self
62	}
63
64	/// Add multiple results to signature builder
65	pub fn with_results(mut self, value_types: Vec<elements::ValueType>) -> Self {
66		self.signature.results_mut().extend(value_types);
67		self
68	}
69
70	/// Start building new result
71	pub fn result(self) -> ValueTypeBuilder<Self> {
72		ValueTypeBuilder::with_callback(self)
73	}
74
75	/// Start building multiple results
76	pub fn results(self) -> ValueTypeBuilder<Self> {
77		ValueTypeBuilder::with_callback(self)
78	}
79
80	/// Finish current builder
81	pub fn build(self) -> F::Result {
82		self.callback.invoke(self.signature)
83	}
84
85	/// Finish current builder returning intermediate `Signature` struct
86	pub fn build_sig(self) -> Signature {
87		Signature::Inline(self.signature)
88	}
89}
90
91impl<F> Invoke<Vec<elements::ValueType>> for SignatureBuilder<F>
92	where F: Invoke<elements::FunctionType>
93{
94	type Result = Self;
95
96	fn invoke(self, args: Vec<elements::ValueType>) -> Self {
97		self.with_params(args)
98	}
99}
100
101impl<F> Invoke<elements::ValueType> for SignatureBuilder<F>
102	where F: Invoke<elements::FunctionType>
103{
104	type Result = Self;
105
106	fn invoke(self, arg: elements::ValueType) -> Self {
107		self.with_result(arg)
108	}
109}
110
111/// Type (signature) reference builder (for function/import/indirect call)
112pub struct TypeRefBuilder<F=Identity> {
113	callback: F,
114	type_ref: u32,
115}
116
117impl<F> TypeRefBuilder<F> where F: Invoke<u32> {
118	/// New builder chained with specified callback
119	pub fn with_callback(callback: F) -> Self {
120		TypeRefBuilder {
121			callback: callback,
122			type_ref: 0
123		}
124	}
125
126	/// Set/override of type reference
127	pub fn val(mut self, val: u32) -> Self {
128		self.type_ref = val;
129		self
130	}
131
132	/// Finish current builder
133	pub fn build(self) -> F::Result { self.callback.invoke(self.type_ref) }
134}
135
136/// Multiple signatures builder
137pub struct SignaturesBuilder<F=Identity> {
138	callback: F,
139	section: Vec<Signature>,
140}
141
142impl SignaturesBuilder {
143	/// New empty functions section builder
144	pub fn new() -> Self {
145		SignaturesBuilder::with_callback(Identity)
146	}
147}
148
149impl<F> SignaturesBuilder<F> {
150	/// New builder chained with specified callback
151	pub fn with_callback(callback: F) -> Self {
152		SignaturesBuilder {
153			callback: callback,
154			section: Vec::new(),
155		}
156	}
157
158	/// Push new signature into the builder output
159	pub fn with_signature(mut self, signature: Signature) -> Self {
160		self.section.push(signature);
161		self
162	}
163
164	/// Start building new signature with `TypeRefBuilder`
165	pub fn type_ref(self) -> TypeRefBuilder<Self> {
166		TypeRefBuilder::with_callback(self)
167	}
168}
169
170impl<F> SignaturesBuilder<F> where F: Invoke<SignatureBindings> {
171	/// Start building new signature with dedicated builder
172	pub fn signature(self) -> SignatureBuilder<Self> {
173		SignatureBuilder::with_callback(self)
174	}
175}
176
177impl<F> Invoke<elements::FunctionType> for SignaturesBuilder<F> {
178	type Result = Self;
179
180	fn invoke(self, signature: elements::FunctionType) -> Self {
181		self.with_signature(Signature::Inline(signature))
182	}
183}
184
185impl<F> Invoke<u32> for SignaturesBuilder<F> {
186	type Result = Self;
187
188	fn invoke(self, type_ref: u32) -> Self {
189		self.with_signature(Signature::TypeReference(type_ref))
190	}
191}
192
193impl<F> SignaturesBuilder<F> where F: Invoke<elements::FunctionSection> {
194
195	/// Finalize builder spawning element
196	pub fn build(self) -> F::Result {
197		let mut result = elements::FunctionSection::default();
198		for f in self.section.into_iter() {
199			if let Signature::TypeReference(type_ref) = f {
200				result.entries_mut().push(elements::Func::new(type_ref));
201			} else {
202				unreachable!(); // never possible with current generics impl-s
203			}
204		}
205		self.callback.invoke(result)
206	}
207}
208
209/// Signature bindings
210pub type SignatureBindings = Vec<Signature>;
211
212impl<F> SignaturesBuilder<F> where F: Invoke<SignatureBindings> {
213	/// Bind signature list
214	pub fn bind(self) -> F::Result {
215		self.callback.invoke(self.section)
216	}
217}
218
219/// Function body (code) builder
220pub struct FuncBodyBuilder<F=Identity> {
221	callback: F,
222	body: elements::FuncBody,
223}
224
225impl<F> FuncBodyBuilder<F> {
226	/// New body (code) builder given the chain callback
227	pub fn with_callback(callback: F) -> Self {
228		FuncBodyBuilder {
229			callback: callback,
230			body: elements::FuncBody::new(Vec::new(), elements::Instructions::empty()),
231		}
232	}
233}
234
235impl<F> FuncBodyBuilder<F> where F: Invoke<elements::FuncBody> {
236	/// Set/override entirely with FuncBody struct
237	pub fn with_func(mut self, func: elements::FuncBody) -> Self {
238		self.body = func;
239		self
240	}
241
242	/// Extend function local list with new entries
243	pub fn with_locals(mut self, locals: Vec<elements::Local>) -> Self {
244		self.body.locals_mut().extend(locals);
245		self
246	}
247
248	/// Set code of the function
249	pub fn with_instructions(mut self, instructions: elements::Instructions) -> Self {
250		*self.body.code_mut() = instructions;
251		self
252	}
253
254	/// Finish current builder spawning resulting struct
255	pub fn build(self) -> F::Result {
256		self.callback.invoke(self.body)
257	}
258}
259
260/// Function definition (extended structure to specify function entirely, incl. signature, mainness and code)
261pub struct FunctionDefinition {
262	/// Is this function is start function
263	pub is_main: bool,
264	/// Signature description
265	pub signature: Signature,
266	/// Body (code) of the function
267	pub code: elements::FuncBody,
268}
269
270impl Default for FunctionDefinition {
271	fn default() -> Self {
272		FunctionDefinition {
273			is_main: false,
274			signature: Signature::TypeReference(0),
275			code: elements::FuncBody::empty(),
276		}
277	}
278}
279
280/// Function definition builder
281pub struct FunctionBuilder<F=Identity> {
282	callback: F,
283	func: FunctionDefinition,
284}
285
286impl FunctionBuilder {
287	/// New function builder
288	pub fn new() -> Self {
289		FunctionBuilder::with_callback(Identity)
290	}
291}
292
293impl<F> FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
294	/// New function builder with chained callback
295	pub fn with_callback(callback: F) -> Self {
296		FunctionBuilder {
297			callback: callback,
298			func: Default::default(),
299		}
300	}
301
302	/// Set that this function is main entry point
303	pub fn main(mut self) -> Self {
304		self.func.is_main = true;
305		self
306	}
307
308	/// Start signature builder of the function
309	pub fn signature(self) -> SignatureBuilder<Self> {
310		SignatureBuilder::with_callback(self)
311	}
312
313	/// Override current signature entirely with new one from known struct
314	pub fn with_signature(mut self, signature: Signature) -> Self {
315		self.func.signature = signature;
316		self
317	}
318
319	/// Start code (body) builder
320	pub fn body(self) -> FuncBodyBuilder<Self> {
321		FuncBodyBuilder::with_callback(self)
322	}
323
324	/// Set body (code) for this function
325	pub fn with_body(mut self, body: elements::FuncBody) -> Self {
326		self.func.code = body;
327		self
328	}
329
330	/// Finalize current builder spawning resulting struct in the callback
331	pub fn build(self) -> F::Result {
332		self.callback.invoke(self.func)
333	}
334}
335
336impl<F> Invoke<elements::FunctionType> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
337	type Result = Self;
338
339	fn invoke(self, signature: elements::FunctionType) -> Self {
340		self.with_signature(Signature::Inline(signature))
341	}
342}
343
344impl<F> Invoke<u32> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
345	type Result = Self;
346
347	fn invoke(self, type_ref: u32) -> Self {
348		self.with_signature(Signature::TypeReference(type_ref))
349	}
350}
351
352impl<F> Invoke<elements::FuncBody> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
353	type Result = Self;
354
355	fn invoke(self, body: elements::FuncBody) -> Self::Result {
356		self.with_body(body)
357	}
358}
359
360/// New builder of signature list
361pub fn signatures() -> SignaturesBuilder {
362	SignaturesBuilder::new()
363}
364
365/// New signature builder
366pub fn signature() -> SignatureBuilder {
367	SignatureBuilder::new()
368}
369
370/// New builder of function (signature & body)
371pub fn function() -> FunctionBuilder {
372	FunctionBuilder::new()
373}
374
375#[cfg(test)]
376mod tests {
377
378	use super::{signatures, function};
379	use crate::elements;
380
381	#[test]
382	fn example() {
383		let result = signatures()
384			.type_ref().val(1).build()
385			.build();
386
387		assert_eq!(result.entries().len(), 1);
388
389		let result = signatures()
390			.signature()
391				.param().i32()
392				.param().i32()
393				.result().i64()
394				.build()
395			.bind();
396
397		assert_eq!(result.len(), 1);
398	}
399
400	#[test]
401	fn func_example() {
402		let func = function()
403			.signature()
404				.param().i32()
405				.result().i32()
406				.build()
407			.body()
408				.with_instructions(elements::Instructions::empty())
409				.build()
410			.build();
411
412		assert_eq!(func.code.locals().len(), 0);
413		assert_eq!(func.code.code().elements().len(), 1);
414	}
415
416	#[test]
417	fn func_example_multi_result() {
418		let func = function()
419			.signature()
420			.param().i32()
421			.result().i32()
422			.result().i32()
423			.build()
424			.body()
425			.with_instructions(elements::Instructions::empty())
426			.build()
427			.build();
428
429		assert_eq!(func.code.locals().len(), 0);
430		assert_eq!(func.code.code().elements().len(), 1);
431	}
432}