parity_wasm/elements/
import_entry.rs

1use super::{
2	Deserialize, Error, Serialize, TableElementType, Uint8, ValueType, VarInt7, VarUint1,
3	VarUint32, VarUint7,
4};
5use crate::io;
6use alloc::string::String;
7
8const FLAG_HAS_MAX: u8 = 0x01;
9#[cfg(feature = "atomics")]
10const FLAG_SHARED: u8 = 0x02;
11
12/// Global definition struct
13#[derive(Debug, Copy, Clone, PartialEq)]
14pub struct GlobalType {
15	content_type: ValueType,
16	is_mutable: bool,
17}
18
19impl GlobalType {
20	/// New global type
21	pub fn new(content_type: ValueType, is_mutable: bool) -> Self {
22		GlobalType { content_type, is_mutable }
23	}
24
25	/// Type of the global entry
26	pub fn content_type(&self) -> ValueType {
27		self.content_type
28	}
29
30	/// Is global entry is declared as mutable
31	pub fn is_mutable(&self) -> bool {
32		self.is_mutable
33	}
34}
35
36impl Deserialize for GlobalType {
37	type Error = Error;
38
39	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
40		let content_type = ValueType::deserialize(reader)?;
41		let is_mutable = VarUint1::deserialize(reader)?;
42		Ok(GlobalType { content_type, is_mutable: is_mutable.into() })
43	}
44}
45
46impl Serialize for GlobalType {
47	type Error = Error;
48
49	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
50		self.content_type.serialize(writer)?;
51		VarUint1::from(self.is_mutable).serialize(writer)?;
52		Ok(())
53	}
54}
55
56/// Table entry
57#[derive(Debug, Copy, Clone, PartialEq)]
58pub struct TableType {
59	elem_type: TableElementType,
60	limits: ResizableLimits,
61}
62
63impl TableType {
64	/// New table definition
65	pub fn new(min: u32, max: Option<u32>) -> Self {
66		TableType { elem_type: TableElementType::AnyFunc, limits: ResizableLimits::new(min, max) }
67	}
68
69	/// Table memory specification
70	pub fn limits(&self) -> &ResizableLimits {
71		&self.limits
72	}
73
74	/// Table element type
75	pub fn elem_type(&self) -> TableElementType {
76		self.elem_type
77	}
78}
79
80impl Deserialize for TableType {
81	type Error = Error;
82
83	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
84		let elem_type = TableElementType::deserialize(reader)?;
85		let limits = ResizableLimits::deserialize(reader)?;
86		Ok(TableType { elem_type, limits })
87	}
88}
89
90impl Serialize for TableType {
91	type Error = Error;
92
93	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
94		self.elem_type.serialize(writer)?;
95		self.limits.serialize(writer)
96	}
97}
98
99/// Memory and table limits.
100#[derive(Debug, Copy, Clone, PartialEq)]
101pub struct ResizableLimits {
102	initial: u32,
103	maximum: Option<u32>,
104	#[cfg(feature = "atomics")]
105	shared: bool,
106}
107
108impl ResizableLimits {
109	/// New memory limits definition.
110	pub fn new(min: u32, max: Option<u32>) -> Self {
111		ResizableLimits {
112			initial: min,
113			maximum: max,
114			#[cfg(feature = "atomics")]
115			shared: false,
116		}
117	}
118	/// Initial size.
119	pub fn initial(&self) -> u32 {
120		self.initial
121	}
122	/// Maximum size.
123	pub fn maximum(&self) -> Option<u32> {
124		self.maximum
125	}
126
127	#[cfg(feature = "atomics")]
128	/// Whether or not this is a shared array buffer.
129	pub fn shared(&self) -> bool {
130		self.shared
131	}
132}
133
134impl Deserialize for ResizableLimits {
135	type Error = Error;
136
137	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
138		let flags: u8 = Uint8::deserialize(reader)?.into();
139		match flags {
140			// Default flags are always supported. This is simply: FLAG_HAS_MAX={true, false}.
141			0x00 | 0x01 => {},
142
143			// Atomics proposal introduce FLAG_SHARED (0x02). Shared memories can be used only
144			// together with FLAG_HAS_MAX (0x01), hence 0x03.
145			#[cfg(feature = "atomics")]
146			0x03 => {},
147
148			_ => return Err(Error::InvalidLimitsFlags(flags)),
149		}
150
151		let initial = VarUint32::deserialize(reader)?;
152		let maximum = if flags & FLAG_HAS_MAX != 0 {
153			Some(VarUint32::deserialize(reader)?.into())
154		} else {
155			None
156		};
157
158		Ok(ResizableLimits {
159			initial: initial.into(),
160			maximum,
161
162			#[cfg(feature = "atomics")]
163			shared: flags & FLAG_SHARED != 0,
164		})
165	}
166}
167
168impl Serialize for ResizableLimits {
169	type Error = Error;
170
171	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
172		let mut flags: u8 = 0;
173		if self.maximum.is_some() {
174			flags |= FLAG_HAS_MAX;
175		}
176
177		#[cfg(feature = "atomics")]
178		{
179			// If the atomics feature is enabled and if the shared flag is set, add logically
180			// it to the flags.
181			if self.shared {
182				flags |= FLAG_SHARED;
183			}
184		}
185		Uint8::from(flags).serialize(writer)?;
186		VarUint32::from(self.initial).serialize(writer)?;
187		if let Some(max) = self.maximum {
188			VarUint32::from(max).serialize(writer)?;
189		}
190		Ok(())
191	}
192}
193
194/// Memory entry.
195#[derive(Debug, Copy, Clone, PartialEq)]
196pub struct MemoryType(ResizableLimits);
197
198impl MemoryType {
199	/// New memory definition
200	pub fn new(min: u32, max: Option<u32>) -> Self {
201		let r = ResizableLimits::new(min, max);
202		MemoryType(r)
203	}
204
205	/// Set the `shared` flag that denotes a memory that can be shared between threads.
206	///
207	/// `false` by default. This is only available if the `atomics` feature is enabled.
208	#[cfg(feature = "atomics")]
209	pub fn set_shared(&mut self, shared: bool) {
210		self.0.shared = shared;
211	}
212
213	/// Limits of the memory entry.
214	pub fn limits(&self) -> &ResizableLimits {
215		&self.0
216	}
217}
218
219impl Deserialize for MemoryType {
220	type Error = Error;
221
222	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
223		Ok(MemoryType(ResizableLimits::deserialize(reader)?))
224	}
225}
226
227impl Serialize for MemoryType {
228	type Error = Error;
229
230	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
231		self.0.serialize(writer)
232	}
233}
234
235/// External to local binding.
236#[derive(Debug, Copy, Clone, PartialEq)]
237pub enum External {
238	/// Binds to a function whose type is associated with the given index in the
239	/// type section.
240	Function(u32),
241	/// Describes local table definition to be imported as.
242	Table(TableType),
243	/// Describes local memory definition to be imported as.
244	Memory(MemoryType),
245	/// Describes local global entry to be imported as.
246	Global(GlobalType),
247}
248
249impl Deserialize for External {
250	type Error = Error;
251
252	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
253		let kind = VarUint7::deserialize(reader)?;
254		match kind.into() {
255			0x00 => Ok(External::Function(VarUint32::deserialize(reader)?.into())),
256			0x01 => Ok(External::Table(TableType::deserialize(reader)?)),
257			0x02 => Ok(External::Memory(MemoryType::deserialize(reader)?)),
258			0x03 => Ok(External::Global(GlobalType::deserialize(reader)?)),
259			_ => Err(Error::UnknownExternalKind(kind.into())),
260		}
261	}
262}
263
264impl Serialize for External {
265	type Error = Error;
266
267	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
268		use self::External::*;
269
270		match self {
271			Function(index) => {
272				VarUint7::from(0x00).serialize(writer)?;
273				VarUint32::from(index).serialize(writer)?;
274			},
275			Table(tt) => {
276				VarInt7::from(0x01).serialize(writer)?;
277				tt.serialize(writer)?;
278			},
279			Memory(mt) => {
280				VarInt7::from(0x02).serialize(writer)?;
281				mt.serialize(writer)?;
282			},
283			Global(gt) => {
284				VarInt7::from(0x03).serialize(writer)?;
285				gt.serialize(writer)?;
286			},
287		}
288
289		Ok(())
290	}
291}
292
293/// Import entry.
294#[derive(Debug, Clone, PartialEq)]
295pub struct ImportEntry {
296	module_str: String,
297	field_str: String,
298	external: External,
299}
300
301impl ImportEntry {
302	/// New import entry.
303	pub fn new(module_str: String, field_str: String, external: External) -> Self {
304		ImportEntry { module_str, field_str, external }
305	}
306
307	/// Module reference of the import entry.
308	pub fn module(&self) -> &str {
309		&self.module_str
310	}
311
312	/// Module reference of the import entry (mutable).
313	pub fn module_mut(&mut self) -> &mut String {
314		&mut self.module_str
315	}
316
317	/// Field reference of the import entry.
318	pub fn field(&self) -> &str {
319		&self.field_str
320	}
321
322	/// Field reference of the import entry (mutable)
323	pub fn field_mut(&mut self) -> &mut String {
324		&mut self.field_str
325	}
326
327	/// Local binidng of the import entry.
328	pub fn external(&self) -> &External {
329		&self.external
330	}
331
332	/// Local binidng of the import entry (mutable)
333	pub fn external_mut(&mut self) -> &mut External {
334		&mut self.external
335	}
336}
337
338impl Deserialize for ImportEntry {
339	type Error = Error;
340
341	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
342		let module_str = String::deserialize(reader)?;
343		let field_str = String::deserialize(reader)?;
344		let external = External::deserialize(reader)?;
345
346		Ok(ImportEntry { module_str, field_str, external })
347	}
348}
349
350impl Serialize for ImportEntry {
351	type Error = Error;
352
353	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
354		self.module_str.serialize(writer)?;
355		self.field_str.serialize(writer)?;
356		self.external.serialize(writer)
357	}
358}