xwasm/elements/
func.rs

1use io;
2use std::vec::Vec;
3use super::{
4	Deserialize, Error, ValueType, VarUint32, CountedList, Instructions,
5	Serialize, CountedWriter, CountedListWriter,
6};
7use elements::section::SectionReader;
8
9/// Function signature (type reference)
10#[derive(Debug, Copy, Clone, PartialEq)]
11pub struct Func(u32);
12
13impl Func {
14	/// New function signature
15	pub fn new(type_ref: u32) -> Self { Func(type_ref) }
16
17	/// Function signature type reference.
18	pub fn type_ref(&self) -> u32 {
19		self.0
20	}
21
22	/// Function signature type reference (mutable).
23	pub fn type_ref_mut(&mut self) -> &mut u32 {
24		&mut self.0
25	}
26}
27
28impl Serialize for Func {
29	type Error = Error;
30
31	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
32		VarUint32::from(self.0).serialize(writer)
33	}
34}
35
36impl Deserialize for Func {
37	 type Error = Error;
38
39	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
40		Ok(Func(VarUint32::deserialize(reader)?.into()))
41	}
42}
43
44/// Local definition inside the function body.
45#[derive(Debug, Copy, Clone, PartialEq)]
46pub struct Local {
47	count: u32,
48	value_type: ValueType,
49}
50
51impl Local {
52	/// New local with `count` and `value_type`.
53	pub fn new(count: u32, value_type: ValueType) -> Self {
54		Local { count: count, value_type: value_type }
55	}
56
57	/// Number of locals with the shared type.
58	pub fn count(&self) -> u32 { self.count }
59
60	/// Type of the locals.
61	pub fn value_type(&self) -> ValueType { self.value_type }
62}
63
64impl Deserialize for Local {
65	 type Error = Error;
66
67	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
68		let count = VarUint32::deserialize(reader)?;
69		let value_type = ValueType::deserialize(reader)?;
70		Ok(Local { count: count.into(), value_type: value_type })
71	}
72}
73
74impl Serialize for Local {
75	type Error = Error;
76
77	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
78		VarUint32::from(self.count).serialize(writer)?;
79		self.value_type.serialize(writer)?;
80		Ok(())
81	}
82}
83
84/// Function body definition.
85#[derive(Debug, Clone, PartialEq)]
86pub struct FuncBody {
87	locals: Vec<Local>,
88	instructions: Instructions,
89}
90
91impl FuncBody {
92	/// New function body with given `locals` and `instructions`
93	pub fn new(locals: Vec<Local>, instructions: Instructions) -> Self {
94		FuncBody { locals: locals, instructions: instructions }
95	}
96
97	/// List of individual instructions
98	pub fn empty() -> Self {
99		FuncBody { locals: Vec::new(), instructions: Instructions::empty() }
100	}
101
102	/// Locals declared in function body.
103	pub fn locals(&self) -> &[Local] { &self.locals }
104
105	/// Instruction list of the function body. Minimal instruction list
106	/// is just `&[Instruction::End]`
107	pub fn code(&self) -> &Instructions { &self.instructions }
108
109	/// Locals declared in function body (mutable).
110	pub fn locals_mut(&mut self) -> &mut Vec<Local> { &mut self.locals }
111
112	/// Instruction list of the function body (mutable).
113	pub fn code_mut(&mut self) -> &mut Instructions { &mut self.instructions }
114}
115
116impl Deserialize for FuncBody {
117	 type Error = Error;
118
119	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
120		// todo: maybe use reader.take(section_length)
121		let mut body_reader = SectionReader::new(reader)?;
122		let locals: Vec<Local> = CountedList::<Local>::deserialize(&mut body_reader)?.into_inner();
123		let instructions = Instructions::deserialize(&mut body_reader)?;
124		body_reader.close()?;
125		Ok(FuncBody { locals: locals, instructions: instructions })
126	}
127}
128
129impl Serialize for FuncBody {
130	type Error = Error;
131
132	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
133		let mut counted_writer = CountedWriter::new(writer);
134
135		let data = self.locals;
136		let counted_list = CountedListWriter::<Local, _>(
137			data.len(),
138			data.into_iter().map(Into::into),
139		);
140		counted_list.serialize(&mut counted_writer)?;
141
142		let code = self.instructions;
143		code.serialize(&mut counted_writer)?;
144
145		counted_writer.done()?;
146
147		Ok(())
148	}
149}