sophon_wasm/elements/
section.rs

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