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