susywasm/builder/
code.rs

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