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#[derive(Debug, Clone, PartialEq)]
23pub enum Section {
24 Unparsed {
26 id: u8,
28 payload: Vec<u8>,
30 },
31 Custom(CustomSection),
33 Type(TypeSection),
35 Import(ImportSection),
37 Function(FunctionSection),
39 Table(TableSection),
41 Memory(MemorySection),
43 Global(GlobalSection),
45 Export(ExportSection),
47 Start(u32),
49 Element(ElementSection),
51 DataCount(u32),
53 Code(CodeSection),
55 Data(DataSection),
57 Name(NameSection),
61 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 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 #[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 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#[derive(Debug, Default, Clone, PartialEq)]
279pub struct CustomSection {
280 name: String,
281 payload: Vec<u8>,
282}
283
284impl CustomSection {
285 pub fn new(name: String, payload: Vec<u8>) -> CustomSection {
287 CustomSection { name, payload }
288 }
289
290 pub fn name(&self) -> &str {
292 &self.name
293 }
294
295 pub fn payload(&self) -> &[u8] {
297 &self.payload
298 }
299
300 pub fn name_mut(&mut self) -> &mut String {
302 &mut self.name
303 }
304
305 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#[derive(Debug, Default, Clone, PartialEq)]
340pub struct TypeSection(Vec<Type>);
341
342impl TypeSection {
343 pub fn with_types(types: Vec<Type>) -> Self {
345 TypeSection(types)
346 }
347
348 pub fn types(&self) -> &[Type] {
350 &self.0
351 }
352
353 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#[derive(Debug, Default, Clone, PartialEq)]
383pub struct ImportSection(Vec<ImportEntry>);
384
385impl ImportSection {
386 pub fn with_entries(entries: Vec<ImportEntry>) -> Self {
388 ImportSection(entries)
389 }
390
391 pub fn entries(&self) -> &[ImportEntry] {
393 &self.0
394 }
395
396 pub fn entries_mut(&mut self) -> &mut Vec<ImportEntry> {
398 &mut self.0
399 }
400
401 pub fn functions(&self) -> usize {
403 self.0
404 .iter()
405 .filter(|entry| matches!(*entry.external(), External::Function(_)))
406 .count()
407 }
408
409 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#[derive(Default, Debug, Clone, PartialEq)]
442pub struct FunctionSection(Vec<Func>);
443
444impl FunctionSection {
445 pub fn with_entries(entries: Vec<Func>) -> Self {
447 FunctionSection(entries)
448 }
449
450 pub fn entries_mut(&mut self) -> &mut Vec<Func> {
452 &mut self.0
453 }
454
455 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#[derive(Default, Debug, Clone, PartialEq)]
487pub struct TableSection(Vec<TableType>);
488
489impl TableSection {
490 pub fn entries(&self) -> &[TableType] {
492 &self.0
493 }
494
495 pub fn with_entries(entries: Vec<TableType>) -> Self {
497 TableSection(entries)
498 }
499
500 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#[derive(Default, Debug, Clone, PartialEq)]
530pub struct MemorySection(Vec<MemoryType>);
531
532impl MemorySection {
533 pub fn entries(&self) -> &[MemoryType] {
535 &self.0
536 }
537
538 pub fn with_entries(entries: Vec<MemoryType>) -> Self {
540 MemorySection(entries)
541 }
542
543 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#[derive(Default, Debug, Clone, PartialEq)]
573pub struct GlobalSection(Vec<GlobalEntry>);
574
575impl GlobalSection {
576 pub fn entries(&self) -> &[GlobalEntry] {
578 &self.0
579 }
580
581 pub fn with_entries(entries: Vec<GlobalEntry>) -> Self {
583 GlobalSection(entries)
584 }
585
586 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#[derive(Debug, Default, Clone, PartialEq)]
616pub struct ExportSection(Vec<ExportEntry>);
617
618impl ExportSection {
619 pub fn entries(&self) -> &[ExportEntry] {
621 &self.0
622 }
623
624 pub fn with_entries(entries: Vec<ExportEntry>) -> Self {
626 ExportSection(entries)
627 }
628
629 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#[derive(Default, Debug, Clone, PartialEq)]
659pub struct CodeSection(Vec<FuncBody>, #[cfg(feature = "offsets")] Offset);
660
661impl CodeSection {
662 pub fn with_bodies(bodies: Vec<FuncBody>) -> Self {
664 CodeSection(
665 bodies,
666 #[cfg(feature = "offsets")]
667 0,
668 )
669 }
670
671 pub fn bodies(&self) -> &[FuncBody] {
673 &self.0
674 }
675
676 pub fn bodies_mut(&mut self) -> &mut Vec<FuncBody> {
678 &mut self.0
679 }
680
681 #[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#[derive(Default, Debug, Clone, PartialEq)]
718pub struct ElementSection(Vec<ElementSegment>);
719
720impl ElementSection {
721 pub fn with_entries(entries: Vec<ElementSegment>) -> Self {
723 ElementSection(entries)
724 }
725
726 pub fn entries(&self) -> &[ElementSegment] {
728 &self.0
729 }
730
731 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#[derive(Default, Debug, Clone, PartialEq)]
761pub struct DataSection(Vec<DataSegment>);
762
763impl DataSection {
764 pub fn with_entries(entries: Vec<DataSegment>) -> Self {
766 DataSection(entries)
767 }
768
769 pub fn entries(&self) -> &[DataSegment] {
771 &self.0
772 }
773
774 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 0x03u8, 0x87, 0x80, 0x80, 0x80, 0x0, 0x04, 0x01, 0x86, 0x80, 0x00, 0x09, 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 11, 2, 0x60, 1, 0x7e, 0x00, 0x60, 2, 0x7e, 0x7d, 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 0x07, 28, 6,
914 0x01, 0x41, 0x01, 0x86, 0x80, 0x00, 0x01, 0x42, 0x01, 0x86, 0x00, 0x01, 0x43, 0x01, 0x07, 0x01, 0x44, 0x02, 0x00, 0x01, 0x45, 0x01, 0x01, 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, 0x20, 0x01, 0x1E, 0x01, 0x01, 0x7F, 0x02, 0x7F, 0x23, 0x00, 0x21, 0x01, 0x23, 0x00, 0x20, 0x00, 0x6A, 0x24, 0x00, 0x23, 0x00, 0x41, 0x0F, 0x6A, 0x41, 0x70, 0x71, 0x24, 0x00, 0x20, 0x01, 0x0B, 0x0B, ]
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 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, 20, 0x01, 0x00, 0x0b, 0x10, 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, 0x01, 0x00, 0x0b, 16, 0x00, 0x00, 0x00, 0x00, 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, 0x01, 0x00, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x00 ]
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, 0x01, 9, 1, 1, 0x7f, 0x02, 0x7f, 0x23, 0x00, 0x0b, 0x0b, ]
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}