tetsy_wasm/elements/
import_entry.rs

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