parity_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() as usize..].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 =
347			CountedListWriter::<Type, _>(data.len(), data.into_iter().map(Into::into));
348		counted_list.serialize(&mut counted_writer)?;
349		counted_writer.done()?;
350		Ok(())
351	}
352}
353
354/// Section of the imports definition.
355#[derive(Debug, Default, Clone, PartialEq)]
356pub struct ImportSection(Vec<ImportEntry>);
357
358impl ImportSection {
359	///  New import section with provided types.
360	pub fn with_entries(entries: Vec<ImportEntry>) -> Self {
361		ImportSection(entries)
362	}
363
364	/// List of import entries.
365	pub fn entries(&self) -> &[ImportEntry] {
366		&self.0
367	}
368
369	/// List of import entries (mutable).
370	pub fn entries_mut(&mut self) -> &mut Vec<ImportEntry> {
371		&mut self.0
372	}
373
374	/// Returns number of functions.
375	pub fn functions(&self) -> usize {
376		self.0
377			.iter()
378			.filter(|entry| matches!(*entry.external(), External::Function(_)))
379			.count()
380	}
381
382	/// Returns number of globals
383	pub fn globals(&self) -> usize {
384		self.0
385			.iter()
386			.filter(|entry| matches!(entry.external(), &External::Global(_)))
387			.count()
388	}
389}
390
391impl Deserialize for ImportSection {
392	type Error = Error;
393
394	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
395		Ok(ImportSection(read_entries(reader)?))
396	}
397}
398
399impl Serialize for ImportSection {
400	type Error = Error;
401
402	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
403		let mut counted_writer = CountedWriter::new(writer);
404		let data = self.0;
405		let counted_list =
406			CountedListWriter::<ImportEntry, _>(data.len(), data.into_iter().map(Into::into));
407		counted_list.serialize(&mut counted_writer)?;
408		counted_writer.done()?;
409		Ok(())
410	}
411}
412
413/// Section with function signatures definition.
414#[derive(Default, Debug, Clone, PartialEq)]
415pub struct FunctionSection(Vec<Func>);
416
417impl FunctionSection {
418	///  New function signatures section with provided entries.
419	pub fn with_entries(entries: Vec<Func>) -> Self {
420		FunctionSection(entries)
421	}
422
423	/// List of all functions in the section, mutable.
424	pub fn entries_mut(&mut self) -> &mut Vec<Func> {
425		&mut self.0
426	}
427
428	/// List of all functions in the section.
429	pub fn entries(&self) -> &[Func] {
430		&self.0
431	}
432}
433
434impl Deserialize for FunctionSection {
435	type Error = Error;
436
437	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
438		Ok(FunctionSection(read_entries(reader)?))
439	}
440}
441
442impl Serialize for FunctionSection {
443	type Error = Error;
444
445	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
446		let mut counted_writer = CountedWriter::new(writer);
447		let data = self.0;
448		let counted_list = CountedListWriter::<VarUint32, _>(
449			data.len(),
450			data.into_iter().map(|func| func.type_ref().into()),
451		);
452		counted_list.serialize(&mut counted_writer)?;
453		counted_writer.done()?;
454		Ok(())
455	}
456}
457
458/// Section with table definition (currently only one is allowed).
459#[derive(Default, Debug, Clone, PartialEq)]
460pub struct TableSection(Vec<TableType>);
461
462impl TableSection {
463	/// Table entries.
464	pub fn entries(&self) -> &[TableType] {
465		&self.0
466	}
467
468	///  New table section with provided table entries.
469	pub fn with_entries(entries: Vec<TableType>) -> Self {
470		TableSection(entries)
471	}
472
473	/// Mutable table entries.
474	pub fn entries_mut(&mut self) -> &mut Vec<TableType> {
475		&mut self.0
476	}
477}
478
479impl Deserialize for TableSection {
480	type Error = Error;
481
482	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
483		Ok(TableSection(read_entries(reader)?))
484	}
485}
486
487impl Serialize for TableSection {
488	type Error = Error;
489
490	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
491		let mut counted_writer = CountedWriter::new(writer);
492		let data = self.0;
493		let counted_list =
494			CountedListWriter::<TableType, _>(data.len(), data.into_iter().map(Into::into));
495		counted_list.serialize(&mut counted_writer)?;
496		counted_writer.done()?;
497		Ok(())
498	}
499}
500
501/// Section with table definition (currently only one entry is allowed).
502#[derive(Default, Debug, Clone, PartialEq)]
503pub struct MemorySection(Vec<MemoryType>);
504
505impl MemorySection {
506	/// List of all memory entries in the section
507	pub fn entries(&self) -> &[MemoryType] {
508		&self.0
509	}
510
511	///  New memory section with memory types.
512	pub fn with_entries(entries: Vec<MemoryType>) -> Self {
513		MemorySection(entries)
514	}
515
516	/// Mutable list of all memory entries in the section.
517	pub fn entries_mut(&mut self) -> &mut Vec<MemoryType> {
518		&mut self.0
519	}
520}
521
522impl Deserialize for MemorySection {
523	type Error = Error;
524
525	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
526		Ok(MemorySection(read_entries(reader)?))
527	}
528}
529
530impl Serialize for MemorySection {
531	type Error = Error;
532
533	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
534		let mut counted_writer = CountedWriter::new(writer);
535		let data = self.0;
536		let counted_list =
537			CountedListWriter::<MemoryType, _>(data.len(), data.into_iter().map(Into::into));
538		counted_list.serialize(&mut counted_writer)?;
539		counted_writer.done()?;
540		Ok(())
541	}
542}
543
544/// Globals definition section.
545#[derive(Default, Debug, Clone, PartialEq)]
546pub struct GlobalSection(Vec<GlobalEntry>);
547
548impl GlobalSection {
549	/// List of all global entries in the section.
550	pub fn entries(&self) -> &[GlobalEntry] {
551		&self.0
552	}
553
554	/// New global section from list of global entries.
555	pub fn with_entries(entries: Vec<GlobalEntry>) -> Self {
556		GlobalSection(entries)
557	}
558
559	/// List of all global entries in the section (mutable).
560	pub fn entries_mut(&mut self) -> &mut Vec<GlobalEntry> {
561		&mut self.0
562	}
563}
564
565impl Deserialize for GlobalSection {
566	type Error = Error;
567
568	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
569		Ok(GlobalSection(read_entries(reader)?))
570	}
571}
572
573impl Serialize for GlobalSection {
574	type Error = Error;
575
576	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
577		let mut counted_writer = CountedWriter::new(writer);
578		let data = self.0;
579		let counted_list =
580			CountedListWriter::<GlobalEntry, _>(data.len(), data.into_iter().map(Into::into));
581		counted_list.serialize(&mut counted_writer)?;
582		counted_writer.done()?;
583		Ok(())
584	}
585}
586
587/// List of exports definition.
588#[derive(Debug, Default, Clone, PartialEq)]
589pub struct ExportSection(Vec<ExportEntry>);
590
591impl ExportSection {
592	/// List of all export entries in the section.
593	pub fn entries(&self) -> &[ExportEntry] {
594		&self.0
595	}
596
597	/// New export section from list of export entries.
598	pub fn with_entries(entries: Vec<ExportEntry>) -> Self {
599		ExportSection(entries)
600	}
601
602	/// List of all export entries in the section (mutable).
603	pub fn entries_mut(&mut self) -> &mut Vec<ExportEntry> {
604		&mut self.0
605	}
606}
607
608impl Deserialize for ExportSection {
609	type Error = Error;
610
611	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
612		Ok(ExportSection(read_entries(reader)?))
613	}
614}
615
616impl Serialize for ExportSection {
617	type Error = Error;
618
619	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
620		let mut counted_writer = CountedWriter::new(writer);
621		let data = self.0;
622		let counted_list =
623			CountedListWriter::<ExportEntry, _>(data.len(), data.into_iter().map(Into::into));
624		counted_list.serialize(&mut counted_writer)?;
625		counted_writer.done()?;
626		Ok(())
627	}
628}
629
630/// Section with function bodies of the module.
631#[derive(Default, Debug, Clone, PartialEq)]
632pub struct CodeSection(Vec<FuncBody>);
633
634impl CodeSection {
635	/// New code section with specified function bodies.
636	pub fn with_bodies(bodies: Vec<FuncBody>) -> Self {
637		CodeSection(bodies)
638	}
639
640	/// All function bodies in the section.
641	pub fn bodies(&self) -> &[FuncBody] {
642		&self.0
643	}
644
645	/// All function bodies in the section, mutable.
646	pub fn bodies_mut(&mut self) -> &mut Vec<FuncBody> {
647		&mut self.0
648	}
649}
650
651impl Deserialize for CodeSection {
652	type Error = Error;
653
654	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
655		Ok(CodeSection(read_entries(reader)?))
656	}
657}
658
659impl Serialize for CodeSection {
660	type Error = Error;
661
662	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
663		let mut counted_writer = CountedWriter::new(writer);
664		let data = self.0;
665		let counted_list =
666			CountedListWriter::<FuncBody, _>(data.len(), data.into_iter().map(Into::into));
667		counted_list.serialize(&mut counted_writer)?;
668		counted_writer.done()?;
669		Ok(())
670	}
671}
672
673/// Element entries section.
674#[derive(Default, Debug, Clone, PartialEq)]
675pub struct ElementSection(Vec<ElementSegment>);
676
677impl ElementSection {
678	/// New elements section.
679	pub fn with_entries(entries: Vec<ElementSegment>) -> Self {
680		ElementSection(entries)
681	}
682
683	/// New elements entries in the section.
684	pub fn entries(&self) -> &[ElementSegment] {
685		&self.0
686	}
687
688	/// List of all data entries in the section (mutable).
689	pub fn entries_mut(&mut self) -> &mut Vec<ElementSegment> {
690		&mut self.0
691	}
692}
693
694impl Deserialize for ElementSection {
695	type Error = Error;
696
697	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
698		Ok(ElementSection(read_entries(reader)?))
699	}
700}
701
702impl Serialize for ElementSection {
703	type Error = Error;
704
705	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
706		let mut counted_writer = CountedWriter::new(writer);
707		let data = self.0;
708		let counted_list =
709			CountedListWriter::<ElementSegment, _>(data.len(), data.into_iter().map(Into::into));
710		counted_list.serialize(&mut counted_writer)?;
711		counted_writer.done()?;
712		Ok(())
713	}
714}
715
716/// Data entries definitions.
717#[derive(Default, Debug, Clone, PartialEq)]
718pub struct DataSection(Vec<DataSegment>);
719
720impl DataSection {
721	/// New data section.
722	pub fn with_entries(entries: Vec<DataSegment>) -> Self {
723		DataSection(entries)
724	}
725
726	/// List of all data entries in the section.
727	pub fn entries(&self) -> &[DataSegment] {
728		&self.0
729	}
730
731	/// List of all data entries in the section (mutable).
732	pub fn entries_mut(&mut self) -> &mut Vec<DataSegment> {
733		&mut self.0
734	}
735}
736
737impl Deserialize for DataSection {
738	type Error = Error;
739
740	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
741		Ok(DataSection(read_entries(reader)?))
742	}
743}
744
745impl Serialize for DataSection {
746	type Error = Error;
747
748	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
749		let mut counted_writer = CountedWriter::new(writer);
750		let data = self.0;
751		let counted_list =
752			CountedListWriter::<DataSegment, _>(data.len(), data.into_iter().map(Into::into));
753		counted_list.serialize(&mut counted_writer)?;
754		counted_writer.done()?;
755		Ok(())
756	}
757}
758
759#[cfg(test)]
760mod tests {
761
762	use super::{
763		super::{
764			deserialize_buffer, deserialize_file, serialize, BlockType, DataSegment,
765			ElementSegment, FuncBody, InitExpr, Instructions, Local, ValueType,
766		},
767		CodeSection, DataSection, ElementSection, Section, Type, TypeSection,
768	};
769
770	#[test]
771	fn import_section() {
772		let module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
773		let mut found = false;
774		for section in module.sections() {
775			if let Section::Import(ref import_section) = *section {
776				assert_eq!(25, import_section.entries().len());
777				found = true
778			}
779		}
780		assert!(found, "There should be import section in test5.wasm");
781	}
782
783	fn functions_test_payload() -> &'static [u8] {
784		&[
785			// functions section id
786			0x03u8, // functions section length
787			0x87, 0x80, 0x80, 0x80, 0x0,  // number of functions
788			0x04, // type reference 1
789			0x01, // type reference 2
790			0x86, 0x80, 0x00, // type reference 3
791			0x09, // type reference 4
792			0x33,
793		]
794	}
795
796	#[test]
797	fn fn_section_detect() {
798		let section: Section =
799			deserialize_buffer(functions_test_payload()).expect("section to be deserialized");
800
801		match section {
802			Section::Function(_) => {},
803			_ => {
804				panic!("Payload should be recognized as functions section")
805			},
806		}
807	}
808
809	#[test]
810	fn fn_section_number() {
811		let section: Section =
812			deserialize_buffer(functions_test_payload()).expect("section to be deserialized");
813
814		if let Section::Function(fn_section) = section {
815			assert_eq!(4, fn_section.entries().len(), "There should be 4 functions total");
816		}
817	}
818
819	#[test]
820	fn fn_section_ref() {
821		let section: Section =
822			deserialize_buffer(functions_test_payload()).expect("section to be deserialized");
823
824		if let Section::Function(fn_section) = section {
825			assert_eq!(6, fn_section.entries()[1].type_ref());
826		}
827	}
828
829	fn types_test_payload() -> &'static [u8] {
830		&[
831			// section length
832			11,   // 2 functions
833			2,    // func 1, form =1
834			0x60, // param_count=1
835			1,    // first param
836			0x7e, // i64
837			// no return params
838			0x00, // func 2, form=1
839			0x60, // param_count=2
840			2,    // first param
841			0x7e, // second param
842			0x7d, // return param (is_present, param_type)
843			0x01, 0x7e,
844		]
845	}
846
847	#[test]
848	fn type_section_len() {
849		let type_section: TypeSection =
850			deserialize_buffer(types_test_payload()).expect("type_section be deserialized");
851
852		assert_eq!(type_section.types().len(), 2);
853	}
854
855	#[test]
856	fn type_section_infer() {
857		let type_section: TypeSection =
858			deserialize_buffer(types_test_payload()).expect("type_section be deserialized");
859
860		let Type::Function(ref t1) = type_section.types()[1];
861		assert_eq!(vec![ValueType::I64], t1.results());
862		assert_eq!(2, t1.params().len());
863	}
864
865	fn export_payload() -> &'static [u8] {
866		&[
867			// section id
868			0x07, // section length
869			28,   // 6 entries
870			6,
871			// func "A", index 6
872			// [name_len(1-5 bytes), name_bytes(name_len, internal_kind(1byte), internal_index(1-5 bytes)])
873			0x01, 0x41, 0x01, 0x86, 0x80, 0x00, // func "B", index 8
874			0x01, 0x42, 0x01, 0x86, 0x00, // func "C", index 7
875			0x01, 0x43, 0x01, 0x07, // memory "D", index 0
876			0x01, 0x44, 0x02, 0x00, // func "E", index 1
877			0x01, 0x45, 0x01, 0x01, // func "F", index 2
878			0x01, 0x46, 0x01, 0x02,
879		]
880	}
881
882	#[test]
883	fn export_detect() {
884		let section: Section =
885			deserialize_buffer(export_payload()).expect("section to be deserialized");
886
887		match section {
888			Section::Export(_) => {},
889			_ => {
890				panic!("Payload should be recognized as export section")
891			},
892		}
893	}
894
895	fn code_payload() -> &'static [u8] {
896		&[
897			// sectionid
898			0x0Au8, // section length, 32
899			0x20,   // body count
900			0x01,   // body 1, length 30
901			0x1E, 0x01, 0x01, 0x7F, // local i32 (one collection of length one of type i32)
902			0x02, 0x7F, // block i32
903			0x23, 0x00, // get_global 0
904			0x21, 0x01, // set_local 1
905			0x23, 0x00, // get_global 0
906			0x20, 0x00, // get_local 0
907			0x6A, // i32.add
908			0x24, 0x00, // set_global 0
909			0x23, 0x00, // get_global 0
910			0x41, 0x0F, // i32.const 15
911			0x6A, // i32.add
912			0x41, 0x70, // i32.const -16
913			0x71, // i32.and
914			0x24, 0x00, // set_global 0
915			0x20, 0x01, // get_local 1
916			0x0B, 0x0B,
917		]
918	}
919
920	#[test]
921	fn code_detect() {
922		let section: Section =
923			deserialize_buffer(code_payload()).expect("section to be deserialized");
924
925		match section {
926			Section::Code(_) => {},
927			_ => {
928				panic!("Payload should be recognized as a code section")
929			},
930		}
931	}
932
933	fn data_payload() -> &'static [u8] {
934		&[
935			0x0bu8, // section id
936			20,     // 20 bytes overall
937			0x01,   // number of segments
938			0x00,   // index
939			0x0b,   // just `end` op
940			0x10,   // 16x 0x00
941			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
942			0x00, 0x00,
943		]
944	}
945
946	#[test]
947	fn data_section_ser() {
948		let data_section = DataSection::with_entries(vec![DataSegment::new(
949			0u32,
950			Some(InitExpr::empty()),
951			vec![0u8; 16],
952		)]);
953
954		let buf = serialize(data_section).expect("Data section to be serialized");
955
956		assert_eq!(
957			buf,
958			vec![
959				20u8, // 19 bytes overall
960				0x01, // number of segments
961				0x00, // index
962				0x0b, // just `end` op
963				16,   // value of length 16
964				0x00, 0x00, 0x00, 0x00, // 16x 0x00 as in initialization
965				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
966			]
967		);
968	}
969
970	#[test]
971	fn data_section_detect() {
972		let section: Section =
973			deserialize_buffer(data_payload()).expect("section to be deserialized");
974
975		match section {
976			Section::Data(_) => {},
977			_ => {
978				panic!("Payload should be recognized as a data section")
979			},
980		}
981	}
982
983	#[test]
984	fn element_section_ser() {
985		let element_section = ElementSection::with_entries(vec![ElementSegment::new(
986			0u32,
987			Some(InitExpr::empty()),
988			vec![0u32; 4],
989		)]);
990
991		let buf = serialize(element_section).expect("Element section to be serialized");
992
993		assert_eq!(
994			buf,
995			vec![
996				8u8,  // 8 bytes overall
997				0x01, // number of segments
998				0x00, // index
999				0x0b, // just `end` op
1000				0x04, // 4 elements
1001				0x00, 0x00, 0x00, 0x00 // 4x 0x00 as in initialization
1002			]
1003		);
1004	}
1005
1006	#[test]
1007	fn code_section_ser() {
1008		use super::super::Instruction::*;
1009
1010		let code_section = CodeSection::with_bodies(vec![FuncBody::new(
1011			vec![Local::new(1, ValueType::I32)],
1012			Instructions::new(vec![
1013				Block(BlockType::Value(ValueType::I32)),
1014				GetGlobal(0),
1015				End,
1016				End,
1017			]),
1018		)]);
1019
1020		let buf = serialize(code_section).expect("Code section to be serialized");
1021
1022		assert_eq!(
1023			buf,
1024			vec![
1025				11u8, // 11 bytes total section size
1026				0x01, // 1 function
1027				9,    //   function #1 total code size
1028				1,    //   1 local variable declaration
1029				1,    //      amount of variables
1030				0x7f, //      type of variable (7-bit, -0x01), negative
1031				0x02, //   block
1032				0x7f, //      block return type (7-bit, -0x01), negative
1033				0x23, 0x00, //      get_global(0)
1034				0x0b, //   block end
1035				0x0b, // function end
1036			]
1037		);
1038	}
1039
1040	#[test]
1041	fn start_section() {
1042		let section: Section =
1043			deserialize_buffer(&[8u8, 1u8, 0u8]).expect("Start section to deserialize");
1044		if let Section::Start(_) = section {
1045		} else {
1046			panic!("Payload should be a start section");
1047		}
1048
1049		let serialized = serialize(section).expect("Start section to successfully serializen");
1050
1051		assert_eq!(serialized, vec![8u8, 1u8, 0u8]);
1052	}
1053}