parity_wasm/elements/
func.rs

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