tetsy_wasm/elements/
func.rs

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