casper_wasm/elements/
section.rs

1use super::{
2	serialize, CountedList, CountedListWriter, CountedWriter, DataSegment, Deserialize,
3	ElementSegment, Error, ExportEntry, External, Func, FuncBody, GlobalEntry, ImportEntry,
4	MemoryType, Serialize, TableType, VarUint32, VarUint7,
5};
6use crate::{elements, io};
7use alloc::{borrow::ToOwned, string::String, vec::Vec};
8
9use super::{name_section::NameSection, reloc_section::RelocSection, types::Type};
10
11#[cfg(feature = "reduced-stack-buffer")]
12const ENTRIES_BUFFER_LENGTH: usize = 256;
13
14#[cfg(not(feature = "reduced-stack-buffer"))]
15const ENTRIES_BUFFER_LENGTH: usize = 16384;
16
17/// Section in the WebAssembly module.
18#[derive(Debug, Clone, PartialEq)]
19pub enum Section {
20	/// Section is unparsed.
21	Unparsed {
22		/// id of the unparsed section.
23		id: u8,
24		/// raw bytes of the unparsed section.
25		payload: Vec<u8>,
26	},
27	/// Custom section (`id=0`).
28	Custom(CustomSection),
29	/// Types section.
30	Type(TypeSection),
31	/// Import section.
32	Import(ImportSection),
33	/// Function signatures section.
34	Function(FunctionSection),
35	/// Table definition section.
36	Table(TableSection),
37	/// Memory definition section.
38	Memory(MemorySection),
39	/// Global entries section.
40	Global(GlobalSection),
41	/// Export definitions.
42	Export(ExportSection),
43	/// Entry reference of the module.
44	Start(u32),
45	/// Elements section.
46	Element(ElementSection),
47	/// Number of passive data entries in the data section
48	DataCount(u32),
49	/// Function bodies section.
50	Code(CodeSection),
51	/// Data definition section.
52	Data(DataSection),
53	/// Name section.
54	///
55	/// Note that initially it is not parsed until `parse_names` is called explicitly.
56	Name(NameSection),
57	/// Relocation section.
58	///
59	/// Note that initially it is not parsed until `parse_reloc` is called explicitly.
60	/// Also note that currently there are serialization (but not de-serialization)
61	///   issues with this section (#198).
62	Reloc(RelocSection),
63}
64
65impl Deserialize for Section {
66	type Error = Error;
67
68	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
69		let id = match VarUint7::deserialize(reader) {
70			// todo: be more selective detecting no more section
71			Err(_) => return Err(Error::UnexpectedEof),
72			Ok(id) => id,
73		};
74
75		Ok(match id.into() {
76			0 => Section::Custom(CustomSection::deserialize(reader)?),
77			1 => Section::Type(TypeSection::deserialize(reader)?),
78			2 => Section::Import(ImportSection::deserialize(reader)?),
79			3 => Section::Function(FunctionSection::deserialize(reader)?),
80			4 => Section::Table(TableSection::deserialize(reader)?),
81			5 => Section::Memory(MemorySection::deserialize(reader)?),
82			6 => Section::Global(GlobalSection::deserialize(reader)?),
83			7 => Section::Export(ExportSection::deserialize(reader)?),
84			8 => {
85				let mut section_reader = SectionReader::new(reader)?;
86				let start_idx = VarUint32::deserialize(&mut section_reader)?;
87				section_reader.close()?;
88				Section::Start(start_idx.into())
89			},
90			9 => Section::Element(ElementSection::deserialize(reader)?),
91			10 => Section::Code(CodeSection::deserialize(reader)?),
92			11 => Section::Data(DataSection::deserialize(reader)?),
93			12 => {
94				let mut section_reader = SectionReader::new(reader)?;
95				let count = VarUint32::deserialize(&mut section_reader)?;
96				section_reader.close()?;
97				Section::DataCount(count.into())
98			},
99			invalid_id => return Err(Error::InvalidSectionId(invalid_id)),
100		})
101	}
102}
103
104impl Serialize for Section {
105	type Error = Error;
106
107	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
108		match self {
109			Section::Custom(custom_section) => {
110				VarUint7::from(0x00).serialize(writer)?;
111				custom_section.serialize(writer)?;
112			},
113			Section::Unparsed { id, payload } => {
114				VarUint7::from(id).serialize(writer)?;
115				writer.write(&payload[..])?;
116			},
117			Section::Type(type_section) => {
118				VarUint7::from(0x01).serialize(writer)?;
119				type_section.serialize(writer)?;
120			},
121			Section::Import(import_section) => {
122				VarUint7::from(0x02).serialize(writer)?;
123				import_section.serialize(writer)?;
124			},
125			Section::Function(function_section) => {
126				VarUint7::from(0x03).serialize(writer)?;
127				function_section.serialize(writer)?;
128			},
129			Section::Table(table_section) => {
130				VarUint7::from(0x04).serialize(writer)?;
131				table_section.serialize(writer)?;
132			},
133			Section::Memory(memory_section) => {
134				VarUint7::from(0x05).serialize(writer)?;
135				memory_section.serialize(writer)?;
136			},
137			Section::Global(global_section) => {
138				VarUint7::from(0x06).serialize(writer)?;
139				global_section.serialize(writer)?;
140			},
141			Section::Export(export_section) => {
142				VarUint7::from(0x07).serialize(writer)?;
143				export_section.serialize(writer)?;
144			},
145			Section::Start(index) => {
146				VarUint7::from(0x08).serialize(writer)?;
147				let mut counted_writer = CountedWriter::new(writer);
148				VarUint32::from(index).serialize(&mut counted_writer)?;
149				counted_writer.done()?;
150			},
151			Section::DataCount(count) => {
152				VarUint7::from(0x0c).serialize(writer)?;
153				let mut counted_writer = CountedWriter::new(writer);
154				VarUint32::from(count).serialize(&mut counted_writer)?;
155				counted_writer.done()?;
156			},
157			Section::Element(element_section) => {
158				VarUint7::from(0x09).serialize(writer)?;
159				element_section.serialize(writer)?;
160			},
161			Section::Code(code_section) => {
162				VarUint7::from(0x0a).serialize(writer)?;
163				code_section.serialize(writer)?;
164			},
165			Section::Data(data_section) => {
166				VarUint7::from(0x0b).serialize(writer)?;
167				data_section.serialize(writer)?;
168			},
169			Section::Name(name_section) => {
170				VarUint7::from(0x00).serialize(writer)?;
171				let custom =
172					CustomSection { name: "name".to_owned(), payload: serialize(name_section)? };
173				custom.serialize(writer)?;
174			},
175			Section::Reloc(reloc_section) => {
176				VarUint7::from(0x00).serialize(writer)?;
177				reloc_section.serialize(writer)?;
178			},
179		}
180		Ok(())
181	}
182}
183
184impl Section {
185	pub(crate) fn order(&self) -> u8 {
186		match *self {
187			Section::Custom(_) => 0x00,
188			Section::Unparsed { .. } => 0x00,
189			Section::Type(_) => 0x1,
190			Section::Import(_) => 0x2,
191			Section::Function(_) => 0x3,
192			Section::Table(_) => 0x4,
193			Section::Memory(_) => 0x5,
194			Section::Global(_) => 0x6,
195			Section::Export(_) => 0x7,
196			Section::Start(_) => 0x8,
197			Section::Element(_) => 0x9,
198			Section::DataCount(_) => 0x0a,
199			Section::Code(_) => 0x0b,
200			Section::Data(_) => 0x0c,
201			Section::Name(_) => 0x00,
202			Section::Reloc(_) => 0x00,
203		}
204	}
205}
206
207pub(crate) struct SectionReader {
208	cursor: io::Cursor<Vec<u8>>,
209	declared_length: usize,
210}
211
212impl SectionReader {
213	pub fn new<R: io::Read>(reader: &mut R) -> Result<Self, elements::Error> {
214		let length = u32::from(VarUint32::deserialize(reader)?) as usize;
215		let inner_buffer = buffered_read!(ENTRIES_BUFFER_LENGTH, length, reader);
216		let declared_length = inner_buffer.len();
217		let cursor = io::Cursor::new(inner_buffer);
218
219		Ok(SectionReader { cursor, declared_length })
220	}
221
222	pub fn close(self) -> Result<(), io::Error> {
223		let cursor = self.cursor;
224		let buf_length = self.declared_length;
225
226		if cursor.position() != buf_length {
227			Err(io::Error::InvalidData)
228		} else {
229			Ok(())
230		}
231	}
232}
233
234impl io::Read for SectionReader {
235	fn read(&mut self, buf: &mut [u8]) -> io::Result<()> {
236		self.cursor.read(buf)?;
237		Ok(())
238	}
239}
240
241fn read_entries<R: io::Read, T: Deserialize<Error = elements::Error>>(
242	reader: &mut R,
243) -> Result<Vec<T>, elements::Error> {
244	let mut section_reader = SectionReader::new(reader)?;
245	let result = CountedList::<T>::deserialize(&mut section_reader)?.into_inner();
246	section_reader.close()?;
247	Ok(result)
248}
249
250/// Custom section.
251#[derive(Debug, Default, Clone, PartialEq)]
252pub struct CustomSection {
253	name: String,
254	payload: Vec<u8>,
255}
256
257impl CustomSection {
258	/// Creates a new custom section with the given name and payload.
259	pub fn new(name: String, payload: Vec<u8>) -> CustomSection {
260		CustomSection { name, payload }
261	}
262
263	/// Name of the custom section.
264	pub fn name(&self) -> &str {
265		&self.name
266	}
267
268	/// Payload of the custom section.
269	pub fn payload(&self) -> &[u8] {
270		&self.payload
271	}
272
273	/// Name of the custom section (mutable).
274	pub fn name_mut(&mut self) -> &mut String {
275		&mut self.name
276	}
277
278	/// Payload of the custom section (mutable).
279	pub fn payload_mut(&mut self) -> &mut Vec<u8> {
280		&mut self.payload
281	}
282}
283
284impl Deserialize for CustomSection {
285	type Error = Error;
286
287	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
288		let section_length: usize = u32::from(VarUint32::deserialize(reader)?) as usize;
289		let buf = buffered_read!(ENTRIES_BUFFER_LENGTH, section_length, reader);
290		let mut cursor = io::Cursor::new(&buf[..]);
291		let name = String::deserialize(&mut cursor)?;
292		let payload = buf[cursor.position()..].to_vec();
293		Ok(CustomSection { name, payload })
294	}
295}
296
297impl Serialize for CustomSection {
298	type Error = Error;
299
300	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
301		use io::Write;
302
303		let mut counted_writer = CountedWriter::new(writer);
304		self.name.serialize(&mut counted_writer)?;
305		counted_writer.write(&self.payload[..])?;
306		counted_writer.done()?;
307		Ok(())
308	}
309}
310
311/// Section with type declarations.
312#[derive(Debug, Default, Clone, PartialEq)]
313pub struct TypeSection(Vec<Type>);
314
315impl TypeSection {
316	///  New type section with provided types.
317	pub fn with_types(types: Vec<Type>) -> Self {
318		TypeSection(types)
319	}
320
321	/// List of type declarations.
322	pub fn types(&self) -> &[Type] {
323		&self.0
324	}
325
326	/// List of type declarations (mutable).
327	pub fn types_mut(&mut self) -> &mut Vec<Type> {
328		&mut self.0
329	}
330}
331
332impl Deserialize for TypeSection {
333	type Error = Error;
334
335	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
336		Ok(TypeSection(read_entries(reader)?))
337	}
338}
339
340impl Serialize for TypeSection {
341	type Error = Error;
342
343	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
344		let mut counted_writer = CountedWriter::new(writer);
345		let data = self.0;
346		let counted_list = CountedListWriter::<Type, _>(data.len(), data.into_iter());
347		counted_list.serialize(&mut counted_writer)?;
348		counted_writer.done()?;
349		Ok(())
350	}
351}
352
353/// Section of the imports definition.
354#[derive(Debug, Default, Clone, PartialEq)]
355pub struct ImportSection(Vec<ImportEntry>);
356
357impl ImportSection {
358	///  New import section with provided types.
359	pub fn with_entries(entries: Vec<ImportEntry>) -> Self {
360		ImportSection(entries)
361	}
362
363	/// List of import entries.
364	pub fn entries(&self) -> &[ImportEntry] {
365		&self.0
366	}
367
368	/// List of import entries (mutable).
369	pub fn entries_mut(&mut self) -> &mut Vec<ImportEntry> {
370		&mut self.0
371	}
372
373	/// Returns number of functions.
374	pub fn functions(&self) -> usize {
375		self.0
376			.iter()
377			.filter(|entry| matches!(*entry.external(), External::Function(_)))
378			.count()
379	}
380
381	/// Returns number of globals
382	pub fn globals(&self) -> usize {
383		self.0
384			.iter()
385			.filter(|entry| matches!(entry.external(), &External::Global(_)))
386			.count()
387	}
388}
389
390impl Deserialize for ImportSection {
391	type Error = Error;
392
393	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
394		Ok(ImportSection(read_entries(reader)?))
395	}
396}
397
398impl Serialize for ImportSection {
399	type Error = Error;
400
401	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
402		let mut counted_writer = CountedWriter::new(writer);
403		let data = self.0;
404		let counted_list = CountedListWriter::<ImportEntry, _>(data.len(), data.into_iter());
405		counted_list.serialize(&mut counted_writer)?;
406		counted_writer.done()?;
407		Ok(())
408	}
409}
410
411/// Section with function signatures definition.
412#[derive(Default, Debug, Clone, PartialEq)]
413pub struct FunctionSection(Vec<Func>);
414
415impl FunctionSection {
416	///  New function signatures section with provided entries.
417	pub fn with_entries(entries: Vec<Func>) -> Self {
418		FunctionSection(entries)
419	}
420
421	/// List of all functions in the section, mutable.
422	pub fn entries_mut(&mut self) -> &mut Vec<Func> {
423		&mut self.0
424	}
425
426	/// List of all functions in the section.
427	pub fn entries(&self) -> &[Func] {
428		&self.0
429	}
430}
431
432impl Deserialize for FunctionSection {
433	type Error = Error;
434
435	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
436		Ok(FunctionSection(read_entries(reader)?))
437	}
438}
439
440impl Serialize for FunctionSection {
441	type Error = Error;
442
443	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
444		let mut counted_writer = CountedWriter::new(writer);
445		let data = self.0;
446		let counted_list = CountedListWriter::<VarUint32, _>(
447			data.len(),
448			data.into_iter().map(|func| func.type_ref().into()),
449		);
450		counted_list.serialize(&mut counted_writer)?;
451		counted_writer.done()?;
452		Ok(())
453	}
454}
455
456/// Section with table definition (currently only one is allowed).
457#[derive(Default, Debug, Clone, PartialEq)]
458pub struct TableSection(Vec<TableType>);
459
460impl TableSection {
461	/// Table entries.
462	pub fn entries(&self) -> &[TableType] {
463		&self.0
464	}
465
466	///  New table section with provided table entries.
467	pub fn with_entries(entries: Vec<TableType>) -> Self {
468		TableSection(entries)
469	}
470
471	/// Mutable table entries.
472	pub fn entries_mut(&mut self) -> &mut Vec<TableType> {
473		&mut self.0
474	}
475}
476
477impl Deserialize for TableSection {
478	type Error = Error;
479
480	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
481		Ok(TableSection(read_entries(reader)?))
482	}
483}
484
485impl Serialize for TableSection {
486	type Error = Error;
487
488	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
489		let mut counted_writer = CountedWriter::new(writer);
490		let data = self.0;
491		let counted_list = CountedListWriter::<TableType, _>(data.len(), data.into_iter());
492		counted_list.serialize(&mut counted_writer)?;
493		counted_writer.done()?;
494		Ok(())
495	}
496}
497
498/// Section with table definition (currently only one entry is allowed).
499#[derive(Default, Debug, Clone, PartialEq)]
500pub struct MemorySection(Vec<MemoryType>);
501
502impl MemorySection {
503	/// List of all memory entries in the section
504	pub fn entries(&self) -> &[MemoryType] {
505		&self.0
506	}
507
508	///  New memory section with memory types.
509	pub fn with_entries(entries: Vec<MemoryType>) -> Self {
510		MemorySection(entries)
511	}
512
513	/// Mutable list of all memory entries in the section.
514	pub fn entries_mut(&mut self) -> &mut Vec<MemoryType> {
515		&mut self.0
516	}
517}
518
519impl Deserialize for MemorySection {
520	type Error = Error;
521
522	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
523		Ok(MemorySection(read_entries(reader)?))
524	}
525}
526
527impl Serialize for MemorySection {
528	type Error = Error;
529
530	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
531		let mut counted_writer = CountedWriter::new(writer);
532		let data = self.0;
533		let counted_list = CountedListWriter::<MemoryType, _>(data.len(), data.into_iter());
534		counted_list.serialize(&mut counted_writer)?;
535		counted_writer.done()?;
536		Ok(())
537	}
538}
539
540/// Globals definition section.
541#[derive(Default, Debug, Clone, PartialEq)]
542pub struct GlobalSection(Vec<GlobalEntry>);
543
544impl GlobalSection {
545	/// List of all global entries in the section.
546	pub fn entries(&self) -> &[GlobalEntry] {
547		&self.0
548	}
549
550	/// New global section from list of global entries.
551	pub fn with_entries(entries: Vec<GlobalEntry>) -> Self {
552		GlobalSection(entries)
553	}
554
555	/// List of all global entries in the section (mutable).
556	pub fn entries_mut(&mut self) -> &mut Vec<GlobalEntry> {
557		&mut self.0
558	}
559}
560
561impl Deserialize for GlobalSection {
562	type Error = Error;
563
564	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
565		Ok(GlobalSection(read_entries(reader)?))
566	}
567}
568
569impl Serialize for GlobalSection {
570	type Error = Error;
571
572	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
573		let mut counted_writer = CountedWriter::new(writer);
574		let data = self.0;
575		let counted_list = CountedListWriter::<GlobalEntry, _>(data.len(), data.into_iter());
576		counted_list.serialize(&mut counted_writer)?;
577		counted_writer.done()?;
578		Ok(())
579	}
580}
581
582/// List of exports definition.
583#[derive(Debug, Default, Clone, PartialEq)]
584pub struct ExportSection(Vec<ExportEntry>);
585
586impl ExportSection {
587	/// List of all export entries in the section.
588	pub fn entries(&self) -> &[ExportEntry] {
589		&self.0
590	}
591
592	/// New export section from list of export entries.
593	pub fn with_entries(entries: Vec<ExportEntry>) -> Self {
594		ExportSection(entries)
595	}
596
597	/// List of all export entries in the section (mutable).
598	pub fn entries_mut(&mut self) -> &mut Vec<ExportEntry> {
599		&mut self.0
600	}
601}
602
603impl Deserialize for ExportSection {
604	type Error = Error;
605
606	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
607		Ok(ExportSection(read_entries(reader)?))
608	}
609}
610
611impl Serialize for ExportSection {
612	type Error = Error;
613
614	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
615		let mut counted_writer = CountedWriter::new(writer);
616		let data = self.0;
617		let counted_list = CountedListWriter::<ExportEntry, _>(data.len(), data.into_iter());
618		counted_list.serialize(&mut counted_writer)?;
619		counted_writer.done()?;
620		Ok(())
621	}
622}
623
624/// Section with function bodies of the module.
625#[derive(Default, Debug, Clone, PartialEq)]
626pub struct CodeSection(Vec<FuncBody>);
627
628impl CodeSection {
629	/// New code section with specified function bodies.
630	pub fn with_bodies(bodies: Vec<FuncBody>) -> Self {
631		CodeSection(bodies)
632	}
633
634	/// All function bodies in the section.
635	pub fn bodies(&self) -> &[FuncBody] {
636		&self.0
637	}
638
639	/// All function bodies in the section, mutable.
640	pub fn bodies_mut(&mut self) -> &mut Vec<FuncBody> {
641		&mut self.0
642	}
643}
644
645impl Deserialize for CodeSection {
646	type Error = Error;
647
648	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
649		Ok(CodeSection(read_entries(reader)?))
650	}
651}
652
653impl Serialize for CodeSection {
654	type Error = Error;
655
656	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
657		let mut counted_writer = CountedWriter::new(writer);
658		let data = self.0;
659		let counted_list = CountedListWriter::<FuncBody, _>(data.len(), data.into_iter());
660		counted_list.serialize(&mut counted_writer)?;
661		counted_writer.done()?;
662		Ok(())
663	}
664}
665
666/// Element entries section.
667#[derive(Default, Debug, Clone, PartialEq)]
668pub struct ElementSection(Vec<ElementSegment>);
669
670impl ElementSection {
671	/// New elements section.
672	pub fn with_entries(entries: Vec<ElementSegment>) -> Self {
673		ElementSection(entries)
674	}
675
676	/// New elements entries in the section.
677	pub fn entries(&self) -> &[ElementSegment] {
678		&self.0
679	}
680
681	/// List of all data entries in the section (mutable).
682	pub fn entries_mut(&mut self) -> &mut Vec<ElementSegment> {
683		&mut self.0
684	}
685}
686
687impl Deserialize for ElementSection {
688	type Error = Error;
689
690	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
691		Ok(ElementSection(read_entries(reader)?))
692	}
693}
694
695impl Serialize for ElementSection {
696	type Error = Error;
697
698	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
699		let mut counted_writer = CountedWriter::new(writer);
700		let data = self.0;
701		let counted_list = CountedListWriter::<ElementSegment, _>(data.len(), data.into_iter());
702		counted_list.serialize(&mut counted_writer)?;
703		counted_writer.done()?;
704		Ok(())
705	}
706}
707
708/// Data entries definitions.
709#[derive(Default, Debug, Clone, PartialEq)]
710pub struct DataSection(Vec<DataSegment>);
711
712impl DataSection {
713	/// New data section.
714	pub fn with_entries(entries: Vec<DataSegment>) -> Self {
715		DataSection(entries)
716	}
717
718	/// List of all data entries in the section.
719	pub fn entries(&self) -> &[DataSegment] {
720		&self.0
721	}
722
723	/// List of all data entries in the section (mutable).
724	pub fn entries_mut(&mut self) -> &mut Vec<DataSegment> {
725		&mut self.0
726	}
727}
728
729impl Deserialize for DataSection {
730	type Error = Error;
731
732	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
733		Ok(DataSection(read_entries(reader)?))
734	}
735}
736
737impl Serialize for DataSection {
738	type Error = Error;
739
740	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
741		let mut counted_writer = CountedWriter::new(writer);
742		let data = self.0;
743		let counted_list = CountedListWriter::<DataSegment, _>(data.len(), data.into_iter());
744		counted_list.serialize(&mut counted_writer)?;
745		counted_writer.done()?;
746		Ok(())
747	}
748}
749
750#[cfg(test)]
751mod tests {
752
753	#[cfg(feature = "std")]
754	use super::super::deserialize_file;
755	use super::{
756		super::{
757			deserialize_buffer, serialize, BlockType, DataSegment, ElementSegment, FuncBody,
758			InitExpr, Instructions, Local, ValueType,
759		},
760		CodeSection, DataSection, ElementSection, Section, Type, TypeSection,
761	};
762
763	#[cfg(feature = "std")]
764	#[test]
765	fn import_section() {
766		let module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
767		let mut found = false;
768		for section in module.sections() {
769			if let Section::Import(ref import_section) = *section {
770				assert_eq!(25, import_section.entries().len());
771				found = true
772			}
773		}
774		assert!(found, "There should be import section in test5.wasm");
775	}
776
777	fn functions_test_payload() -> &'static [u8] {
778		&[
779			// functions section id
780			0x03u8, // functions section length
781			0x87, 0x80, 0x80, 0x80, 0x0,  // number of functions
782			0x04, // type reference 1
783			0x01, // type reference 2
784			0x86, 0x80, 0x00, // type reference 3
785			0x09, // type reference 4
786			0x33,
787		]
788	}
789
790	#[test]
791	fn fn_section_detect() {
792		let section: Section =
793			deserialize_buffer(functions_test_payload()).expect("section to be deserialized");
794
795		match section {
796			Section::Function(_) => {},
797			_ => {
798				panic!("Payload should be recognized as functions section")
799			},
800		}
801	}
802
803	#[test]
804	fn fn_section_number() {
805		let section: Section =
806			deserialize_buffer(functions_test_payload()).expect("section to be deserialized");
807
808		if let Section::Function(fn_section) = section {
809			assert_eq!(4, fn_section.entries().len(), "There should be 4 functions total");
810		}
811	}
812
813	#[test]
814	fn fn_section_ref() {
815		let section: Section =
816			deserialize_buffer(functions_test_payload()).expect("section to be deserialized");
817
818		if let Section::Function(fn_section) = section {
819			assert_eq!(6, fn_section.entries()[1].type_ref());
820		}
821	}
822
823	fn types_test_payload() -> &'static [u8] {
824		&[
825			// section length
826			11,   // 2 functions
827			2,    // func 1, form =1
828			0x60, // param_count=1
829			1,    // first param
830			0x7e, // i64
831			// no return params
832			0x00, // func 2, form=1
833			0x60, // param_count=2
834			2,    // first param
835			0x7e, // second param
836			0x7d, // return param (is_present, param_type)
837			0x01, 0x7e,
838		]
839	}
840
841	#[test]
842	fn type_section_len() {
843		let type_section: TypeSection =
844			deserialize_buffer(types_test_payload()).expect("type_section be deserialized");
845
846		assert_eq!(type_section.types().len(), 2);
847	}
848
849	#[test]
850	fn type_section_infer() {
851		let type_section: TypeSection =
852			deserialize_buffer(types_test_payload()).expect("type_section be deserialized");
853
854		let Type::Function(ref t1) = type_section.types()[1];
855		assert_eq!(vec![ValueType::I64], t1.results());
856		assert_eq!(2, t1.params().len());
857	}
858
859	fn export_payload() -> &'static [u8] {
860		&[
861			// section id
862			0x07, // section length
863			28,   // 6 entries
864			6,
865			// func "A", index 6
866			// [name_len(1-5 bytes), name_bytes(name_len, internal_kind(1byte), internal_index(1-5 bytes)])
867			0x01, 0x41, 0x01, 0x86, 0x80, 0x00, // func "B", index 8
868			0x01, 0x42, 0x01, 0x86, 0x00, // func "C", index 7
869			0x01, 0x43, 0x01, 0x07, // memory "D", index 0
870			0x01, 0x44, 0x02, 0x00, // func "E", index 1
871			0x01, 0x45, 0x01, 0x01, // func "F", index 2
872			0x01, 0x46, 0x01, 0x02,
873		]
874	}
875
876	#[test]
877	fn export_detect() {
878		let section: Section =
879			deserialize_buffer(export_payload()).expect("section to be deserialized");
880
881		match section {
882			Section::Export(_) => {},
883			_ => {
884				panic!("Payload should be recognized as export section")
885			},
886		}
887	}
888
889	fn code_payload() -> &'static [u8] {
890		&[
891			// sectionid
892			0x0Au8, // section length, 32
893			0x20,   // body count
894			0x01,   // body 1, length 30
895			0x1E, 0x01, 0x01, 0x7F, // local i32 (one collection of length one of type i32)
896			0x02, 0x7F, // block i32
897			0x23, 0x00, // get_global 0
898			0x21, 0x01, // set_local 1
899			0x23, 0x00, // get_global 0
900			0x20, 0x00, // get_local 0
901			0x6A, // i32.add
902			0x24, 0x00, // set_global 0
903			0x23, 0x00, // get_global 0
904			0x41, 0x0F, // i32.const 15
905			0x6A, // i32.add
906			0x41, 0x70, // i32.const -16
907			0x71, // i32.and
908			0x24, 0x00, // set_global 0
909			0x20, 0x01, // get_local 1
910			0x0B, 0x0B,
911		]
912	}
913
914	#[test]
915	fn code_detect() {
916		let section: Section =
917			deserialize_buffer(code_payload()).expect("section to be deserialized");
918
919		match section {
920			Section::Code(_) => {},
921			_ => {
922				panic!("Payload should be recognized as a code section")
923			},
924		}
925	}
926
927	fn data_payload() -> &'static [u8] {
928		&[
929			0x0bu8, // section id
930			20,     // 20 bytes overall
931			0x01,   // number of segments
932			0x00,   // index
933			0x0b,   // just `end` op
934			0x10,   // 16x 0x00
935			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
936			0x00, 0x00,
937		]
938	}
939
940	#[test]
941	fn data_section_ser() {
942		let data_section = DataSection::with_entries(vec![DataSegment::new(
943			0u32,
944			Some(InitExpr::empty()),
945			vec![0u8; 16],
946		)]);
947
948		let buf = serialize(data_section).expect("Data section to be serialized");
949
950		assert_eq!(
951			buf,
952			vec![
953				20u8, // 19 bytes overall
954				0x01, // number of segments
955				0x00, // index
956				0x0b, // just `end` op
957				16,   // value of length 16
958				0x00, 0x00, 0x00, 0x00, // 16x 0x00 as in initialization
959				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
960			]
961		);
962	}
963
964	#[test]
965	fn data_section_detect() {
966		let section: Section =
967			deserialize_buffer(data_payload()).expect("section to be deserialized");
968
969		match section {
970			Section::Data(_) => {},
971			_ => {
972				panic!("Payload should be recognized as a data section")
973			},
974		}
975	}
976
977	#[test]
978	fn element_section_ser() {
979		let element_section = ElementSection::with_entries(vec![ElementSegment::new(
980			0u32,
981			Some(InitExpr::empty()),
982			vec![0u32; 4],
983		)]);
984
985		let buf = serialize(element_section).expect("Element section to be serialized");
986
987		assert_eq!(
988			buf,
989			vec![
990				8u8,  // 8 bytes overall
991				0x01, // number of segments
992				0x00, // index
993				0x0b, // just `end` op
994				0x04, // 4 elements
995				0x00, 0x00, 0x00, 0x00 // 4x 0x00 as in initialization
996			]
997		);
998	}
999
1000	#[test]
1001	fn code_section_ser() {
1002		use super::super::Instruction::*;
1003
1004		let code_section = CodeSection::with_bodies(vec![FuncBody::new(
1005			vec![Local::new(1, ValueType::I32)],
1006			Instructions::new(vec![
1007				Block(BlockType::Value(ValueType::I32)),
1008				GetGlobal(0),
1009				End,
1010				End,
1011			]),
1012		)]);
1013
1014		let buf = serialize(code_section).expect("Code section to be serialized");
1015
1016		assert_eq!(
1017			buf,
1018			vec![
1019				11u8, // 11 bytes total section size
1020				0x01, // 1 function
1021				9,    //   function #1 total code size
1022				1,    //   1 local variable declaration
1023				1,    //      amount of variables
1024				0x7f, //      type of variable (7-bit, -0x01), negative
1025				0x02, //   block
1026				0x7f, //      block return type (7-bit, -0x01), negative
1027				0x23, 0x00, //      get_global(0)
1028				0x0b, //   block end
1029				0x0b, // function end
1030			]
1031		);
1032	}
1033
1034	#[test]
1035	fn start_section() {
1036		let section: Section =
1037			deserialize_buffer(&[8u8, 1u8, 0u8]).expect("Start section to deserialize");
1038		if let Section::Start(_) = section {
1039		} else {
1040			panic!("Payload should be a start section");
1041		}
1042
1043		let serialized = serialize(section).expect("Start section to successfully serializen");
1044
1045		assert_eq!(serialized, vec![8u8, 1u8, 0u8]);
1046	}
1047}