tetsy_wasm/elements/
segment.rs

1use alloc::vec::Vec;
2use crate::io;
3use super::{Deserialize, Serialize, Error, VarUint32, CountedList, InitExpr, CountedListWriter};
4
5#[cfg(feature="bulk")]
6const FLAG_MEMZERO: u32 = 0;
7#[cfg(feature="bulk")]
8const FLAG_PASSIVE: u32 = 1;
9#[cfg(feature="bulk")]
10const FLAG_MEM_NONZERO: u32 = 2;
11
12/// Entry in the element section.
13#[derive(Debug, Clone, PartialEq)]
14pub struct ElementSegment {
15	index: u32,
16	offset: Option<InitExpr>,
17	members: Vec<u32>,
18
19	#[cfg(feature="bulk")]
20	passive: bool,
21}
22
23impl ElementSegment {
24	/// New element segment.
25	pub fn new(index: u32, offset: Option<InitExpr>, members: Vec<u32>) -> Self {
26		ElementSegment {
27			index: index,
28			offset: offset,
29			members: members,
30
31			#[cfg(feature="bulk")]
32			passive: false,
33		}
34	}
35
36	/// Sequence of function indices.
37	pub fn members(&self) -> &[u32] { &self.members }
38
39	/// Sequence of function indices (mutable)
40	pub fn members_mut(&mut self) -> &mut Vec<u32> { &mut self.members }
41
42	/// Table index (currently valid only value of `0`)
43	pub fn index(&self) -> u32 { self.index }
44
45	/// An i32 initializer expression that computes the offset at which to place the elements.
46	///
47	/// Note that this return `None` if the segment is `passive`.
48	pub fn offset(&self) -> &Option<InitExpr> { &self.offset }
49
50	/// An i32 initializer expression that computes the offset at which to place the elements (mutable)
51	///
52	/// Note that this return `None` if the segment is `passive`.
53	pub fn offset_mut(&mut self) -> &mut Option<InitExpr> { &mut self.offset }
54}
55
56#[cfg(feature="bulk")]
57impl ElementSegment {
58	/// Whether or not this table segment is "passive"
59	pub fn passive(&self) -> bool { self.passive }
60
61	/// Whether or not this table segment is "passive"
62	pub fn passive_mut(&mut self) -> &mut bool { &mut self.passive }
63
64	/// Set whether or not this table segment is "passive"
65	pub fn set_passive(&mut self, passive: bool) {
66		self.passive = passive;
67	}
68}
69
70impl Deserialize for ElementSegment {
71	type Error = Error;
72
73	#[cfg(not(feature="bulk"))]
74	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
75		let index: u32 = VarUint32::deserialize(reader)?.into();
76		let offset = InitExpr::deserialize(reader)?;
77		let members: Vec<u32> = CountedList::<VarUint32>::deserialize(reader)?
78			.into_inner()
79			.into_iter()
80			.map(Into::into)
81			.collect();
82
83		Ok(ElementSegment {
84			index,
85			offset: Some(offset),
86			members,
87		})
88	}
89
90	#[cfg(feature="bulk")]
91	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
92		// This piece of data was treated as `index` [of the table], but was repurposed
93		// for flags in bulk-memory operations proposal.
94		let flags: u32 = VarUint32::deserialize(reader)?.into();
95		let index = if flags == FLAG_MEMZERO || flags == FLAG_PASSIVE {
96			0u32
97		} else if flags == FLAG_MEM_NONZERO {
98			VarUint32::deserialize(reader)?.into()
99		} else {
100			return Err(Error::InvalidSegmentFlags(flags))
101		};
102		let offset = if flags == FLAG_PASSIVE {
103			None
104		} else {
105			Some(InitExpr::deserialize(reader)?)
106		};
107
108		let funcs: Vec<u32> = CountedList::<VarUint32>::deserialize(reader)?
109			.into_inner()
110			.into_iter()
111			.map(Into::into)
112			.collect();
113
114		Ok(ElementSegment {
115			index: index,
116			offset: offset,
117			members: funcs,
118			passive: flags == FLAG_PASSIVE,
119		})
120	}
121}
122
123impl Serialize for ElementSegment {
124	type Error = Error;
125
126	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
127		#[cfg(feature="bulk")]
128		{
129			if self.passive {
130				VarUint32::from(FLAG_PASSIVE).serialize(writer)?;
131			} else if self.index != 0 {
132				VarUint32::from(FLAG_MEM_NONZERO).serialize(writer)?;
133				VarUint32::from(self.index).serialize(writer)?;
134			} else {
135				VarUint32::from(FLAG_MEMZERO).serialize(writer)?;
136			}
137		}
138		#[cfg(not(feature="bulk"))]
139		VarUint32::from(self.index).serialize(writer)?;
140
141		if let Some(offset) = self.offset {
142			offset.serialize(writer)?;
143		}
144		let data = self.members;
145		let counted_list = CountedListWriter::<VarUint32, _>(
146			data.len(),
147			data.into_iter().map(Into::into),
148		);
149		counted_list.serialize(writer)?;
150		Ok(())
151	}
152}
153
154/// Data segment definition.
155#[derive(Clone, Debug, PartialEq)]
156pub struct DataSegment {
157	index: u32,
158	offset: Option<InitExpr>,
159	value: Vec<u8>,
160
161	#[cfg(feature="bulk")]
162	passive: bool,
163}
164
165impl DataSegment {
166	/// New data segments.
167	pub fn new(index: u32, offset: Option<InitExpr>, value: Vec<u8>) -> Self {
168		DataSegment {
169			index: index,
170			offset: offset,
171			value: value,
172
173			#[cfg(feature="bulk")]
174			passive: false,
175		}
176	}
177
178	/// Linear memory index (currently the only valid value is `0`).
179	pub fn index(&self) -> u32 { self.index }
180
181	/// An i32 initializer expression that computes the offset at which to place the data.
182	///
183	/// Note that this return `None` if the segment is `passive`.
184	pub fn offset(&self) -> &Option<InitExpr> { &self.offset }
185
186	/// An i32 initializer expression that computes the offset at which to place the data (mutable)
187	///
188	/// Note that this return `None` if the segment is `passive`.
189	pub fn offset_mut(&mut self) -> &mut Option<InitExpr> { &mut self.offset }
190
191	/// Initial value of the data segment.
192	pub fn value(&self) -> &[u8] { &self.value }
193
194	/// Initial value of the data segment (mutable).
195	pub fn value_mut(&mut self) -> &mut Vec<u8> { &mut self.value }
196}
197
198#[cfg(feature="bulk")]
199impl DataSegment {
200	/// Whether or not this data segment is "passive".
201	pub fn passive(&self) -> bool { self.passive }
202
203	/// Whether or not this data segment is "passive" (mutable).
204	pub fn passive_mut(&mut self) -> &mut bool { &mut self.passive }
205
206	/// Set whether or not this table segment is "passive"
207	pub fn set_passive(&mut self, passive: bool) {
208		self.passive = passive;
209	}
210}
211
212impl Deserialize for DataSegment {
213	type Error = Error;
214
215	#[cfg(not(feature="bulk"))]
216	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
217		let index = VarUint32::deserialize(reader)?;
218		let offset = InitExpr::deserialize(reader)?;
219		let value_len = u32::from(VarUint32::deserialize(reader)?) as usize;
220		let value_buf = buffered_read!(65536, value_len, reader);
221
222		Ok(DataSegment {
223			index: index.into(),
224			offset: Some(offset),
225			value: value_buf,
226		})
227	}
228
229	#[cfg(feature="bulk")]
230	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
231		let flags: u32 = VarUint32::deserialize(reader)?.into();
232		let index = if flags == FLAG_MEMZERO || flags == FLAG_PASSIVE {
233			0u32
234		} else if flags == FLAG_MEM_NONZERO {
235			VarUint32::deserialize(reader)?.into()
236		} else {
237			return Err(Error::InvalidSegmentFlags(flags))
238		};
239		let offset = if flags == FLAG_PASSIVE {
240			None
241		} else {
242			Some(InitExpr::deserialize(reader)?)
243		};
244		let value_len = u32::from(VarUint32::deserialize(reader)?) as usize;
245		let value_buf = buffered_read!(65536, value_len, reader);
246
247		Ok(DataSegment {
248			index: index,
249			offset: offset,
250			value: value_buf,
251			passive: flags == FLAG_PASSIVE,
252		})
253	}
254}
255
256impl Serialize for DataSegment {
257	type Error = Error;
258
259	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
260		#[cfg(feature="bulk")]
261		{
262			if self.passive {
263				VarUint32::from(FLAG_PASSIVE).serialize(writer)?;
264			} else if self.index != 0 {
265				VarUint32::from(FLAG_MEM_NONZERO).serialize(writer)?;
266				VarUint32::from(self.index).serialize(writer)?;
267			} else {
268				VarUint32::from(FLAG_MEMZERO).serialize(writer)?;
269			}
270		}
271		#[cfg(not(feature="bulk"))]
272		VarUint32::from(self.index).serialize(writer)?;
273
274		if let Some(offset) = self.offset {
275			offset.serialize(writer)?;
276		}
277
278		let value = self.value;
279		VarUint32::from(value.len()).serialize(writer)?;
280		writer.write(&value[..])?;
281		Ok(())
282	}
283}