swasm/elements/
section.rs

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