use super::{
serialize, CountedList, CountedListWriter, CountedWriter, DataSegment, Deserialize,
ElementSegment, Error, ExportEntry, External, Func, FuncBody, GlobalEntry, ImportEntry,
MemoryType, Serialize, TableType, VarUint32, VarUint7,
};
use crate::{elements, io};
use alloc::{borrow::ToOwned, string::String, vec::Vec};
use super::{name_section::NameSection, reloc_section::RelocSection, types::Type};
#[cfg(feature = "reduced-stack-buffer")]
const ENTRIES_BUFFER_LENGTH: usize = 256;
#[cfg(not(feature = "reduced-stack-buffer"))]
const ENTRIES_BUFFER_LENGTH: usize = 16384;
#[derive(Debug, Clone, PartialEq)]
pub enum Section {
Unparsed {
id: u8,
payload: Vec<u8>,
},
Custom(CustomSection),
Type(TypeSection),
Import(ImportSection),
Function(FunctionSection),
Table(TableSection),
Memory(MemorySection),
Global(GlobalSection),
Export(ExportSection),
Start(u32),
Element(ElementSection),
DataCount(u32),
Code(CodeSection),
Data(DataSection),
Name(NameSection),
Reloc(RelocSection),
}
impl Deserialize for Section {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let id = match VarUint7::deserialize(reader) {
Err(_) => return Err(Error::UnexpectedEof),
Ok(id) => id,
};
Ok(match id.into() {
0 => Section::Custom(CustomSection::deserialize(reader)?),
1 => Section::Type(TypeSection::deserialize(reader)?),
2 => Section::Import(ImportSection::deserialize(reader)?),
3 => Section::Function(FunctionSection::deserialize(reader)?),
4 => Section::Table(TableSection::deserialize(reader)?),
5 => Section::Memory(MemorySection::deserialize(reader)?),
6 => Section::Global(GlobalSection::deserialize(reader)?),
7 => Section::Export(ExportSection::deserialize(reader)?),
8 => {
let mut section_reader = SectionReader::new(reader)?;
let start_idx = VarUint32::deserialize(&mut section_reader)?;
section_reader.close()?;
Section::Start(start_idx.into())
},
9 => Section::Element(ElementSection::deserialize(reader)?),
10 => Section::Code(CodeSection::deserialize(reader)?),
11 => Section::Data(DataSection::deserialize(reader)?),
12 => {
let mut section_reader = SectionReader::new(reader)?;
let count = VarUint32::deserialize(&mut section_reader)?;
section_reader.close()?;
Section::DataCount(count.into())
},
invalid_id => return Err(Error::InvalidSectionId(invalid_id)),
})
}
}
impl Serialize for Section {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
match self {
Section::Custom(custom_section) => {
VarUint7::from(0x00).serialize(writer)?;
custom_section.serialize(writer)?;
},
Section::Unparsed { id, payload } => {
VarUint7::from(id).serialize(writer)?;
writer.write(&payload[..])?;
},
Section::Type(type_section) => {
VarUint7::from(0x01).serialize(writer)?;
type_section.serialize(writer)?;
},
Section::Import(import_section) => {
VarUint7::from(0x02).serialize(writer)?;
import_section.serialize(writer)?;
},
Section::Function(function_section) => {
VarUint7::from(0x03).serialize(writer)?;
function_section.serialize(writer)?;
},
Section::Table(table_section) => {
VarUint7::from(0x04).serialize(writer)?;
table_section.serialize(writer)?;
},
Section::Memory(memory_section) => {
VarUint7::from(0x05).serialize(writer)?;
memory_section.serialize(writer)?;
},
Section::Global(global_section) => {
VarUint7::from(0x06).serialize(writer)?;
global_section.serialize(writer)?;
},
Section::Export(export_section) => {
VarUint7::from(0x07).serialize(writer)?;
export_section.serialize(writer)?;
},
Section::Start(index) => {
VarUint7::from(0x08).serialize(writer)?;
let mut counted_writer = CountedWriter::new(writer);
VarUint32::from(index).serialize(&mut counted_writer)?;
counted_writer.done()?;
},
Section::DataCount(count) => {
VarUint7::from(0x0c).serialize(writer)?;
let mut counted_writer = CountedWriter::new(writer);
VarUint32::from(count).serialize(&mut counted_writer)?;
counted_writer.done()?;
},
Section::Element(element_section) => {
VarUint7::from(0x09).serialize(writer)?;
element_section.serialize(writer)?;
},
Section::Code(code_section) => {
VarUint7::from(0x0a).serialize(writer)?;
code_section.serialize(writer)?;
},
Section::Data(data_section) => {
VarUint7::from(0x0b).serialize(writer)?;
data_section.serialize(writer)?;
},
Section::Name(name_section) => {
VarUint7::from(0x00).serialize(writer)?;
let custom =
CustomSection { name: "name".to_owned(), payload: serialize(name_section)? };
custom.serialize(writer)?;
},
Section::Reloc(reloc_section) => {
VarUint7::from(0x00).serialize(writer)?;
reloc_section.serialize(writer)?;
},
}
Ok(())
}
}
impl Section {
pub(crate) fn order(&self) -> u8 {
match *self {
Section::Custom(_) => 0x00,
Section::Unparsed { .. } => 0x00,
Section::Type(_) => 0x1,
Section::Import(_) => 0x2,
Section::Function(_) => 0x3,
Section::Table(_) => 0x4,
Section::Memory(_) => 0x5,
Section::Global(_) => 0x6,
Section::Export(_) => 0x7,
Section::Start(_) => 0x8,
Section::Element(_) => 0x9,
Section::DataCount(_) => 0x0a,
Section::Code(_) => 0x0b,
Section::Data(_) => 0x0c,
Section::Name(_) => 0x00,
Section::Reloc(_) => 0x00,
}
}
}
pub(crate) struct SectionReader {
cursor: io::Cursor<Vec<u8>>,
declared_length: usize,
}
impl SectionReader {
pub fn new<R: io::Read>(reader: &mut R) -> Result<Self, elements::Error> {
let length = u32::from(VarUint32::deserialize(reader)?) as usize;
let inner_buffer = buffered_read!(ENTRIES_BUFFER_LENGTH, length, reader);
let declared_length = inner_buffer.len();
let cursor = io::Cursor::new(inner_buffer);
Ok(SectionReader { cursor, declared_length })
}
pub fn close(self) -> Result<(), io::Error> {
let cursor = self.cursor;
let buf_length = self.declared_length;
if cursor.position() != buf_length {
Err(io::Error::InvalidData)
} else {
Ok(())
}
}
}
impl io::Read for SectionReader {
fn read(&mut self, buf: &mut [u8]) -> io::Result<()> {
self.cursor.read(buf)?;
Ok(())
}
}
fn read_entries<R: io::Read, T: Deserialize<Error = elements::Error>>(
reader: &mut R,
) -> Result<Vec<T>, elements::Error> {
let mut section_reader = SectionReader::new(reader)?;
let result = CountedList::<T>::deserialize(&mut section_reader)?.into_inner();
section_reader.close()?;
Ok(result)
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct CustomSection {
name: String,
payload: Vec<u8>,
}
impl CustomSection {
pub fn new(name: String, payload: Vec<u8>) -> CustomSection {
CustomSection { name, payload }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn payload(&self) -> &[u8] {
&self.payload
}
pub fn name_mut(&mut self) -> &mut String {
&mut self.name
}
pub fn payload_mut(&mut self) -> &mut Vec<u8> {
&mut self.payload
}
}
impl Deserialize for CustomSection {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let section_length: usize = u32::from(VarUint32::deserialize(reader)?) as usize;
let buf = buffered_read!(ENTRIES_BUFFER_LENGTH, section_length, reader);
let mut cursor = io::Cursor::new(&buf[..]);
let name = String::deserialize(&mut cursor)?;
let payload = buf[cursor.position() as usize..].to_vec();
Ok(CustomSection { name, payload })
}
}
impl Serialize for CustomSection {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
use io::Write;
let mut counted_writer = CountedWriter::new(writer);
self.name.serialize(&mut counted_writer)?;
counted_writer.write(&self.payload[..])?;
counted_writer.done()?;
Ok(())
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct TypeSection(Vec<Type>);
impl TypeSection {
pub fn with_types(types: Vec<Type>) -> Self {
TypeSection(types)
}
pub fn types(&self) -> &[Type] {
&self.0
}
pub fn types_mut(&mut self) -> &mut Vec<Type> {
&mut self.0
}
}
impl Deserialize for TypeSection {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(TypeSection(read_entries(reader)?))
}
}
impl Serialize for TypeSection {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list =
CountedListWriter::<Type, _>(data.len(), data.into_iter().map(Into::into));
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct ImportSection(Vec<ImportEntry>);
impl ImportSection {
pub fn with_entries(entries: Vec<ImportEntry>) -> Self {
ImportSection(entries)
}
pub fn entries(&self) -> &[ImportEntry] {
&self.0
}
pub fn entries_mut(&mut self) -> &mut Vec<ImportEntry> {
&mut self.0
}
pub fn functions(&self) -> usize {
self.0
.iter()
.filter(|entry| matches!(*entry.external(), External::Function(_)))
.count()
}
pub fn globals(&self) -> usize {
self.0
.iter()
.filter(|entry| matches!(entry.external(), &External::Global(_)))
.count()
}
}
impl Deserialize for ImportSection {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(ImportSection(read_entries(reader)?))
}
}
impl Serialize for ImportSection {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list =
CountedListWriter::<ImportEntry, _>(data.len(), data.into_iter().map(Into::into));
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
}
}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct FunctionSection(Vec<Func>);
impl FunctionSection {
pub fn with_entries(entries: Vec<Func>) -> Self {
FunctionSection(entries)
}
pub fn entries_mut(&mut self) -> &mut Vec<Func> {
&mut self.0
}
pub fn entries(&self) -> &[Func] {
&self.0
}
}
impl Deserialize for FunctionSection {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(FunctionSection(read_entries(reader)?))
}
}
impl Serialize for FunctionSection {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list = CountedListWriter::<VarUint32, _>(
data.len(),
data.into_iter().map(|func| func.type_ref().into()),
);
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
}
}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct TableSection(Vec<TableType>);
impl TableSection {
pub fn entries(&self) -> &[TableType] {
&self.0
}
pub fn with_entries(entries: Vec<TableType>) -> Self {
TableSection(entries)
}
pub fn entries_mut(&mut self) -> &mut Vec<TableType> {
&mut self.0
}
}
impl Deserialize for TableSection {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(TableSection(read_entries(reader)?))
}
}
impl Serialize for TableSection {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list =
CountedListWriter::<TableType, _>(data.len(), data.into_iter().map(Into::into));
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
}
}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct MemorySection(Vec<MemoryType>);
impl MemorySection {
pub fn entries(&self) -> &[MemoryType] {
&self.0
}
pub fn with_entries(entries: Vec<MemoryType>) -> Self {
MemorySection(entries)
}
pub fn entries_mut(&mut self) -> &mut Vec<MemoryType> {
&mut self.0
}
}
impl Deserialize for MemorySection {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(MemorySection(read_entries(reader)?))
}
}
impl Serialize for MemorySection {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list =
CountedListWriter::<MemoryType, _>(data.len(), data.into_iter().map(Into::into));
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
}
}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct GlobalSection(Vec<GlobalEntry>);
impl GlobalSection {
pub fn entries(&self) -> &[GlobalEntry] {
&self.0
}
pub fn with_entries(entries: Vec<GlobalEntry>) -> Self {
GlobalSection(entries)
}
pub fn entries_mut(&mut self) -> &mut Vec<GlobalEntry> {
&mut self.0
}
}
impl Deserialize for GlobalSection {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(GlobalSection(read_entries(reader)?))
}
}
impl Serialize for GlobalSection {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list =
CountedListWriter::<GlobalEntry, _>(data.len(), data.into_iter().map(Into::into));
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct ExportSection(Vec<ExportEntry>);
impl ExportSection {
pub fn entries(&self) -> &[ExportEntry] {
&self.0
}
pub fn with_entries(entries: Vec<ExportEntry>) -> Self {
ExportSection(entries)
}
pub fn entries_mut(&mut self) -> &mut Vec<ExportEntry> {
&mut self.0
}
}
impl Deserialize for ExportSection {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(ExportSection(read_entries(reader)?))
}
}
impl Serialize for ExportSection {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list =
CountedListWriter::<ExportEntry, _>(data.len(), data.into_iter().map(Into::into));
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
}
}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct CodeSection(Vec<FuncBody>);
impl CodeSection {
pub fn with_bodies(bodies: Vec<FuncBody>) -> Self {
CodeSection(bodies)
}
pub fn bodies(&self) -> &[FuncBody] {
&self.0
}
pub fn bodies_mut(&mut self) -> &mut Vec<FuncBody> {
&mut self.0
}
}
impl Deserialize for CodeSection {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(CodeSection(read_entries(reader)?))
}
}
impl Serialize for CodeSection {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list =
CountedListWriter::<FuncBody, _>(data.len(), data.into_iter().map(Into::into));
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
}
}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct ElementSection(Vec<ElementSegment>);
impl ElementSection {
pub fn with_entries(entries: Vec<ElementSegment>) -> Self {
ElementSection(entries)
}
pub fn entries(&self) -> &[ElementSegment] {
&self.0
}
pub fn entries_mut(&mut self) -> &mut Vec<ElementSegment> {
&mut self.0
}
}
impl Deserialize for ElementSection {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(ElementSection(read_entries(reader)?))
}
}
impl Serialize for ElementSection {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list =
CountedListWriter::<ElementSegment, _>(data.len(), data.into_iter().map(Into::into));
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
}
}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct DataSection(Vec<DataSegment>);
impl DataSection {
pub fn with_entries(entries: Vec<DataSegment>) -> Self {
DataSection(entries)
}
pub fn entries(&self) -> &[DataSegment] {
&self.0
}
pub fn entries_mut(&mut self) -> &mut Vec<DataSegment> {
&mut self.0
}
}
impl Deserialize for DataSection {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(DataSection(read_entries(reader)?))
}
}
impl Serialize for DataSection {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.0;
let counted_list =
CountedListWriter::<DataSegment, _>(data.len(), data.into_iter().map(Into::into));
counted_list.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::{
super::{
deserialize_buffer, deserialize_file, serialize, BlockType, DataSegment,
ElementSegment, FuncBody, InitExpr, Instructions, Local, ValueType,
},
CodeSection, DataSection, ElementSection, Section, Type, TypeSection,
};
#[test]
fn import_section() {
let module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
let mut found = false;
for section in module.sections() {
if let Section::Import(ref import_section) = *section {
assert_eq!(25, import_section.entries().len());
found = true
}
}
assert!(found, "There should be import section in test5.wasm");
}
fn functions_test_payload() -> &'static [u8] {
&[
0x03u8, 0x87, 0x80, 0x80, 0x80, 0x0, 0x04, 0x01, 0x86, 0x80, 0x00, 0x09, 0x33,
]
}
#[test]
fn fn_section_detect() {
let section: Section =
deserialize_buffer(functions_test_payload()).expect("section to be deserialized");
match section {
Section::Function(_) => {},
_ => {
panic!("Payload should be recognized as functions section")
},
}
}
#[test]
fn fn_section_number() {
let section: Section =
deserialize_buffer(functions_test_payload()).expect("section to be deserialized");
if let Section::Function(fn_section) = section {
assert_eq!(4, fn_section.entries().len(), "There should be 4 functions total");
}
}
#[test]
fn fn_section_ref() {
let section: Section =
deserialize_buffer(functions_test_payload()).expect("section to be deserialized");
if let Section::Function(fn_section) = section {
assert_eq!(6, fn_section.entries()[1].type_ref());
}
}
fn types_test_payload() -> &'static [u8] {
&[
11, 2, 0x60, 1, 0x7e, 0x00, 0x60, 2, 0x7e, 0x7d, 0x01, 0x7e,
]
}
#[test]
fn type_section_len() {
let type_section: TypeSection =
deserialize_buffer(types_test_payload()).expect("type_section be deserialized");
assert_eq!(type_section.types().len(), 2);
}
#[test]
fn type_section_infer() {
let type_section: TypeSection =
deserialize_buffer(types_test_payload()).expect("type_section be deserialized");
let Type::Function(ref t1) = type_section.types()[1];
assert_eq!(vec![ValueType::I64], t1.results());
assert_eq!(2, t1.params().len());
}
fn export_payload() -> &'static [u8] {
&[
0x07, 28, 6,
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,
]
}
#[test]
fn export_detect() {
let section: Section =
deserialize_buffer(export_payload()).expect("section to be deserialized");
match section {
Section::Export(_) => {},
_ => {
panic!("Payload should be recognized as export section")
},
}
}
fn code_payload() -> &'static [u8] {
&[
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,
]
}
#[test]
fn code_detect() {
let section: Section =
deserialize_buffer(code_payload()).expect("section to be deserialized");
match section {
Section::Code(_) => {},
_ => {
panic!("Payload should be recognized as a code section")
},
}
}
fn data_payload() -> &'static [u8] {
&[
0x0bu8, 20, 0x01, 0x00, 0x0b, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
]
}
#[test]
fn data_section_ser() {
let data_section = DataSection::with_entries(vec![DataSegment::new(
0u32,
Some(InitExpr::empty()),
vec![0u8; 16],
)]);
let buf = serialize(data_section).expect("Data section to be serialized");
assert_eq!(
buf,
vec![
20u8, 0x01, 0x00, 0x0b, 16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]
);
}
#[test]
fn data_section_detect() {
let section: Section =
deserialize_buffer(data_payload()).expect("section to be deserialized");
match section {
Section::Data(_) => {},
_ => {
panic!("Payload should be recognized as a data section")
},
}
}
#[test]
fn element_section_ser() {
let element_section = ElementSection::with_entries(vec![ElementSegment::new(
0u32,
Some(InitExpr::empty()),
vec![0u32; 4],
)]);
let buf = serialize(element_section).expect("Element section to be serialized");
assert_eq!(
buf,
vec![
8u8, 0x01, 0x00, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x00 ]
);
}
#[test]
fn code_section_ser() {
use super::super::Instruction::*;
let code_section = CodeSection::with_bodies(vec![FuncBody::new(
vec![Local::new(1, ValueType::I32)],
Instructions::new(vec![
Block(BlockType::Value(ValueType::I32)),
GetGlobal(0),
End,
End,
]),
)]);
let buf = serialize(code_section).expect("Code section to be serialized");
assert_eq!(
buf,
vec![
11u8, 0x01, 9, 1, 1, 0x7f, 0x02, 0x7f, 0x23, 0x00, 0x0b, 0x0b, ]
);
}
#[test]
fn start_section() {
let section: Section =
deserialize_buffer(&[8u8, 1u8, 0u8]).expect("Start section to deserialize");
if let Section::Start(_) = section {
} else {
panic!("Payload should be a start section");
}
let serialized = serialize(section).expect("Start section to successfully serializen");
assert_eq!(serialized, vec![8u8, 1u8, 0u8]);
}
}