parity_wasm/builder/
code.rs

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