spaces to tabs

This commit is contained in:
NikVolf
2018-01-23 22:47:20 +03:00
parent bb24f2a11a
commit f915a89b9d
36 changed files with 5875 additions and 5876 deletions

View File

@ -11,37 +11,37 @@ use parity_wasm::elements;
fn main() {
// Example binary accepts one parameter which is the output file
// where generated wasm module will be written at the end of execution
let args = env::args().collect::<Vec<_>>();
if args.len() != 2 {
println!("Usage: {} output_file.wasm", args[0]);
return;
}
// Example binary accepts one parameter which is the output file
// where generated wasm module will be written at the end of execution
let args = env::args().collect::<Vec<_>>();
if args.len() != 2 {
println!("Usage: {} output_file.wasm", args[0]);
return;
}
// Main entry for the builder api is the module function
// It returns empty module builder structure which can be further
// appended with various wasm artefacts
let module = builder::module()
// Here we append function to the builder
// function() function returns a function builder attached
// to the module builder.
.function()
// We describe signature for the function via signature()
// function. In our simple example it's just one input
// argument of type 'i32' without return value
.signature().with_param(elements::ValueType::I32).build()
// body() without any further arguments means that the body
// of the function will be empty
.body().build()
// This is the end of the function builder. When `build()` is
// invoked, function builder returns original module builder
// from which it was invoked
.build()
// And finally we finish our module builder to produce actual
// wasm module.
.build();
// Main entry for the builder api is the module function
// It returns empty module builder structure which can be further
// appended with various wasm artefacts
let module = builder::module()
// Here we append function to the builder
// function() function returns a function builder attached
// to the module builder.
.function()
// We describe signature for the function via signature()
// function. In our simple example it's just one input
// argument of type 'i32' without return value
.signature().with_param(elements::ValueType::I32).build()
// body() without any further arguments means that the body
// of the function will be empty
.body().build()
// This is the end of the function builder. When `build()` is
// invoked, function builder returns original module builder
// from which it was invoked
.build()
// And finally we finish our module builder to produce actual
// wasm module.
.build();
// Module structure can be serialzed to produce a valid wasm file
parity_wasm::serialize_to_file(&args[1], module).unwrap();
// Module structure can be serialzed to produce a valid wasm file
parity_wasm::serialize_to_file(&args[1], module).unwrap();
}

View File

@ -7,40 +7,40 @@ use std::env;
fn main() {
// Example executable takes one argument which must
// refernce the existing file with a valid wasm module
let args = env::args().collect::<Vec<_>>();
if args.len() != 2 {
println!("Usage: {} somefile.wasm", args[0]);
return;
}
// Example executable takes one argument which must
// refernce the existing file with a valid wasm module
let args = env::args().collect::<Vec<_>>();
if args.len() != 2 {
println!("Usage: {} somefile.wasm", args[0]);
return;
}
// Here we load module using dedicated for this purpose
// `deserialize_file` function (which works only with modules)
let module = parity_wasm::deserialize_file(&args[1]).expect("Failed to load module");
// Here we load module using dedicated for this purpose
// `deserialize_file` function (which works only with modules)
let module = parity_wasm::deserialize_file(&args[1]).expect("Failed to load module");
// We query module for data section. Note that not every valid
// wasm module must contain a data section. So in case the provided
// module does not contain data section, we panic with an error
let data_section = module.data_section().expect("no data section in module");
// We query module for data section. Note that not every valid
// wasm module must contain a data section. So in case the provided
// module does not contain data section, we panic with an error
let data_section = module.data_section().expect("no data section in module");
// Printing the total count of data segments
println!("Data segments: {}", data_section.entries().len());
// Printing the total count of data segments
println!("Data segments: {}", data_section.entries().len());
let mut index = 0;
for entry in data_section.entries() {
// Printing the details info of each data segment
// see `elements::DataSegment` for more properties
// you can query
println!(" Entry #{}", index);
let mut index = 0;
for entry in data_section.entries() {
// Printing the details info of each data segment
// see `elements::DataSegment` for more properties
// you can query
println!(" Entry #{}", index);
// This shows the initialization member of data segment
// (expression which must resolve in the linear memory location).
println!(" init: {}", entry.offset().code()[0]);
// This shows the initialization member of data segment
// (expression which must resolve in the linear memory location).
println!(" init: {}", entry.offset().code()[0]);
// This shows the total length of the data segment in bytes.
println!(" size: {}", entry.value().len());
// This shows the total length of the data segment in bytes.
println!(" size: {}", entry.value().len());
index += 1;
}
index += 1;
}
}

View File

@ -10,74 +10,74 @@ use parity_wasm::elements::{Internal, External, Type, FunctionType, Module};
// Auxillary function to resolve function type (signature) given it's callable index
fn type_by_index(module: &Module, index: usize) -> FunctionType {
// Demand that function and type section exist. Otherwise, fail with a
// corresponding error.
let function_section = module.function_section().expect("No function section found");
let type_section = module.type_section().expect("No type section found");
// Demand that function and type section exist. Otherwise, fail with a
// corresponding error.
let function_section = module.function_section().expect("No function section found");
let type_section = module.type_section().expect("No type section found");
// This counts the number of _function_ imports listed by the module, excluding
// the globals, since indexing for actual functions for `call` and `export` purposes
// includes both imported and own functions. So we actualy need the imported function count
// to resolve actual index of the given function in own functions list.
let import_section_len: usize = match module.import_section() {
Some(import) =>
import.entries().iter().filter(|entry| match entry.external() {
&External::Function(_) => true,
_ => false,
}).count(),
None => 0,
};
// This counts the number of _function_ imports listed by the module, excluding
// the globals, since indexing for actual functions for `call` and `export` purposes
// includes both imported and own functions. So we actualy need the imported function count
// to resolve actual index of the given function in own functions list.
let import_section_len: usize = match module.import_section() {
Some(import) =>
import.entries().iter().filter(|entry| match entry.external() {
&External::Function(_) => true,
_ => false,
}).count(),
None => 0,
};
// Substract the value queried in the previous step from the provided index
// to get own function index from which we can query type next.
let function_index_in_section = index - import_section_len;
// Substract the value queried in the previous step from the provided index
// to get own function index from which we can query type next.
let function_index_in_section = index - import_section_len;
// Query the own function given we have it's index
let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize;
// Query the own function given we have it's index
let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize;
// Finally, return function type (signature)
match type_section.types()[func_type_ref] {
Type::Function(ref func_type) => func_type.clone(),
}
// Finally, return function type (signature)
match type_section.types()[func_type_ref] {
Type::Function(ref func_type) => func_type.clone(),
}
}
fn main() {
// Example executable takes one argument which must
// refernce the existing file with a valid wasm module
let args: Vec<_> = args().collect();
if args.len() < 2 {
println!("Prints export function names with and their types");
println!("Usage: {} <wasm file>", args[0]);
return;
}
// Example executable takes one argument which must
// refernce the existing file with a valid wasm module
let args: Vec<_> = args().collect();
if args.len() < 2 {
println!("Prints export function names with and their types");
println!("Usage: {} <wasm file>", args[0]);
return;
}
// Here we load module using dedicated for this purpose
// `deserialize_file` function (which works only with modules)
let module = parity_wasm::deserialize_file(&args[1]).expect("File to be deserialized");
// Here we load module using dedicated for this purpose
// `deserialize_file` function (which works only with modules)
let module = parity_wasm::deserialize_file(&args[1]).expect("File to be deserialized");
// Query the export section from the loaded module. Note that not every
// wasm module obliged to contain export section. So in case there is no
// any export section, we panic with the corresponding error.
let export_section = module.export_section().expect("No export section found");
// Query the export section from the loaded module. Note that not every
// wasm module obliged to contain export section. So in case there is no
// any export section, we panic with the corresponding error.
let export_section = module.export_section().expect("No export section found");
// Process all exports, leaving only those which reference the internal function
// of the wasm module
let exports: Vec<String> = export_section.entries().iter()
.filter_map(|entry|
// This is match on export variant, which can be function, global,table or memory
// We are interested only in functions for an example
match *entry.internal() {
// Return function export name (return by field() function and it's index)
Internal::Function(index) => Some((entry.field(), index as usize)),
_ => None
})
// Another map to resolve function signature index given it's internal index and return
// the printable string of the export
.map(|(field, index)| format!("{:}: {:?}", field, type_by_index(&module, index).params())).collect();
// Process all exports, leaving only those which reference the internal function
// of the wasm module
let exports: Vec<String> = export_section.entries().iter()
.filter_map(|entry|
// This is match on export variant, which can be function, global,table or memory
// We are interested only in functions for an example
match *entry.internal() {
// Return function export name (return by field() function and it's index)
Internal::Function(index) => Some((entry.field(), index as usize)),
_ => None
})
// Another map to resolve function signature index given it's internal index and return
// the printable string of the export
.map(|(field, index)| format!("{:}: {:?}", field, type_by_index(&module, index).params())).collect();
// Print the result
for export in exports {
println!("{:}", export);
}
// Print the result
for export in exports {
println!("{:}", export);
}
}

View File

@ -4,40 +4,40 @@ use std::env;
use parity_wasm::elements::Section;
fn main() {
let args = env::args().collect::<Vec<_>>();
if args.len() != 2 {
println!("Usage: {} somefile.wasm", args[0]);
return;
}
let args = env::args().collect::<Vec<_>>();
if args.len() != 2 {
println!("Usage: {} somefile.wasm", args[0]);
return;
}
let module = parity_wasm::deserialize_file(&args[1]).expect("Failed to load module");
let module = parity_wasm::deserialize_file(&args[1]).expect("Failed to load module");
println!("Module sections: {}", module.sections().len());
println!("Module sections: {}", module.sections().len());
for section in module.sections() {
match *section {
Section::Import(ref import_section) => {
println!(" Imports: {}", import_section.entries().len());
import_section.entries().iter().map(|e| println!(" {}.{}", e.module(), e.field())).count();
},
Section::Export(ref exports_section) => {
println!(" Exports: {}", exports_section.entries().len());
exports_section.entries().iter().map(|e| println!(" {}", e.field())).count();
},
Section::Function(ref function_section) => {
println!(" Functions: {}", function_section.entries().len());
},
Section::Type(ref type_section) => {
println!(" Types: {}", type_section.types().len());
},
Section::Global(ref globals_section) => {
println!(" Globals: {}", globals_section.entries().len());
},
Section::Data(ref data_section) if data_section.entries().len() > 0 => {
let data = &data_section.entries()[0];
println!(" Data size: {}", data.value().len());
},
_ => {},
}
}
for section in module.sections() {
match *section {
Section::Import(ref import_section) => {
println!(" Imports: {}", import_section.entries().len());
import_section.entries().iter().map(|e| println!(" {}.{}", e.module(), e.field())).count();
},
Section::Export(ref exports_section) => {
println!(" Exports: {}", exports_section.entries().len());
exports_section.entries().iter().map(|e| println!(" {}", e.field())).count();
},
Section::Function(ref function_section) => {
println!(" Functions: {}", function_section.entries().len());
},
Section::Type(ref type_section) => {
println!(" Types: {}", type_section.types().len());
},
Section::Global(ref globals_section) => {
println!(" Globals: {}", globals_section.entries().len());
},
Section::Data(ref data_section) if data_section.entries().len() > 0 => {
let data = &data_section.entries()[0];
println!(" Data size: {}", data.value().len());
},
_ => {},
}
}
}

View File

@ -6,58 +6,58 @@ use parity_wasm::elements;
use parity_wasm::builder;
pub fn inject_nop(opcodes: &mut elements::Opcodes) {
use parity_wasm::elements::Opcode::*;
let opcodes = opcodes.elements_mut();
let mut position = 0;
loop {
let need_inject = match &opcodes[position] {
&Block(_) | &If(_) => true,
_ => false,
};
if need_inject {
opcodes.insert(position + 1, Nop);
}
use parity_wasm::elements::Opcode::*;
let opcodes = opcodes.elements_mut();
let mut position = 0;
loop {
let need_inject = match &opcodes[position] {
&Block(_) | &If(_) => true,
_ => false,
};
if need_inject {
opcodes.insert(position + 1, Nop);
}
position += 1;
if position >= opcodes.len() {
break;
}
}
position += 1;
if position >= opcodes.len() {
break;
}
}
}
fn main() {
let args = env::args().collect::<Vec<_>>();
if args.len() != 3 {
println!("Usage: {} input_file.wasm output_file.wasm", args[0]);
return;
}
let args = env::args().collect::<Vec<_>>();
if args.len() != 3 {
println!("Usage: {} input_file.wasm output_file.wasm", args[0]);
return;
}
let mut module = parity_wasm::deserialize_file(&args[1]).unwrap();
let mut module = parity_wasm::deserialize_file(&args[1]).unwrap();
for section in module.sections_mut() {
match section {
&mut elements::Section::Code(ref mut code_section) => {
for ref mut func_body in code_section.bodies_mut() {
inject_nop(func_body.code_mut());
}
},
_ => { }
}
}
for section in module.sections_mut() {
match section {
&mut elements::Section::Code(ref mut code_section) => {
for ref mut func_body in code_section.bodies_mut() {
inject_nop(func_body.code_mut());
}
},
_ => { }
}
}
let mut build = builder::from_module(module);
let import_sig = build.push_signature(
builder::signature()
.param().i32()
.param().i32()
.return_type().i32()
.build_sig()
);
let build = build.import()
.module("env")
.field("log")
.external().func(import_sig)
.build();
let mut build = builder::from_module(module);
let import_sig = build.push_signature(
builder::signature()
.param().i32()
.param().i32()
.return_type().i32()
.build_sig()
);
let build = build.import()
.module("env")
.field("log")
.external().func(import_sig)
.build();
parity_wasm::serialize_to_file(&args[2], build.build()).unwrap();
parity_wasm::serialize_to_file(&args[2], build.build()).unwrap();
}

View File

@ -7,30 +7,30 @@ use std::env::args;
use parity_wasm::ModuleInstanceInterface;
fn main() {
let args: Vec<_> = args().collect();
if args.len() != 3 {
println!("Usage: {} <wasm file> <arg>", args[0]);
println!(" wasm file should contain exported `_call` function with single I32 argument");
return;
}
let args: Vec<_> = args().collect();
if args.len() != 3 {
println!("Usage: {} <wasm file> <arg>", args[0]);
println!(" wasm file should contain exported `_call` function with single I32 argument");
return;
}
// Intrepreter initialization.
let program = parity_wasm::ProgramInstance::new();
// Intrepreter initialization.
let program = parity_wasm::ProgramInstance::new();
// Here we load module using dedicated for this purpose
// `deserialize_file` function (which works only with modules)
let module = parity_wasm::deserialize_file(&args[1]).expect("Failed to load module");
// Here we load module using dedicated for this purpose
// `deserialize_file` function (which works only with modules)
let module = parity_wasm::deserialize_file(&args[1]).expect("Failed to load module");
// Intialize deserialized module. It adds module into It expects 3 parameters:
// - a name for the module
// - a module declaration
// - "main" module doesn't import native module(s) this is why we don't need to provide external native modules here
// This test shows how to implement native module https://github.com/NikVolf/parity-wasm/blob/master/src/interpreter/tests/basics.rs#L197
let module = program.add_module("main", module, None).expect("Failed to initialize module");
// Intialize deserialized module. It adds module into It expects 3 parameters:
// - a name for the module
// - a module declaration
// - "main" module doesn't import native module(s) this is why we don't need to provide external native modules here
// This test shows how to implement native module https://github.com/NikVolf/parity-wasm/blob/master/src/interpreter/tests/basics.rs#L197
let module = program.add_module("main", module, None).expect("Failed to initialize module");
// The argument should be parsable as a valid integer
let argument: i32 = args[2].parse().expect("Integer argument required");
// The argument should be parsable as a valid integer
let argument: i32 = args[2].parse().expect("Integer argument required");
// "_call" export of function to be executed with an i32 argument and prints the result of execution
println!("Result: {:?}", module.execute_export("_call", vec![parity_wasm::RuntimeValue::I32(argument)].into()));
// "_call" export of function to be executed with an i32 argument and prints the result of execution
println!("Result: {:?}", module.execute_export("_call", vec![parity_wasm::RuntimeValue::I32(argument)].into()));
}

View File

@ -5,80 +5,79 @@ use std::env::args;
use parity_wasm::{interpreter, ModuleInstanceInterface, RuntimeValue};
use parity_wasm::elements::{Internal, External, Type, FunctionType, ValueType};
fn main() {
let args: Vec<_> = args().collect();
if args.len() < 3 {
println!("Usage: {} <wasm file> <exported func> [<arg>...]", args[0]);
return;
}
let func_name = &args[2];
let (_, program_args) = args.split_at(3);
let args: Vec<_> = args().collect();
if args.len() < 3 {
println!("Usage: {} <wasm file> <exported func> [<arg>...]", args[0]);
return;
}
let func_name = &args[2];
let (_, program_args) = args.split_at(3);
// Intrepreter initialization.
let program = parity_wasm::ProgramInstance::new();
// Intrepreter initialization.
let program = parity_wasm::ProgramInstance::new();
let module = parity_wasm::deserialize_file(&args[1]).expect("File to be deserialized");
let module = parity_wasm::deserialize_file(&args[1]).expect("File to be deserialized");
// Extracts call arguments from command-line arguments
let execution_params = {
// Export section has an entry with a func_name with an index inside a module
let export_section = module.export_section().expect("No export section found");
// It's a section with function declarations (which are references to the type section entries)
let function_section = module.function_section().expect("No function section found");
// Type section stores function types which are referenced by function_section entries
let type_section = module.type_section().expect("No type section found");
// Extracts call arguments from command-line arguments
let execution_params = {
// Export section has an entry with a func_name with an index inside a module
let export_section = module.export_section().expect("No export section found");
// It's a section with function declarations (which are references to the type section entries)
let function_section = module.function_section().expect("No function section found");
// Type section stores function types which are referenced by function_section entries
let type_section = module.type_section().expect("No type section found");
// Given function name used to find export section entry which contains
// an `internal` field which points to the index in the function index space
let found_entry = export_section.entries().iter()
.find(|entry| func_name == entry.field()).expect(&format!("No export with name {} found", func_name));
// Given function name used to find export section entry which contains
// an `internal` field which points to the index in the function index space
let found_entry = export_section.entries().iter()
.find(|entry| func_name == entry.field()).expect(&format!("No export with name {} found", func_name));
// Function index in the function index space (internally-defined + imported)
let function_index: usize = match found_entry.internal() {
&Internal::Function(index) => index as usize,
_ => panic!("Founded export is not a function"),
};
// Function index in the function index space (internally-defined + imported)
let function_index: usize = match found_entry.internal() {
&Internal::Function(index) => index as usize,
_ => panic!("Founded export is not a function"),
};
// We need to count import section entries (functions only!) to subtract it from function_index
// and obtain the index within the function section
let import_section_len: usize = match module.import_section() {
Some(import) =>
import.entries().iter().filter(|entry| match entry.external() {
&External::Function(_) => true,
_ => false,
}).count(),
None => 0,
};
// We need to count import section entries (functions only!) to subtract it from function_index
// and obtain the index within the function section
let import_section_len: usize = match module.import_section() {
Some(import) =>
import.entries().iter().filter(|entry| match entry.external() {
&External::Function(_) => true,
_ => false,
}).count(),
None => 0,
};
// Calculates a function index within module's function section
let function_index_in_section = function_index - import_section_len;
// Calculates a function index within module's function section
let function_index_in_section = function_index - import_section_len;
// Getting a type reference from a function section entry
let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize;
// Getting a type reference from a function section entry
let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize;
// Use the reference to get an actual function type
let function_type: &FunctionType = match &type_section.types()[func_type_ref] {
&Type::Function(ref func_type) => func_type,
};
// Use the reference to get an actual function type
let function_type: &FunctionType = match &type_section.types()[func_type_ref] {
&Type::Function(ref func_type) => func_type,
};
// Parses arguments and constructs runtime values in correspondence of their types
let args: Vec<RuntimeValue> = function_type.params().iter().enumerate().map(|(i, value)| match value {
&ValueType::I32 => RuntimeValue::I32(program_args[i].parse::<i32>().expect(&format!("Can't parse arg #{} as i32", program_args[i]))),
&ValueType::I64 => RuntimeValue::I64(program_args[i].parse::<i64>().expect(&format!("Can't parse arg #{} as i64", program_args[i]))),
&ValueType::F32 => RuntimeValue::F32(program_args[i].parse::<f32>().expect(&format!("Can't parse arg #{} as f32", program_args[i]))),
&ValueType::F64 => RuntimeValue::F64(program_args[i].parse::<f64>().expect(&format!("Can't parse arg #{} as f64", program_args[i]))),
}).collect();
// Parses arguments and constructs runtime values in correspondence of their types
let args: Vec<RuntimeValue> = function_type.params().iter().enumerate().map(|(i, value)| match value {
&ValueType::I32 => RuntimeValue::I32(program_args[i].parse::<i32>().expect(&format!("Can't parse arg #{} as i32", program_args[i]))),
&ValueType::I64 => RuntimeValue::I64(program_args[i].parse::<i64>().expect(&format!("Can't parse arg #{} as i64", program_args[i]))),
&ValueType::F32 => RuntimeValue::F32(program_args[i].parse::<f32>().expect(&format!("Can't parse arg #{} as f32", program_args[i]))),
&ValueType::F64 => RuntimeValue::F64(program_args[i].parse::<f64>().expect(&format!("Can't parse arg #{} as f64", program_args[i]))),
}).collect();
interpreter::ExecutionParams::from(args)
};
interpreter::ExecutionParams::from(args)
};
// Intialize deserialized module. It adds module into It expects 3 parameters:
// - a name for the module
// - a module declaration
// - "main" module doesn't import native module(s) this is why we don't need to provide external native modules here
// This test shows how to implement native module https://github.com/NikVolf/parity-wasm/blob/master/src/interpreter/tests/basics.rs#L197
let module = program.add_module("main", module, None).expect("Failed to initialize module");
// Intialize deserialized module. It adds module into It expects 3 parameters:
// - a name for the module
// - a module declaration
// - "main" module doesn't import native module(s) this is why we don't need to provide external native modules here
// This test shows how to implement native module https://github.com/NikVolf/parity-wasm/blob/master/src/interpreter/tests/basics.rs#L197
let module = program.add_module("main", module, None).expect("Failed to initialize module");
println!("Result: {:?}", module.execute_export(func_name, execution_params).expect(""));
println!("Result: {:?}", module.execute_export(func_name, execution_params).expect(""));
}

View File

@ -3,24 +3,24 @@ extern crate parity_wasm;
use std::env;
fn main() {
let args = env::args().collect::<Vec<_>>();
if args.len() != 3 {
println!("Usage: {} in.wasm out.wasm", args[0]);
return;
}
let args = env::args().collect::<Vec<_>>();
if args.len() != 3 {
println!("Usage: {} in.wasm out.wasm", args[0]);
return;
}
let module = match parity_wasm::deserialize_file(&args[1])
.expect("Failed to load module")
.parse_names()
{
Ok(m) => m,
Err((errors, m)) => {
for (index, error) in errors.into_iter() {
println!("Custom section #{} parse error: {:?}", index, error);
}
m
}
};
let module = match parity_wasm::deserialize_file(&args[1])
.expect("Failed to load module")
.parse_names()
{
Ok(m) => m,
Err((errors, m)) => {
for (index, error) in errors.into_iter() {
println!("Custom section #{} parse error: {:?}", index, error);
}
m
}
};
parity_wasm::serialize_to_file(&args[2], module).expect("Failed to write module");
parity_wasm::serialize_to_file(&args[2], module).expect("Failed to write module");
}

View File

@ -5,15 +5,15 @@ extern crate parity_wasm;
extern crate binaryen;
fuzz_target!(|data: &[u8]| {
let binaryen_module = binaryen::tools::translate_to_fuzz(data);
let binaryen_module = binaryen::tools::translate_to_fuzz(data);
// enable binaryen's validation if in doubt.
// assert!(binaryen_module.is_valid());
// enable binaryen's validation if in doubt.
// assert!(binaryen_module.is_valid());
let wasm = binaryen_module.write();
let wasm = binaryen_module.write();
let _module: parity_wasm::elements::Module = parity_wasm::deserialize_buffer(&wasm)
.expect(
"deserialize output of wasm-opt, indicating possible bug in deserializer",
);
let _module: parity_wasm::elements::Module = parity_wasm::deserialize_buffer(&wasm)
.expect(
"deserialize output of wasm-opt, indicating possible bug in deserializer",
);
});

View File

@ -1,16 +1,16 @@
macro_rules! run_test {
($label: expr, $test_name: ident, fail) => (
#[test]
fn $test_name() {
::run::failing_spec($label)
}
);
($label: expr, $test_name: ident) => (
#[test]
fn $test_name() {
::run::spec($label)
}
);
($label: expr, $test_name: ident, fail) => (
#[test]
fn $test_name() {
::run::failing_spec($label)
}
);
($label: expr, $test_name: ident) => (
#[test]
fn $test_name() {
::run::spec($label)
}
);
}
run_test!("address-offset-range.fail", wasm_address_offset_range_fail, fail);

View File

@ -10,276 +10,276 @@ use serde_json;
use test;
use parity_wasm::{self, elements, builder};
use parity_wasm::interpreter::{
RuntimeValue,
ProgramInstance, ModuleInstance,
ItemIndex, ExportEntryType,
Error as InterpreterError,
RuntimeValue,
ProgramInstance, ModuleInstance,
ItemIndex, ExportEntryType,
Error as InterpreterError,
};
fn spec_test_module() -> elements::Module {
builder::module()
.function().signature().build().body().build().build()
.function().signature().param().i32().build().body().build().build()
.function().signature().param().i64().build().body().build().build()
.function().signature().param().f32().build().body().build().build()
.function().signature().param().f64().build().body().build().build()
.function().signature().param().i32().param().f32().build().body().build().build()
.function().signature().param().f64().param().f64().build().body().build().build()
.global().value_type().i32().init_expr(elements::Opcode::I32Const(666)).build()
.with_table(elements::TableType::new(100, None))
.memory().with_min(1).with_max(Some(2)).build()
.export().field("print").internal().func(0).build()
.export().field("print").internal().func(1).build()
.export().field("print").internal().func(2).build()
.export().field("print").internal().func(3).build()
.export().field("print").internal().func(4).build()
.export().field("print").internal().func(5).build()
.export().field("print").internal().func(6).build()
.export().field("global").internal().global(0).build()
.export().field("table").internal().table(0).build()
.export().field("memory").internal().memory(0).build()
.build()
builder::module()
.function().signature().build().body().build().build()
.function().signature().param().i32().build().body().build().build()
.function().signature().param().i64().build().body().build().build()
.function().signature().param().f32().build().body().build().build()
.function().signature().param().f64().build().body().build().build()
.function().signature().param().i32().param().f32().build().body().build().build()
.function().signature().param().f64().param().f64().build().body().build().build()
.global().value_type().i32().init_expr(elements::Opcode::I32Const(666)).build()
.with_table(elements::TableType::new(100, None))
.memory().with_min(1).with_max(Some(2)).build()
.export().field("print").internal().func(0).build()
.export().field("print").internal().func(1).build()
.export().field("print").internal().func(2).build()
.export().field("print").internal().func(3).build()
.export().field("print").internal().func(4).build()
.export().field("print").internal().func(5).build()
.export().field("print").internal().func(6).build()
.export().field("global").internal().global(0).build()
.export().field("table").internal().table(0).build()
.export().field("memory").internal().memory(0).build()
.build()
}
fn load_module(base_dir: &str, path: &str, name: &Option<String>, program: &ProgramInstance) -> Arc<ModuleInstance> {
let module = try_deserialize(base_dir, path).expect(&format!("Wasm file {} failed to load", path));
let module = try_deserialize(base_dir, path).expect(&format!("Wasm file {} failed to load", path));
program.add_module("spectest", spec_test_module(), None).expect("Failed adding 'spectest' module");
program.add_module("spectest", spec_test_module(), None).expect("Failed adding 'spectest' module");
let module_name = name.as_ref().map(|s| s.as_ref()).unwrap_or("wasm_test").trim_left_matches('$');
let module_instance = program.add_module(module_name, module, None).expect(&format!("Failed adding {} module", module_name));
module_instance
let module_name = name.as_ref().map(|s| s.as_ref()).unwrap_or("wasm_test").trim_left_matches('$');
let module_instance = program.add_module(module_name, module, None).expect(&format!("Failed adding {} module", module_name));
module_instance
}
fn try_deserialize(base_dir: &str, module_path: &str) -> Result<elements::Module, elements::Error> {
let mut wasm_path = PathBuf::from(base_dir.clone());
wasm_path.push(module_path);
parity_wasm::deserialize_file(&wasm_path)
let mut wasm_path = PathBuf::from(base_dir.clone());
wasm_path.push(module_path);
parity_wasm::deserialize_file(&wasm_path)
}
fn try_load(base_dir: &str, module_path: &str) -> Result<(), InterpreterError> {
let module = try_deserialize(base_dir, module_path).map_err(|e| parity_wasm::interpreter::Error::Program(format!("{:?}", e)))?;
let program = ProgramInstance::new();
program.add_module("try_load", module, None).map(|_| ())
let module = try_deserialize(base_dir, module_path).map_err(|e| parity_wasm::interpreter::Error::Program(format!("{:?}", e)))?;
let program = ProgramInstance::new();
program.add_module("try_load", module, None).map(|_| ())
}
fn runtime_value(test_val: &test::RuntimeValue) -> parity_wasm::RuntimeValue {
match test_val.value_type.as_ref() {
"i32" => {
let unsigned: u32 = test_val.value.parse().expect("Literal parse error");
parity_wasm::RuntimeValue::I32(unsigned as i32)
},
"i64" => {
let unsigned: u64 = test_val.value.parse().expect("Literal parse error");
parity_wasm::RuntimeValue::I64(unsigned as i64)
},
"f32" => {
let unsigned: u32 = test_val.value.parse().expect("Literal parse error");
parity_wasm::RuntimeValue::decode_f32(unsigned)
},
"f64" => {
let unsigned: u64 = test_val.value.parse().expect("Literal parse error");
parity_wasm::RuntimeValue::decode_f64(unsigned)
},
_ => panic!("Unknwon runtime value type"),
}
match test_val.value_type.as_ref() {
"i32" => {
let unsigned: u32 = test_val.value.parse().expect("Literal parse error");
parity_wasm::RuntimeValue::I32(unsigned as i32)
},
"i64" => {
let unsigned: u64 = test_val.value.parse().expect("Literal parse error");
parity_wasm::RuntimeValue::I64(unsigned as i64)
},
"f32" => {
let unsigned: u32 = test_val.value.parse().expect("Literal parse error");
parity_wasm::RuntimeValue::decode_f32(unsigned)
},
"f64" => {
let unsigned: u64 = test_val.value.parse().expect("Literal parse error");
parity_wasm::RuntimeValue::decode_f64(unsigned)
},
_ => panic!("Unknwon runtime value type"),
}
}
fn runtime_values(test_vals: &[test::RuntimeValue]) -> Vec<parity_wasm::RuntimeValue> {
test_vals.iter().map(runtime_value).collect::<Vec<parity_wasm::RuntimeValue>>()
test_vals.iter().map(runtime_value).collect::<Vec<parity_wasm::RuntimeValue>>()
}
fn run_action(program: &ProgramInstance, action: &test::Action)
-> Result<Option<parity_wasm::RuntimeValue>, InterpreterError>
-> Result<Option<parity_wasm::RuntimeValue>, InterpreterError>
{
match *action {
test::Action::Invoke { ref module, ref field, ref args } => {
let module = module.clone().unwrap_or("wasm_test".into());
let module = module.trim_left_matches('$');
let module = program.module(&module).expect(&format!("Expected program to have loaded module {}", module));
module.execute_export(&jstring_to_rstring(field), runtime_values(args).into())
},
test::Action::Get { ref module, ref field, .. } => {
let module = module.clone().unwrap_or("wasm_test".into());
let module = module.trim_left_matches('$');
let module = program.module(&module).expect(&format!("Expected program to have loaded module {}", module));
let field = jstring_to_rstring(&field);
match *action {
test::Action::Invoke { ref module, ref field, ref args } => {
let module = module.clone().unwrap_or("wasm_test".into());
let module = module.trim_left_matches('$');
let module = program.module(&module).expect(&format!("Expected program to have loaded module {}", module));
module.execute_export(&jstring_to_rstring(field), runtime_values(args).into())
},
test::Action::Get { ref module, ref field, .. } => {
let module = module.clone().unwrap_or("wasm_test".into());
let module = module.trim_left_matches('$');
let module = program.module(&module).expect(&format!("Expected program to have loaded module {}", module));
let field = jstring_to_rstring(&field);
module.export_entry(field.as_ref(), &ExportEntryType::Any)
.and_then(|i| match i {
elements::Internal::Global(global_index) => Ok(ItemIndex::IndexSpace(global_index)),
_ => Err(InterpreterError::Global(format!("Expected to have exported global with name {}", field))),
})
.and_then(|g| module.global(g, None, None).map(|g| Some(g.get())))
}
}
module.export_entry(field.as_ref(), &ExportEntryType::Any)
.and_then(|i| match i {
elements::Internal::Global(global_index) => Ok(ItemIndex::IndexSpace(global_index)),
_ => Err(InterpreterError::Global(format!("Expected to have exported global with name {}", field))),
})
.and_then(|g| module.global(g, None, None).map(|g| Some(g.get())))
}
}
}
pub struct FixtureParams {
failing: bool,
json: String,
failing: bool,
json: String,
}
pub fn run_wast2wasm(name: &str) -> FixtureParams {
let outdir = env::var("OUT_DIR").unwrap();
let outdir = env::var("OUT_DIR").unwrap();
let mut wast2wasm_path = PathBuf::from(outdir.clone());
wast2wasm_path.push("bin");
wast2wasm_path.push("wast2wasm");
let mut wast2wasm_path = PathBuf::from(outdir.clone());
wast2wasm_path.push("bin");
wast2wasm_path.push("wast2wasm");
let mut json_spec_path = PathBuf::from(outdir.clone());
json_spec_path.push(&format!("{}.json", name));
let mut json_spec_path = PathBuf::from(outdir.clone());
json_spec_path.push(&format!("{}.json", name));
let wast2wasm_output = Command::new(wast2wasm_path)
.arg("--spec")
.arg("-o")
.arg(&json_spec_path)
.arg(&format!("./wabt/third_party/testsuite/{}.wast", name))
.output()
.expect("Failed to execute process");
let wast2wasm_output = Command::new(wast2wasm_path)
.arg("--spec")
.arg("-o")
.arg(&json_spec_path)
.arg(&format!("./wabt/third_party/testsuite/{}.wast", name))
.output()
.expect("Failed to execute process");
FixtureParams {
json: json_spec_path.to_str().unwrap().to_owned(),
failing: {
if !wast2wasm_output.status.success() {
println!("wasm2wast error code: {}", wast2wasm_output.status);
println!("wasm2wast stdout: {}", String::from_utf8_lossy(&wast2wasm_output.stdout));
println!("wasm2wast stderr: {}", String::from_utf8_lossy(&wast2wasm_output.stderr));
true
} else {
false
}
}
}
FixtureParams {
json: json_spec_path.to_str().unwrap().to_owned(),
failing: {
if !wast2wasm_output.status.success() {
println!("wasm2wast error code: {}", wast2wasm_output.status);
println!("wasm2wast stdout: {}", String::from_utf8_lossy(&wast2wasm_output.stdout));
println!("wasm2wast stderr: {}", String::from_utf8_lossy(&wast2wasm_output.stderr));
true
} else {
false
}
}
}
}
pub fn failing_spec(name: &str) {
let fixture = run_wast2wasm(name);
if !fixture.failing {
panic!("wasm2wast expected to fail, but terminated normally");
}
let fixture = run_wast2wasm(name);
if !fixture.failing {
panic!("wasm2wast expected to fail, but terminated normally");
}
}
pub fn spec(name: &str) {
let outdir = env::var("OUT_DIR").unwrap();
let outdir = env::var("OUT_DIR").unwrap();
let fixture = run_wast2wasm(name);
if fixture.failing {
panic!("wasm2wast terminated abnormally, expected to success");
}
let fixture = run_wast2wasm(name);
if fixture.failing {
panic!("wasm2wast terminated abnormally, expected to success");
}
let mut f = File::open(&fixture.json)
.expect(&format!("Failed to load json file {}", &fixture.json));
let spec: test::Spec = serde_json::from_reader(&mut f).expect("Failed to deserialize JSON file");
let mut f = File::open(&fixture.json)
.expect(&format!("Failed to load json file {}", &fixture.json));
let spec: test::Spec = serde_json::from_reader(&mut f).expect("Failed to deserialize JSON file");
let program = ProgramInstance::new();
let mut last_module = None;
for command in &spec.commands {
println!("command {:?}", command);
match command {
&test::Command::Module { ref name, ref filename, .. } => {
last_module = Some(load_module(&outdir, &filename, &name, &program));
},
&test::Command::AssertReturn { line, ref action, ref expected } => {
let result = run_action(&program, action);
match result {
Ok(result) => {
let spec_expected = runtime_values(expected);
let actual_result = result.into_iter().collect::<Vec<parity_wasm::RuntimeValue>>();
for (actual_result, spec_expected) in actual_result.iter().zip(spec_expected.iter()) {
assert_eq!(actual_result.variable_type(), spec_expected.variable_type());
// f32::NAN != f32::NAN
match spec_expected {
&RuntimeValue::F32(val) if val.is_nan() => match actual_result {
&RuntimeValue::F32(val) => assert!(val.is_nan()),
_ => unreachable!(), // checked above that types are same
},
&RuntimeValue::F64(val) if val.is_nan() => match actual_result {
&RuntimeValue::F64(val) => assert!(val.is_nan()),
_ => unreachable!(), // checked above that types are same
},
spec_expected @ _ => assert_eq!(actual_result, spec_expected),
}
}
println!("assert_return at line {} - success", line);
},
Err(e) => {
panic!("Expected action to return value, got error: {:?}", e);
}
}
},
&test::Command::AssertReturnCanonicalNan { line, ref action } | &test::Command::AssertReturnArithmeticNan { line, ref action } => {
let result = run_action(&program, action);
match result {
Ok(result) => {
for actual_result in result.into_iter().collect::<Vec<parity_wasm::RuntimeValue>>() {
match actual_result {
RuntimeValue::F32(val) => if !val.is_nan() { panic!("Expected nan value, got {:?}", val) },
RuntimeValue::F64(val) => if !val.is_nan() { panic!("Expected nan value, got {:?}", val) },
val @ _ => panic!("Expected action to return float value, got {:?}", val),
}
}
println!("assert_return_nan at line {} - success", line);
},
Err(e) => {
panic!("Expected action to return value, got error: {:?}", e);
}
}
},
&test::Command::AssertExhaustion { line, ref action, .. } => {
let result = run_action(&program, action);
match result {
Ok(result) => panic!("Expected exhaustion, got result: {:?}", result),
Err(e) => println!("assert_exhaustion at line {} - success ({:?})", line, e),
}
},
&test::Command::AssertTrap { line, ref action, .. } => {
let result = run_action(&program, action);
match result {
Ok(result) => {
panic!("Expected action to result in a trap, got result: {:?}", result);
},
Err(e) => {
println!("assert_trap at line {} - success ({:?})", line, e);
}
}
},
&test::Command::AssertInvalid { line, ref filename, .. }
| &test::Command::AssertMalformed { line, ref filename, .. }
| &test::Command::AssertUnlinkable { line, ref filename, .. }
=> {
let module_load = try_load(&outdir, filename);
match module_load {
Ok(_) => {
panic!("Expected invalid module definition, got some module!")
},
Err(e) => {
println!("assert_invalid at line {} - success ({:?})", line, e)
}
}
},
&test::Command::AssertUninstantiable { line, ref filename, .. } => {
match try_load(&outdir, &filename) {
Ok(_) => panic!("Expected error running start function at line {}", line),
Err(e) => println!("assert_uninstantiable - success ({:?})", e),
}
},
&test::Command::Register { ref name, ref as_name, .. } => {
match name {
&Some(ref name) => assert_eq!(name.trim_left_matches('$'), as_name), // we have already registered this module without $ prefix
&None => program.insert_loaded_module(as_name, last_module.take().expect("Last module must be set for this command")).map(|_| ()).unwrap(),
}
},
&test::Command::Action { line, ref action } => {
match run_action(&program, action) {
Ok(_) => { },
Err(e) => {
panic!("Failed to invoke action at line {}: {:?}", line, e)
}
}
},
}
}
let program = ProgramInstance::new();
let mut last_module = None;
for command in &spec.commands {
println!("command {:?}", command);
match command {
&test::Command::Module { ref name, ref filename, .. } => {
last_module = Some(load_module(&outdir, &filename, &name, &program));
},
&test::Command::AssertReturn { line, ref action, ref expected } => {
let result = run_action(&program, action);
match result {
Ok(result) => {
let spec_expected = runtime_values(expected);
let actual_result = result.into_iter().collect::<Vec<parity_wasm::RuntimeValue>>();
for (actual_result, spec_expected) in actual_result.iter().zip(spec_expected.iter()) {
assert_eq!(actual_result.variable_type(), spec_expected.variable_type());
// f32::NAN != f32::NAN
match spec_expected {
&RuntimeValue::F32(val) if val.is_nan() => match actual_result {
&RuntimeValue::F32(val) => assert!(val.is_nan()),
_ => unreachable!(), // checked above that types are same
},
&RuntimeValue::F64(val) if val.is_nan() => match actual_result {
&RuntimeValue::F64(val) => assert!(val.is_nan()),
_ => unreachable!(), // checked above that types are same
},
spec_expected @ _ => assert_eq!(actual_result, spec_expected),
}
}
println!("assert_return at line {} - success", line);
},
Err(e) => {
panic!("Expected action to return value, got error: {:?}", e);
}
}
},
&test::Command::AssertReturnCanonicalNan { line, ref action } | &test::Command::AssertReturnArithmeticNan { line, ref action } => {
let result = run_action(&program, action);
match result {
Ok(result) => {
for actual_result in result.into_iter().collect::<Vec<parity_wasm::RuntimeValue>>() {
match actual_result {
RuntimeValue::F32(val) => if !val.is_nan() { panic!("Expected nan value, got {:?}", val) },
RuntimeValue::F64(val) => if !val.is_nan() { panic!("Expected nan value, got {:?}", val) },
val @ _ => panic!("Expected action to return float value, got {:?}", val),
}
}
println!("assert_return_nan at line {} - success", line);
},
Err(e) => {
panic!("Expected action to return value, got error: {:?}", e);
}
}
},
&test::Command::AssertExhaustion { line, ref action, .. } => {
let result = run_action(&program, action);
match result {
Ok(result) => panic!("Expected exhaustion, got result: {:?}", result),
Err(e) => println!("assert_exhaustion at line {} - success ({:?})", line, e),
}
},
&test::Command::AssertTrap { line, ref action, .. } => {
let result = run_action(&program, action);
match result {
Ok(result) => {
panic!("Expected action to result in a trap, got result: {:?}", result);
},
Err(e) => {
println!("assert_trap at line {} - success ({:?})", line, e);
}
}
},
&test::Command::AssertInvalid { line, ref filename, .. }
| &test::Command::AssertMalformed { line, ref filename, .. }
| &test::Command::AssertUnlinkable { line, ref filename, .. }
=> {
let module_load = try_load(&outdir, filename);
match module_load {
Ok(_) => {
panic!("Expected invalid module definition, got some module!")
},
Err(e) => {
println!("assert_invalid at line {} - success ({:?})", line, e)
}
}
},
&test::Command::AssertUninstantiable { line, ref filename, .. } => {
match try_load(&outdir, &filename) {
Ok(_) => panic!("Expected error running start function at line {}", line),
Err(e) => println!("assert_uninstantiable - success ({:?})", e),
}
},
&test::Command::Register { ref name, ref as_name, .. } => {
match name {
&Some(ref name) => assert_eq!(name.trim_left_matches('$'), as_name), // we have already registered this module without $ prefix
&None => program.insert_loaded_module(as_name, last_module.take().expect("Last module must be set for this command")).map(|_| ()).unwrap(),
}
},
&test::Command::Action { line, ref action } => {
match run_action(&program, action) {
Ok(_) => { },
Err(e) => {
panic!("Failed to invoke action at line {}: {:?}", line, e)
}
}
},
}
}
}
// Convert json string to correct rust UTF8 string.
@ -287,7 +287,7 @@ pub fn spec(name: &str) {
// It is incorrect. Correct BOM representation in json is "\uFEFF" => we need to do a double utf8-parse here.
// This conversion is incorrect in general case (casting char to u8)!!!
fn jstring_to_rstring(jstring: &str) -> String {
let jstring_chars: Vec<u8> = jstring.chars().map(|c| c as u8).collect();
let rstring = String::from_utf8(jstring_chars).unwrap();
rstring
let jstring_chars: Vec<u8> = jstring.chars().map(|c| c as u8).collect();
let rstring = String::from_utf8(jstring_chars).unwrap();
rstring
}

View File

@ -2,103 +2,103 @@
#[derive(Deserialize, Debug)]
pub struct RuntimeValue {
#[serde(rename = "type")]
pub value_type: String,
pub value: String,
#[serde(rename = "type")]
pub value_type: String,
pub value: String,
}
#[derive(Deserialize, Debug)]
#[serde(tag = "type")]
pub enum Action {
#[serde(rename = "invoke")]
Invoke {
module: Option<String>,
field: String,
args: Vec<RuntimeValue>,
},
#[serde(rename = "get")]
Get {
module: Option<String>,
field: String,
}
#[serde(rename = "invoke")]
Invoke {
module: Option<String>,
field: String,
args: Vec<RuntimeValue>,
},
#[serde(rename = "get")]
Get {
module: Option<String>,
field: String,
}
}
#[derive(Deserialize, Debug)]
#[serde(tag = "type")]
pub enum Command {
#[serde(rename = "module")]
Module {
line: u64,
name: Option<String>,
filename: String
},
#[serde(rename = "assert_return")]
AssertReturn {
line: u64,
action: Action,
expected: Vec<RuntimeValue>,
},
#[serde(rename = "assert_return_canonical_nan")]
AssertReturnCanonicalNan {
line: u64,
action: Action,
},
#[serde(rename = "assert_return_arithmetic_nan")]
AssertReturnArithmeticNan {
line: u64,
action: Action,
},
#[serde(rename = "assert_trap")]
AssertTrap {
line: u64,
action: Action,
text: String,
},
#[serde(rename = "assert_invalid")]
AssertInvalid {
line: u64,
filename: String,
text: String,
},
#[serde(rename = "assert_malformed")]
AssertMalformed {
line: u64,
filename: String,
text: String,
},
#[serde(rename = "assert_uninstantiable")]
AssertUninstantiable {
line: u64,
filename: String,
text: String,
},
#[serde(rename = "assert_exhaustion")]
AssertExhaustion {
line: u64,
action: Action,
},
#[serde(rename = "assert_unlinkable")]
AssertUnlinkable {
line: u64,
filename: String,
text: String,
},
#[serde(rename = "register")]
Register {
line: u64,
name: Option<String>,
#[serde(rename = "as")]
as_name: String,
},
#[serde(rename = "action")]
Action {
line: u64,
action: Action,
},
#[serde(rename = "module")]
Module {
line: u64,
name: Option<String>,
filename: String
},
#[serde(rename = "assert_return")]
AssertReturn {
line: u64,
action: Action,
expected: Vec<RuntimeValue>,
},
#[serde(rename = "assert_return_canonical_nan")]
AssertReturnCanonicalNan {
line: u64,
action: Action,
},
#[serde(rename = "assert_return_arithmetic_nan")]
AssertReturnArithmeticNan {
line: u64,
action: Action,
},
#[serde(rename = "assert_trap")]
AssertTrap {
line: u64,
action: Action,
text: String,
},
#[serde(rename = "assert_invalid")]
AssertInvalid {
line: u64,
filename: String,
text: String,
},
#[serde(rename = "assert_malformed")]
AssertMalformed {
line: u64,
filename: String,
text: String,
},
#[serde(rename = "assert_uninstantiable")]
AssertUninstantiable {
line: u64,
filename: String,
text: String,
},
#[serde(rename = "assert_exhaustion")]
AssertExhaustion {
line: u64,
action: Action,
},
#[serde(rename = "assert_unlinkable")]
AssertUnlinkable {
line: u64,
filename: String,
text: String,
},
#[serde(rename = "register")]
Register {
line: u64,
name: Option<String>,
#[serde(rename = "as")]
as_name: String,
},
#[serde(rename = "action")]
Action {
line: u64,
action: Action,
},
}
#[derive(Deserialize, Debug)]
pub struct Spec {
pub source_filename: String,
pub commands: Vec<Command>,
pub source_filename: String,
pub commands: Vec<Command>,
}

View File

@ -4,170 +4,170 @@ use super::misc::{ValueTypeBuilder, ValueTypesBuilder, OptionalValueTypeBuilder}
/// Signature template description
pub enum Signature {
TypeReference(u32),
Inline(elements::FunctionType),
TypeReference(u32),
Inline(elements::FunctionType),
}
/// Signature builder
pub struct SignatureBuilder<F=Identity> {
callback: F,
signature: elements::FunctionType,
callback: F,
signature: elements::FunctionType,
}
impl SignatureBuilder {
/// New signature builder
pub fn new() -> Self {
SignatureBuilder::with_callback(Identity)
}
/// New signature builder
pub fn new() -> Self {
SignatureBuilder::with_callback(Identity)
}
}
impl<F> SignatureBuilder<F> where F: Invoke<elements::FunctionType> {
/// New builder with callback function specified
pub fn with_callback(callback: F) -> Self {
SignatureBuilder {
callback: callback,
signature: elements::FunctionType::default(),
}
}
/// New builder with callback function specified
pub fn with_callback(callback: F) -> Self {
SignatureBuilder {
callback: callback,
signature: elements::FunctionType::default(),
}
}
/// Add argument to signature builder
pub fn with_param(mut self, value_type: elements::ValueType) -> Self {
self.signature.params_mut().push(value_type);
self
}
/// Add argument to signature builder
pub fn with_param(mut self, value_type: elements::ValueType) -> Self {
self.signature.params_mut().push(value_type);
self
}
/// Add multiple arguments to signature builder
pub fn with_params(mut self, value_types: Vec<elements::ValueType>) -> Self {
self.signature.params_mut().extend(value_types);
self
}
/// Add multiple arguments to signature builder
pub fn with_params(mut self, value_types: Vec<elements::ValueType>) -> Self {
self.signature.params_mut().extend(value_types);
self
}
/// Override signature return type
pub fn with_return_type(mut self, return_type: Option<elements::ValueType>) -> Self {
*self.signature.return_type_mut() = return_type;
self
}
/// Override signature return type
pub fn with_return_type(mut self, return_type: Option<elements::ValueType>) -> Self {
*self.signature.return_type_mut() = return_type;
self
}
/// Start build new argument
pub fn param(self) -> ValueTypeBuilder<Self> {
ValueTypeBuilder::with_callback(self)
}
/// Start build new argument
pub fn param(self) -> ValueTypeBuilder<Self> {
ValueTypeBuilder::with_callback(self)
}
/// Start build multiple arguments
pub fn params(self) -> ValueTypesBuilder<Self> {
ValueTypesBuilder::with_callback(self)
}
/// Start build multiple arguments
pub fn params(self) -> ValueTypesBuilder<Self> {
ValueTypesBuilder::with_callback(self)
}
/// Start building return type
pub fn return_type(self) -> OptionalValueTypeBuilder<Self> {
OptionalValueTypeBuilder::with_callback(self)
}
/// Start building return type
pub fn return_type(self) -> OptionalValueTypeBuilder<Self> {
OptionalValueTypeBuilder::with_callback(self)
}
/// Finish current builder
pub fn build(self) -> F::Result {
self.callback.invoke(self.signature)
}
/// Finish current builder
pub fn build(self) -> F::Result {
self.callback.invoke(self.signature)
}
/// Finish current builder returning intermediate `Signature` struct
pub fn build_sig(self) -> Signature {
Signature::Inline(self.signature)
}
/// Finish current builder returning intermediate `Signature` struct
pub fn build_sig(self) -> Signature {
Signature::Inline(self.signature)
}
}
impl<F> Invoke<Vec<elements::ValueType>> for SignatureBuilder<F>
where F: Invoke<elements::FunctionType>
where F: Invoke<elements::FunctionType>
{
type Result = Self;
type Result = Self;
fn invoke(self, args: Vec<elements::ValueType>) -> Self {
self.with_params(args)
}
fn invoke(self, args: Vec<elements::ValueType>) -> Self {
self.with_params(args)
}
}
impl<F> Invoke<Option<elements::ValueType>> for SignatureBuilder<F>
where F: Invoke<elements::FunctionType>
where F: Invoke<elements::FunctionType>
{
type Result = Self;
type Result = Self;
fn invoke(self, arg: Option<elements::ValueType>) -> Self {
self.with_return_type(arg)
}
fn invoke(self, arg: Option<elements::ValueType>) -> Self {
self.with_return_type(arg)
}
}
impl<F> Invoke<elements::ValueType> for SignatureBuilder<F>
where F: Invoke<elements::FunctionType>
where F: Invoke<elements::FunctionType>
{
type Result = Self;
type Result = Self;
fn invoke(self, arg: elements::ValueType) -> Self {
self.with_param(arg)
}
fn invoke(self, arg: elements::ValueType) -> Self {
self.with_param(arg)
}
}
/// Type (signature) reference builder (for function/import/indirect call)
pub struct TypeRefBuilder<F=Identity> {
callback: F,
type_ref: u32,
callback: F,
type_ref: u32,
}
impl<F> TypeRefBuilder<F> where F: Invoke<u32> {
/// New builder chained with specified callback
pub fn with_callback(callback: F) -> Self {
TypeRefBuilder {
callback: callback,
type_ref: 0
}
}
/// New builder chained with specified callback
pub fn with_callback(callback: F) -> Self {
TypeRefBuilder {
callback: callback,
type_ref: 0
}
}
/// Set/override of type reference
pub fn val(mut self, val: u32) -> Self {
self.type_ref = val;
self
}
/// Set/override of type reference
pub fn val(mut self, val: u32) -> Self {
self.type_ref = val;
self
}
/// Finish current builder
pub fn build(self) -> F::Result { self.callback.invoke(self.type_ref) }
/// Finish current builder
pub fn build(self) -> F::Result { self.callback.invoke(self.type_ref) }
}
/// Multiple signatures builder
pub struct SignaturesBuilder<F=Identity> {
callback: F,
section: Vec<Signature>,
callback: F,
section: Vec<Signature>,
}
impl SignaturesBuilder {
/// New empty functions section builder
pub fn new() -> Self {
SignaturesBuilder::with_callback(Identity)
}
/// New empty functions section builder
pub fn new() -> Self {
SignaturesBuilder::with_callback(Identity)
}
}
impl<F> SignaturesBuilder<F> {
/// New builder chained with specified callback
pub fn with_callback(callback: F) -> Self {
SignaturesBuilder {
callback: callback,
section: Vec::new(),
}
}
/// New builder chained with specified callback
pub fn with_callback(callback: F) -> Self {
SignaturesBuilder {
callback: callback,
section: Vec::new(),
}
}
/// Push new signature into the builder output
pub fn with_signature(mut self, signature: Signature) -> Self {
self.section.push(signature);
self
}
/// Push new signature into the builder output
pub fn with_signature(mut self, signature: Signature) -> Self {
self.section.push(signature);
self
}
/// Start building new signature with `TypeRefBuilder`
pub fn type_ref(self) -> TypeRefBuilder<Self> {
TypeRefBuilder::with_callback(self)
}
/// Start building new signature with `TypeRefBuilder`
pub fn type_ref(self) -> TypeRefBuilder<Self> {
TypeRefBuilder::with_callback(self)
}
}
impl<F> SignaturesBuilder<F> where F: Invoke<SignatureBindings> {
/// Start building new signature with dedicated builder
pub fn signature(self) -> SignatureBuilder<Self> {
SignatureBuilder::with_callback(self)
}
/// Start building new signature with dedicated builder
pub fn signature(self) -> SignatureBuilder<Self> {
SignatureBuilder::with_callback(self)
}
}
impl<F> Invoke<elements::FunctionType> for SignaturesBuilder<F> {
@ -175,7 +175,7 @@ impl<F> Invoke<elements::FunctionType> for SignaturesBuilder<F> {
fn invoke(self, signature: elements::FunctionType) -> Self {
self.with_signature(Signature::Inline(signature))
}
}
}
impl<F> Invoke<u32> for SignaturesBuilder<F> {
@ -183,150 +183,150 @@ impl<F> Invoke<u32> for SignaturesBuilder<F> {
fn invoke(self, type_ref: u32) -> Self {
self.with_signature(Signature::TypeReference(type_ref))
}
}
}
impl<F> SignaturesBuilder<F> where F: Invoke<elements::FunctionSection> {
/// Finalize builder spawning element
pub fn build(self) -> F::Result {
let mut result = elements::FunctionSection::default();
for f in self.section.into_iter() {
if let Signature::TypeReference(type_ref) = f {
result.entries_mut().push(elements::Func::new(type_ref));
} else {
unreachable!(); // never possible with current generics impl-s
}
}
self.callback.invoke(result)
}
/// Finalize builder spawning element
pub fn build(self) -> F::Result {
let mut result = elements::FunctionSection::default();
for f in self.section.into_iter() {
if let Signature::TypeReference(type_ref) = f {
result.entries_mut().push(elements::Func::new(type_ref));
} else {
unreachable!(); // never possible with current generics impl-s
}
}
self.callback.invoke(result)
}
}
/// Signature bindings
pub type SignatureBindings = Vec<Signature>;
impl<F> SignaturesBuilder<F> where F: Invoke<SignatureBindings> {
/// Bind signature list
pub fn bind(self) -> F::Result {
self.callback.invoke(self.section)
}
/// Bind signature list
pub fn bind(self) -> F::Result {
self.callback.invoke(self.section)
}
}
/// Function body (code) builder
pub struct FuncBodyBuilder<F=Identity> {
callback: F,
body: elements::FuncBody,
callback: F,
body: elements::FuncBody,
}
impl<F> FuncBodyBuilder<F> {
/// New body (code) builder given the chain callback
pub fn with_callback(callback: F) -> Self {
FuncBodyBuilder {
callback: callback,
body: elements::FuncBody::new(Vec::new(), elements::Opcodes::empty()),
}
}
/// New body (code) builder given the chain callback
pub fn with_callback(callback: F) -> Self {
FuncBodyBuilder {
callback: callback,
body: elements::FuncBody::new(Vec::new(), elements::Opcodes::empty()),
}
}
}
impl<F> FuncBodyBuilder<F> where F: Invoke<elements::FuncBody> {
/// Set/override entirely with FuncBody struct
pub fn with_func(mut self, func: elements::FuncBody) -> Self {
self.body = func;
self
}
/// Set/override entirely with FuncBody struct
pub fn with_func(mut self, func: elements::FuncBody) -> Self {
self.body = func;
self
}
/// Extend function local list with new entries
pub fn with_locals(mut self, locals: Vec<elements::Local>) -> Self {
self.body.locals_mut().extend(locals);
self
}
/// Extend function local list with new entries
pub fn with_locals(mut self, locals: Vec<elements::Local>) -> Self {
self.body.locals_mut().extend(locals);
self
}
/// Set code of the function
pub fn with_opcodes(mut self, opcodes: elements::Opcodes) -> Self {
*self.body.code_mut() = opcodes;
self
}
/// Set code of the function
pub fn with_opcodes(mut self, opcodes: elements::Opcodes) -> Self {
*self.body.code_mut() = opcodes;
self
}
/// Finish current builder spawning resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(self.body)
}
/// Finish current builder spawning resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(self.body)
}
}
/// Function definition (extended structure to specify function entirely, incl. signature, mainness and code)
pub struct FunctionDefinition {
/// Is this function is start function
pub is_main: bool,
/// Signature description
pub signature: Signature,
/// Body (code) of the function
pub code: elements::FuncBody,
/// Is this function is start function
pub is_main: bool,
/// Signature description
pub signature: Signature,
/// Body (code) of the function
pub code: elements::FuncBody,
}
impl Default for FunctionDefinition {
fn default() -> Self {
FunctionDefinition {
is_main: false,
signature: Signature::TypeReference(0),
code: elements::FuncBody::empty(),
}
}
fn default() -> Self {
FunctionDefinition {
is_main: false,
signature: Signature::TypeReference(0),
code: elements::FuncBody::empty(),
}
}
}
/// Function definition builder
pub struct FunctionBuilder<F=Identity> {
callback: F,
func: FunctionDefinition,
callback: F,
func: FunctionDefinition,
}
impl FunctionBuilder {
/// New function builder
pub fn new() -> Self {
FunctionBuilder::with_callback(Identity)
}
/// New function builder
pub fn new() -> Self {
FunctionBuilder::with_callback(Identity)
}
}
impl<F> FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
/// New function builder with chained callback
pub fn with_callback(callback: F) -> Self {
FunctionBuilder {
callback: callback,
func: Default::default(),
}
}
/// New function builder with chained callback
pub fn with_callback(callback: F) -> Self {
FunctionBuilder {
callback: callback,
func: Default::default(),
}
}
/// Set that this function is main entry point
pub fn main(mut self) -> Self {
self.func.is_main = true;
self
}
/// Set that this function is main entry point
pub fn main(mut self) -> Self {
self.func.is_main = true;
self
}
/// Start signature builder of the function
pub fn signature(self) -> SignatureBuilder<Self> {
SignatureBuilder::with_callback(self)
}
/// Start signature builder of the function
pub fn signature(self) -> SignatureBuilder<Self> {
SignatureBuilder::with_callback(self)
}
/// Override current signature entirely with new one from known struct
pub fn with_signature(mut self, signature: Signature) -> Self {
self.func.signature = signature;
self
}
/// Override current signature entirely with new one from known struct
pub fn with_signature(mut self, signature: Signature) -> Self {
self.func.signature = signature;
self
}
/// Start code (body) builder
pub fn body(self) -> FuncBodyBuilder<Self> {
FuncBodyBuilder::with_callback(self)
}
/// Start code (body) builder
pub fn body(self) -> FuncBodyBuilder<Self> {
FuncBodyBuilder::with_callback(self)
}
/// Set body (code) for this function
pub fn with_body(mut self, body: elements::FuncBody) -> Self {
self.func.code = body;
self
}
/// Set body (code) for this function
pub fn with_body(mut self, body: elements::FuncBody) -> Self {
self.func.code = body;
self
}
/// Finalize current builder spawning resulting struct in the callback
pub fn build(self) -> F::Result {
self.callback.invoke(self.func)
}
/// Finalize current builder spawning resulting struct in the callback
pub fn build(self) -> F::Result {
self.callback.invoke(self.func)
}
}
impl<F> Invoke<elements::FunctionType> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
@ -334,7 +334,7 @@ impl<F> Invoke<elements::FunctionType> for FunctionBuilder<F> where F: Invoke<Fu
fn invoke(self, signature: elements::FunctionType) -> Self {
self.with_signature(Signature::Inline(signature))
}
}
}
impl<F> Invoke<u32> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
@ -342,70 +342,70 @@ impl<F> Invoke<u32> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
fn invoke(self, type_ref: u32) -> Self {
self.with_signature(Signature::TypeReference(type_ref))
}
}
}
impl<F> Invoke<elements::FuncBody> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
type Result = Self;
type Result = Self;
fn invoke(self, body: elements::FuncBody) -> Self::Result {
self.with_body(body)
}
fn invoke(self, body: elements::FuncBody) -> Self::Result {
self.with_body(body)
}
}
/// New builder of signature list
pub fn signatures() -> SignaturesBuilder {
SignaturesBuilder::new()
SignaturesBuilder::new()
}
/// New signature builder
pub fn signature() -> SignatureBuilder {
SignatureBuilder::new()
SignatureBuilder::new()
}
/// New builder of function (signature & body)
pub fn function() -> FunctionBuilder {
FunctionBuilder::new()
FunctionBuilder::new()
}
#[cfg(test)]
mod tests {
use super::{signatures, function};
use elements;
use super::{signatures, function};
use elements;
#[test]
fn example() {
let result = signatures()
.type_ref().val(1).build()
.build();
#[test]
fn example() {
let result = signatures()
.type_ref().val(1).build()
.build();
assert_eq!(result.entries().len(), 1);
assert_eq!(result.entries().len(), 1);
let result = signatures()
.signature()
.param().i32()
.param().i32()
.return_type().i64()
.build()
.bind();
let result = signatures()
.signature()
.param().i32()
.param().i32()
.return_type().i64()
.build()
.bind();
assert_eq!(result.len(), 1);
}
assert_eq!(result.len(), 1);
}
#[test]
fn func_example() {
let func = function()
.signature()
.param().i32()
.return_type().i32()
.build()
.body()
.with_opcodes(elements::Opcodes::empty())
.build()
.build();
#[test]
fn func_example() {
let func = function()
.signature()
.param().i32()
.return_type().i32()
.build()
.body()
.with_opcodes(elements::Opcodes::empty())
.build()
.build();
assert_eq!(func.code.locals().len(), 0);
assert_eq!(func.code.code().elements().len(), 1);
}
assert_eq!(func.code.locals().len(), 0);
assert_eq!(func.code.code().elements().len(), 1);
}
}

View File

@ -3,53 +3,53 @@ use elements;
/// Data segment builder
pub struct DataSegmentBuilder<F=Identity> {
callback: F,
// todo: add mapper once multiple memory refs possible
mem_index: u32,
offset: elements::InitExpr,
value: Vec<u8>,
callback: F,
// todo: add mapper once multiple memory refs possible
mem_index: u32,
offset: elements::InitExpr,
value: Vec<u8>,
}
impl DataSegmentBuilder {
/// New data segment builder
pub fn new() -> Self {
DataSegmentBuilder::with_callback(Identity)
}
/// New data segment builder
pub fn new() -> Self {
DataSegmentBuilder::with_callback(Identity)
}
}
impl<F> DataSegmentBuilder<F> {
/// New data segment builder inside the chain context
pub fn with_callback(callback: F) -> Self {
DataSegmentBuilder {
callback: callback,
mem_index: 0,
offset: elements::InitExpr::empty(),
value: Vec::new(),
}
}
/// New data segment builder inside the chain context
pub fn with_callback(callback: F) -> Self {
DataSegmentBuilder {
callback: callback,
mem_index: 0,
offset: elements::InitExpr::empty(),
value: Vec::new(),
}
}
/// Set offset initialization opcode. `End` opcode will be added automatically.
pub fn offset(mut self, opcode: elements::Opcode) -> Self {
self.offset = elements::InitExpr::new(vec![opcode, elements::Opcode::End]);
self
}
/// Set offset initialization opcode. `End` opcode will be added automatically.
pub fn offset(mut self, opcode: elements::Opcode) -> Self {
self.offset = elements::InitExpr::new(vec![opcode, elements::Opcode::End]);
self
}
/// Set the bytes value of the segment
pub fn value(mut self, value: Vec<u8>) -> Self {
self.value = value;
self
}
/// Set the bytes value of the segment
pub fn value(mut self, value: Vec<u8>) -> Self {
self.value = value;
self
}
}
impl<F> DataSegmentBuilder<F> where F: Invoke<elements::DataSegment> {
/// Finish current builder, spawning resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(
elements::DataSegment::new(
self.mem_index,
self.offset,
self.value,
)
)
}
/// Finish current builder, spawning resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(
elements::DataSegment::new(
self.mem_index,
self.offset,
self.value,
)
)
}
}

View File

@ -3,113 +3,113 @@ use elements;
/// Export entry builder
pub struct ExportBuilder<F=Identity> {
callback: F,
field: String,
binding: elements::Internal,
callback: F,
field: String,
binding: elements::Internal,
}
impl ExportBuilder {
/// New export builder
pub fn new() -> Self {
ExportBuilder::with_callback(Identity)
}
/// New export builder
pub fn new() -> Self {
ExportBuilder::with_callback(Identity)
}
}
impl<F> ExportBuilder<F> {
/// New export entry builder in the specified chained context
pub fn with_callback(callback: F) -> Self {
ExportBuilder {
callback: callback,
field: String::new(),
binding: elements::Internal::Function(0),
}
}
/// New export entry builder in the specified chained context
pub fn with_callback(callback: F) -> Self {
ExportBuilder {
callback: callback,
field: String::new(),
binding: elements::Internal::Function(0),
}
}
/// Set the field name of the export entry
pub fn field(mut self, field: &str) -> Self {
self.field = field.to_owned();
self
}
/// Set the field name of the export entry
pub fn field(mut self, field: &str) -> Self {
self.field = field.to_owned();
self
}
/// Specify the internal module mapping for this entry
pub fn with_internal(mut self, external: elements::Internal) -> Self {
self.binding = external;
self
}
/// Specify the internal module mapping for this entry
pub fn with_internal(mut self, external: elements::Internal) -> Self {
self.binding = external;
self
}
/// Start the internal builder for this export entry
pub fn internal(self) -> ExportInternalBuilder<Self> {
ExportInternalBuilder::with_callback(self)
}
/// Start the internal builder for this export entry
pub fn internal(self) -> ExportInternalBuilder<Self> {
ExportInternalBuilder::with_callback(self)
}
}
impl<F> ExportBuilder<F> where F: Invoke<elements::ExportEntry> {
/// Finalize export entry builder spawning the resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(elements::ExportEntry::new(self.field, self.binding))
}
/// Finalize export entry builder spawning the resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(elements::ExportEntry::new(self.field, self.binding))
}
}
impl<F> Invoke<elements::Internal> for ExportBuilder<F> {
type Result = Self;
fn invoke(self, val: elements::Internal) -> Self {
self.with_internal(val)
}
type Result = Self;
fn invoke(self, val: elements::Internal) -> Self {
self.with_internal(val)
}
}
/// Internal mapping builder for export entry
pub struct ExportInternalBuilder<F=Identity> {
callback: F,
binding: elements::Internal,
callback: F,
binding: elements::Internal,
}
impl<F> ExportInternalBuilder<F> where F: Invoke<elements::Internal> {
/// New export entry internal mapping for the chained context
pub fn with_callback(callback: F) -> Self {
ExportInternalBuilder{
callback: callback,
binding: elements::Internal::Function(0),
}
}
/// New export entry internal mapping for the chained context
pub fn with_callback(callback: F) -> Self {
ExportInternalBuilder{
callback: callback,
binding: elements::Internal::Function(0),
}
}
/// Map to function by index
pub fn func(mut self, index: u32) -> F::Result {
self.binding = elements::Internal::Function(index);
self.callback.invoke(self.binding)
}
/// Map to function by index
pub fn func(mut self, index: u32) -> F::Result {
self.binding = elements::Internal::Function(index);
self.callback.invoke(self.binding)
}
/// Map to memory
pub fn memory(mut self, index: u32) -> F::Result {
self.binding = elements::Internal::Memory(index);
self.callback.invoke(self.binding)
}
/// Map to memory
pub fn memory(mut self, index: u32) -> F::Result {
self.binding = elements::Internal::Memory(index);
self.callback.invoke(self.binding)
}
/// Map to table
pub fn table(mut self, index: u32) -> F::Result {
self.binding = elements::Internal::Table(index);
self.callback.invoke(self.binding)
}
/// Map to table
pub fn table(mut self, index: u32) -> F::Result {
self.binding = elements::Internal::Table(index);
self.callback.invoke(self.binding)
}
/// Map to global
pub fn global(mut self, index: u32) -> F::Result {
self.binding = elements::Internal::Global(index);
self.callback.invoke(self.binding)
}
/// Map to global
pub fn global(mut self, index: u32) -> F::Result {
self.binding = elements::Internal::Global(index);
self.callback.invoke(self.binding)
}
}
/// New builder for export entry
pub fn export() -> ExportBuilder {
ExportBuilder::new()
ExportBuilder::new()
}
#[cfg(test)]
mod tests {
use super::export;
use super::export;
#[test]
fn example() {
let entry = export().field("memory").internal().memory(0).build();
assert_eq!(entry.field(), "memory");
}
#[test]
fn example() {
let entry = export().field("memory").internal().memory(0).build();
assert_eq!(entry.field(), "memory");
}
}

View File

@ -4,87 +4,87 @@ use elements;
/// Global builder
pub struct GlobalBuilder<F=Identity> {
callback: F,
value_type: elements::ValueType,
is_mutable: bool,
init_expr: elements::InitExpr,
callback: F,
value_type: elements::ValueType,
is_mutable: bool,
init_expr: elements::InitExpr,
}
impl GlobalBuilder {
/// New global builder
pub fn new() -> Self {
GlobalBuilder::with_callback(Identity)
}
/// New global builder
pub fn new() -> Self {
GlobalBuilder::with_callback(Identity)
}
}
impl<F> GlobalBuilder<F> {
/// New global builder with callback (in chained context)
pub fn with_callback(callback: F) -> Self {
GlobalBuilder {
callback: callback,
value_type: elements::ValueType::I32,
init_expr: elements::InitExpr::empty(),
is_mutable: false,
}
}
/// New global builder with callback (in chained context)
pub fn with_callback(callback: F) -> Self {
GlobalBuilder {
callback: callback,
value_type: elements::ValueType::I32,
init_expr: elements::InitExpr::empty(),
is_mutable: false,
}
}
/// Set/override resulting global type
pub fn with_type(mut self, value_type: elements::ValueType) -> Self {
self.value_type = value_type;
self
}
/// Set/override resulting global type
pub fn with_type(mut self, value_type: elements::ValueType) -> Self {
self.value_type = value_type;
self
}
/// Set mutabilty to true
pub fn mutable(mut self) -> Self {
self.is_mutable = true;
self
}
/// Set mutabilty to true
pub fn mutable(mut self) -> Self {
self.is_mutable = true;
self
}
/// Set initialization expression opcode for this global (`end` opcode will be added automatically)
pub fn init_expr(mut self, opcode: elements::Opcode) -> Self {
self.init_expr = elements::InitExpr::new(vec![opcode, elements::Opcode::End]);
self
}
/// Set initialization expression opcode for this global (`end` opcode will be added automatically)
pub fn init_expr(mut self, opcode: elements::Opcode) -> Self {
self.init_expr = elements::InitExpr::new(vec![opcode, elements::Opcode::End]);
self
}
/// Start value type builder
pub fn value_type(self) -> ValueTypeBuilder<Self> {
ValueTypeBuilder::with_callback(self)
}
/// Start value type builder
pub fn value_type(self) -> ValueTypeBuilder<Self> {
ValueTypeBuilder::with_callback(self)
}
}
impl<F> GlobalBuilder<F> where F: Invoke<elements::GlobalEntry> {
/// Finalize current builder spawning resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(
elements::GlobalEntry::new(
elements::GlobalType::new(self.value_type, self.is_mutable),
self.init_expr,
)
)
}
/// Finalize current builder spawning resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(
elements::GlobalEntry::new(
elements::GlobalType::new(self.value_type, self.is_mutable),
self.init_expr,
)
)
}
}
impl<F> Invoke<elements::ValueType> for GlobalBuilder<F> {
type Result = Self;
fn invoke(self, the_type: elements::ValueType) -> Self {
self.with_type(the_type)
}
type Result = Self;
fn invoke(self, the_type: elements::ValueType) -> Self {
self.with_type(the_type)
}
}
/// New builder for export entry
pub fn global() -> GlobalBuilder {
GlobalBuilder::new()
GlobalBuilder::new()
}
#[cfg(test)]
mod tests {
use super::global;
use elements;
use super::global;
use elements;
#[test]
fn example() {
let entry = global().value_type().i32().build();
assert_eq!(entry.global_type().content_type(), elements::ValueType::I32);
assert_eq!(entry.global_type().is_mutable(), false);
}
#[test]
fn example() {
let entry = global().value_type().i32().build();
assert_eq!(entry.global_type().content_type(), elements::ValueType::I32);
assert_eq!(entry.global_type().is_mutable(), false);
}
}

View File

@ -3,127 +3,127 @@ use elements;
/// Import builder
pub struct ImportBuilder<F=Identity> {
callback: F,
module: String,
field: String,
binding: elements::External,
callback: F,
module: String,
field: String,
binding: elements::External,
}
impl ImportBuilder {
/// New import builder
pub fn new() -> Self {
ImportBuilder::with_callback(Identity)
}
/// New import builder
pub fn new() -> Self {
ImportBuilder::with_callback(Identity)
}
}
impl<F> ImportBuilder<F> {
/// New import builder with callback (in chained context)
pub fn with_callback(callback: F) -> Self {
ImportBuilder {
callback: callback,
module: String::new(),
field: String::new(),
binding: elements::External::Function(0),
}
}
/// New import builder with callback (in chained context)
pub fn with_callback(callback: F) -> Self {
ImportBuilder {
callback: callback,
module: String::new(),
field: String::new(),
binding: elements::External::Function(0),
}
}
/// Set/override module name
pub fn module(mut self, name: &str) -> Self {
self.module = name.to_owned();
self
}
/// Set/override module name
pub fn module(mut self, name: &str) -> Self {
self.module = name.to_owned();
self
}
/// Set/override field name
pub fn field(mut self, name: &str) -> Self {
self.field = name.to_owned();
self
}
/// Set/override field name
pub fn field(mut self, name: &str) -> Self {
self.field = name.to_owned();
self
}
/// Set/override both module name and field name
pub fn path(self, module: &str, field: &str) -> Self {
self.module(module).field(field)
}
/// Set/override both module name and field name
pub fn path(self, module: &str, field: &str) -> Self {
self.module(module).field(field)
}
/// Set/override external mapping for this import
pub fn with_external(mut self, external: elements::External) -> Self {
self.binding = external;
self
}
/// Set/override external mapping for this import
pub fn with_external(mut self, external: elements::External) -> Self {
self.binding = external;
self
}
/// Start new external mapping builder
pub fn external(self) -> ImportExternalBuilder<Self> {
ImportExternalBuilder::with_callback(self)
}
/// Start new external mapping builder
pub fn external(self) -> ImportExternalBuilder<Self> {
ImportExternalBuilder::with_callback(self)
}
}
impl<F> ImportBuilder<F> where F: Invoke<elements::ImportEntry> {
/// Finalize current builder spawning the resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(elements::ImportEntry::new(self.module, self.field, self.binding))
}
/// Finalize current builder spawning the resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(elements::ImportEntry::new(self.module, self.field, self.binding))
}
}
impl<F> Invoke<elements::External> for ImportBuilder<F> {
type Result = Self;
fn invoke(self, val: elements::External) -> Self {
self.with_external(val)
}
type Result = Self;
fn invoke(self, val: elements::External) -> Self {
self.with_external(val)
}
}
/// Import to external mapping builder
pub struct ImportExternalBuilder<F=Identity> {
callback: F,
binding: elements::External,
callback: F,
binding: elements::External,
}
impl<F> ImportExternalBuilder<F> where F: Invoke<elements::External> {
/// New import to external mapping builder with callback (in chained context)
pub fn with_callback(callback: F) -> Self {
ImportExternalBuilder{
callback: callback,
binding: elements::External::Function(0),
}
}
/// New import to external mapping builder with callback (in chained context)
pub fn with_callback(callback: F) -> Self {
ImportExternalBuilder{
callback: callback,
binding: elements::External::Function(0),
}
}
/// Function mapping with type reference
pub fn func(mut self, index: u32) -> F::Result {
self.binding = elements::External::Function(index);
self.callback.invoke(self.binding)
}
/// Function mapping with type reference
pub fn func(mut self, index: u32) -> F::Result {
self.binding = elements::External::Function(index);
self.callback.invoke(self.binding)
}
/// Memory mapping with specified limits
pub fn memory(mut self, min: u32, max: Option<u32>) -> F::Result {
self.binding = elements::External::Memory(elements::MemoryType::new(min, max));
self.callback.invoke(self.binding)
}
/// Memory mapping with specified limits
pub fn memory(mut self, min: u32, max: Option<u32>) -> F::Result {
self.binding = elements::External::Memory(elements::MemoryType::new(min, max));
self.callback.invoke(self.binding)
}
/// Table mapping with specified limits
pub fn table(mut self, min: u32, max: Option<u32>) -> F::Result {
self.binding = elements::External::Table(elements::TableType::new(min, max));
self.callback.invoke(self.binding)
}
/// Table mapping with specified limits
pub fn table(mut self, min: u32, max: Option<u32>) -> F::Result {
self.binding = elements::External::Table(elements::TableType::new(min, max));
self.callback.invoke(self.binding)
}
/// Global mapping with speciifed type and mutability
pub fn global(mut self, value_type: elements::ValueType, is_mut: bool) -> F::Result {
self.binding = elements::External::Global(elements::GlobalType::new(value_type, is_mut));
self.callback.invoke(self.binding)
}
/// Global mapping with speciifed type and mutability
pub fn global(mut self, value_type: elements::ValueType, is_mut: bool) -> F::Result {
self.binding = elements::External::Global(elements::GlobalType::new(value_type, is_mut));
self.callback.invoke(self.binding)
}
}
/// New builder for import entry
pub fn import() -> ImportBuilder {
ImportBuilder::new()
ImportBuilder::new()
}
#[cfg(test)]
mod tests {
use super::import;
use super::import;
#[test]
fn example() {
let entry = import().module("env").field("memory").external().memory(256, Some(256)).build();
#[test]
fn example() {
let entry = import().module("env").field("memory").external().memory(256, Some(256)).build();
assert_eq!(entry.module(), "env");
assert_eq!(entry.field(), "memory");
}
assert_eq!(entry.module(), "env");
assert_eq!(entry.field(), "memory");
}
}

View File

@ -4,81 +4,81 @@ use super::invoke::{Invoke, Identity};
/// Memory definition struct
#[derive(Debug)]
pub struct MemoryDefinition {
/// Minimum memory size
pub min: u32,
/// Maximum memory size
pub max: Option<u32>,
/// Memory data segments (static regions)
pub data: Vec<MemoryDataDefinition>,
/// Minimum memory size
pub min: u32,
/// Maximum memory size
pub max: Option<u32>,
/// Memory data segments (static regions)
pub data: Vec<MemoryDataDefinition>,
}
/// Memory static region entry definition
#[derive(Debug)]
pub struct MemoryDataDefinition {
/// Segment initialization expression for offset
pub offset: elements::InitExpr,
/// Raw bytes of static region
pub values: Vec<u8>,
/// Segment initialization expression for offset
pub offset: elements::InitExpr,
/// Raw bytes of static region
pub values: Vec<u8>,
}
/// Memory and static regions builder
pub struct MemoryBuilder<F=Identity> {
callback: F,
memory: MemoryDefinition,
callback: F,
memory: MemoryDefinition,
}
impl MemoryBuilder {
/// New memory builder
pub fn new() -> Self {
MemoryBuilder::with_callback(Identity)
}
/// New memory builder
pub fn new() -> Self {
MemoryBuilder::with_callback(Identity)
}
}
impl<F> MemoryBuilder<F> where F: Invoke<MemoryDefinition> {
/// New memory builder with callback (in chained context)
pub fn with_callback(callback: F) -> Self {
MemoryBuilder {
callback: callback,
memory: Default::default(),
}
}
/// New memory builder with callback (in chained context)
pub fn with_callback(callback: F) -> Self {
MemoryBuilder {
callback: callback,
memory: Default::default(),
}
}
/// Set/override minimum size
pub fn with_min(mut self, min: u32) -> Self {
self.memory.min = min;
self
}
/// Set/override minimum size
pub fn with_min(mut self, min: u32) -> Self {
self.memory.min = min;
self
}
/// Set/override maximum size
pub fn with_max(mut self, max: Option<u32>) -> Self {
self.memory.max = max;
self
}
/// Set/override maximum size
pub fn with_max(mut self, max: Option<u32>) -> Self {
self.memory.max = max;
self
}
/// Push new static region with initialized offset expression and raw bytes
pub fn with_data(mut self, index: u32, values: Vec<u8>) -> Self {
self.memory.data.push(MemoryDataDefinition {
offset: elements::InitExpr::new(vec![
elements::Opcode::I32Const(index as i32),
elements::Opcode::End,
]),
values: values,
});
self
}
/// Push new static region with initialized offset expression and raw bytes
pub fn with_data(mut self, index: u32, values: Vec<u8>) -> Self {
self.memory.data.push(MemoryDataDefinition {
offset: elements::InitExpr::new(vec![
elements::Opcode::I32Const(index as i32),
elements::Opcode::End,
]),
values: values,
});
self
}
/// Finalize current builder, spawning resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(self.memory)
}
/// Finalize current builder, spawning resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(self.memory)
}
}
impl Default for MemoryDefinition {
fn default() -> Self {
MemoryDefinition {
min: 1,
max: None,
data: Vec::new(),
}
}
fn default() -> Self {
MemoryDefinition {
min: 1,
max: None,
data: Vec::new(),
}
}
}

View File

@ -2,91 +2,91 @@ use super::invoke::{Invoke, Identity};
use elements;
pub struct ValueTypeBuilder<F=Identity> {
callback: F,
callback: F,
}
impl<F> ValueTypeBuilder<F> where F: Invoke<elements::ValueType> {
pub fn with_callback(callback: F) -> Self {
ValueTypeBuilder { callback: callback }
}
pub fn with_callback(callback: F) -> Self {
ValueTypeBuilder { callback: callback }
}
pub fn i32(self) -> F::Result {
self.callback.invoke(elements::ValueType::I32)
}
pub fn i32(self) -> F::Result {
self.callback.invoke(elements::ValueType::I32)
}
pub fn i64(self) -> F::Result {
self.callback.invoke(elements::ValueType::I64)
}
pub fn i64(self) -> F::Result {
self.callback.invoke(elements::ValueType::I64)
}
pub fn f32(self) -> F::Result {
self.callback.invoke(elements::ValueType::F32)
}
pub fn f32(self) -> F::Result {
self.callback.invoke(elements::ValueType::F32)
}
pub fn f64(self) -> F::Result {
self.callback.invoke(elements::ValueType::F64)
}
pub fn f64(self) -> F::Result {
self.callback.invoke(elements::ValueType::F64)
}
}
pub struct OptionalValueTypeBuilder<F=Identity> {
callback: F,
callback: F,
}
impl<F> OptionalValueTypeBuilder<F> where F: Invoke<Option<elements::ValueType>> {
pub fn with_callback(callback: F) -> Self {
OptionalValueTypeBuilder { callback: callback }
}
pub fn with_callback(callback: F) -> Self {
OptionalValueTypeBuilder { callback: callback }
}
pub fn i32(self) -> F::Result {
self.callback.invoke(Some(elements::ValueType::I32))
}
pub fn i32(self) -> F::Result {
self.callback.invoke(Some(elements::ValueType::I32))
}
pub fn i64(self) -> F::Result {
self.callback.invoke(Some(elements::ValueType::I64))
}
pub fn i64(self) -> F::Result {
self.callback.invoke(Some(elements::ValueType::I64))
}
pub fn f32(self) -> F::Result {
self.callback.invoke(Some(elements::ValueType::F32))
}
pub fn f32(self) -> F::Result {
self.callback.invoke(Some(elements::ValueType::F32))
}
pub fn f64(self) -> F::Result {
self.callback.invoke(Some(elements::ValueType::F64))
}
pub fn f64(self) -> F::Result {
self.callback.invoke(Some(elements::ValueType::F64))
}
}
pub struct ValueTypesBuilder<F=Identity> {
callback: F,
value_types: Vec<elements::ValueType>,
callback: F,
value_types: Vec<elements::ValueType>,
}
impl<F> ValueTypesBuilder<F> where F: Invoke<Vec<elements::ValueType>> {
pub fn with_callback(callback: F) -> Self {
ValueTypesBuilder {
callback: callback,
value_types: Vec::new(),
}
}
pub fn with_callback(callback: F) -> Self {
ValueTypesBuilder {
callback: callback,
value_types: Vec::new(),
}
}
pub fn i32(mut self) -> Self {
self.value_types.push(elements::ValueType::I32);
self
}
pub fn i32(mut self) -> Self {
self.value_types.push(elements::ValueType::I32);
self
}
pub fn i64(mut self) -> Self {
self.value_types.push(elements::ValueType::I64);
self
}
pub fn i64(mut self) -> Self {
self.value_types.push(elements::ValueType::I64);
self
}
pub fn f32(mut self) -> Self {
self.value_types.push(elements::ValueType::F32);
self
}
pub fn f32(mut self) -> Self {
self.value_types.push(elements::ValueType::F32);
self
}
pub fn f64(mut self) -> Self {
self.value_types.push(elements::ValueType::F64);
self
}
pub fn f64(mut self) -> Self {
self.value_types.push(elements::ValueType::F64);
self
}
pub fn build(self) -> F::Result {
self.callback.invoke(self.value_types)
}
pub fn build(self) -> F::Result {
self.callback.invoke(self.value_types)
}
}

View File

@ -12,8 +12,8 @@ mod global;
mod data;
pub use self::code::{
signatures, signature, function, SignatureBuilder, SignaturesBuilder,
FunctionBuilder, TypeRefBuilder, FuncBodyBuilder, FunctionDefinition,
signatures, signature, function, SignatureBuilder, SignaturesBuilder,
FunctionBuilder, TypeRefBuilder, FuncBodyBuilder, FunctionDefinition,
};
pub use self::data::DataSegmentBuilder;
pub use self::export::{export, ExportBuilder, ExportInternalBuilder};

View File

@ -7,484 +7,484 @@ use elements;
/// Module builder
pub struct ModuleBuilder<F=Identity> {
callback: F,
module: ModuleScaffold,
callback: F,
module: ModuleScaffold,
}
/// Location of the internal module function
pub struct CodeLocation {
/// Location (index in 'functions' section) of the signature
pub signature: u32,
/// Location (index in the 'code' section) of the body
pub body: u32,
/// Location (index in 'functions' section) of the signature
pub signature: u32,
/// Location (index in the 'code' section) of the body
pub body: u32,
}
#[derive(Default)]
struct ModuleScaffold {
pub types: elements::TypeSection,
pub import: elements::ImportSection,
pub functions: elements::FunctionSection,
pub table: elements::TableSection,
pub memory: elements::MemorySection,
pub global: elements::GlobalSection,
pub export: elements::ExportSection,
pub start: Option<u32>,
pub element: elements::ElementSection,
pub code: elements::CodeSection,
pub data: elements::DataSection,
pub other: Vec<elements::Section>,
pub types: elements::TypeSection,
pub import: elements::ImportSection,
pub functions: elements::FunctionSection,
pub table: elements::TableSection,
pub memory: elements::MemorySection,
pub global: elements::GlobalSection,
pub export: elements::ExportSection,
pub start: Option<u32>,
pub element: elements::ElementSection,
pub code: elements::CodeSection,
pub data: elements::DataSection,
pub other: Vec<elements::Section>,
}
impl From<elements::Module> for ModuleScaffold {
fn from(module: elements::Module) -> Self {
let mut types: Option<elements::TypeSection> = None;
let mut import: Option<elements::ImportSection> = None;
let mut funcs: Option<elements::FunctionSection> = None;
let mut table: Option<elements::TableSection> = None;
let mut memory: Option<elements::MemorySection> = None;
let mut global: Option<elements::GlobalSection> = None;
let mut export: Option<elements::ExportSection> = None;
let mut start: Option<u32> = None;
let mut element: Option<elements::ElementSection> = None;
let mut code: Option<elements::CodeSection> = None;
let mut data: Option<elements::DataSection> = None;
fn from(module: elements::Module) -> Self {
let mut types: Option<elements::TypeSection> = None;
let mut import: Option<elements::ImportSection> = None;
let mut funcs: Option<elements::FunctionSection> = None;
let mut table: Option<elements::TableSection> = None;
let mut memory: Option<elements::MemorySection> = None;
let mut global: Option<elements::GlobalSection> = None;
let mut export: Option<elements::ExportSection> = None;
let mut start: Option<u32> = None;
let mut element: Option<elements::ElementSection> = None;
let mut code: Option<elements::CodeSection> = None;
let mut data: Option<elements::DataSection> = None;
let mut sections = module.into_sections();
while let Some(section) = sections.pop() {
match section {
elements::Section::Type(sect) => { types = Some(sect); }
elements::Section::Import(sect) => { import = Some(sect); }
elements::Section::Function(sect) => { funcs = Some(sect); }
elements::Section::Table(sect) => { table = Some(sect); }
elements::Section::Memory(sect) => { memory = Some(sect); }
elements::Section::Global(sect) => { global = Some(sect); }
elements::Section::Export(sect) => { export = Some(sect); }
elements::Section::Start(index) => { start = Some(index); }
elements::Section::Element(sect) => { element = Some(sect); }
elements::Section::Code(sect) => { code = Some(sect); }
elements::Section::Data(sect) => { data = Some(sect); }
_ => {}
}
}
let mut sections = module.into_sections();
while let Some(section) = sections.pop() {
match section {
elements::Section::Type(sect) => { types = Some(sect); }
elements::Section::Import(sect) => { import = Some(sect); }
elements::Section::Function(sect) => { funcs = Some(sect); }
elements::Section::Table(sect) => { table = Some(sect); }
elements::Section::Memory(sect) => { memory = Some(sect); }
elements::Section::Global(sect) => { global = Some(sect); }
elements::Section::Export(sect) => { export = Some(sect); }
elements::Section::Start(index) => { start = Some(index); }
elements::Section::Element(sect) => { element = Some(sect); }
elements::Section::Code(sect) => { code = Some(sect); }
elements::Section::Data(sect) => { data = Some(sect); }
_ => {}
}
}
ModuleScaffold {
types: types.unwrap_or_default(),
import: import.unwrap_or_default(),
functions: funcs.unwrap_or_default(),
table: table.unwrap_or_default(),
memory: memory.unwrap_or_default(),
global: global.unwrap_or_default(),
export: export.unwrap_or_default(),
start: start,
element: element.unwrap_or_default(),
code: code.unwrap_or_default(),
data: data.unwrap_or_default(),
other: sections,
}
}
ModuleScaffold {
types: types.unwrap_or_default(),
import: import.unwrap_or_default(),
functions: funcs.unwrap_or_default(),
table: table.unwrap_or_default(),
memory: memory.unwrap_or_default(),
global: global.unwrap_or_default(),
export: export.unwrap_or_default(),
start: start,
element: element.unwrap_or_default(),
code: code.unwrap_or_default(),
data: data.unwrap_or_default(),
other: sections,
}
}
}
impl From<ModuleScaffold> for elements::Module {
fn from(module: ModuleScaffold) -> Self {
let mut sections = Vec::new();
fn from(module: ModuleScaffold) -> Self {
let mut sections = Vec::new();
let types = module.types;
if types.types().len() > 0 {
sections.push(elements::Section::Type(types));
}
let import = module.import;
if import.entries().len() > 0 {
sections.push(elements::Section::Import(import));
}
let functions = module.functions;
if functions.entries().len() > 0 {
sections.push(elements::Section::Function(functions));
}
let table = module.table;
if table.entries().len() > 0 {
sections.push(elements::Section::Table(table));
}
let memory = module.memory;
if memory.entries().len() > 0 {
sections.push(elements::Section::Memory(memory));
}
let global = module.global;
if global.entries().len() > 0 {
sections.push(elements::Section::Global(global));
}
let export = module.export;
if export.entries().len() > 0 {
sections.push(elements::Section::Export(export));
}
if let Some(start) = module.start {
sections.push(elements::Section::Start(start));
}
let element = module.element;
if element.entries().len() > 0 {
sections.push(elements::Section::Element(element));
}
let code = module.code;
if code.bodies().len() > 0 {
sections.push(elements::Section::Code(code));
}
let data = module.data;
if data.entries().len() > 0 {
sections.push(elements::Section::Data(data));
}
sections.extend(module.other);
elements::Module::new(sections)
}
let types = module.types;
if types.types().len() > 0 {
sections.push(elements::Section::Type(types));
}
let import = module.import;
if import.entries().len() > 0 {
sections.push(elements::Section::Import(import));
}
let functions = module.functions;
if functions.entries().len() > 0 {
sections.push(elements::Section::Function(functions));
}
let table = module.table;
if table.entries().len() > 0 {
sections.push(elements::Section::Table(table));
}
let memory = module.memory;
if memory.entries().len() > 0 {
sections.push(elements::Section::Memory(memory));
}
let global = module.global;
if global.entries().len() > 0 {
sections.push(elements::Section::Global(global));
}
let export = module.export;
if export.entries().len() > 0 {
sections.push(elements::Section::Export(export));
}
if let Some(start) = module.start {
sections.push(elements::Section::Start(start));
}
let element = module.element;
if element.entries().len() > 0 {
sections.push(elements::Section::Element(element));
}
let code = module.code;
if code.bodies().len() > 0 {
sections.push(elements::Section::Code(code));
}
let data = module.data;
if data.entries().len() > 0 {
sections.push(elements::Section::Data(data));
}
sections.extend(module.other);
elements::Module::new(sections)
}
}
impl ModuleBuilder {
/// New empty module builder
pub fn new() -> Self {
ModuleBuilder::with_callback(Identity)
}
/// New empty module builder
pub fn new() -> Self {
ModuleBuilder::with_callback(Identity)
}
}
impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
/// New module builder with bound callback
pub fn with_callback(callback: F) -> Self {
ModuleBuilder {
callback: callback,
module: Default::default(),
}
}
/// New module builder with bound callback
pub fn with_callback(callback: F) -> Self {
ModuleBuilder {
callback: callback,
module: Default::default(),
}
}
/// Builder from raw module
pub fn with_module(mut self, module: elements::Module) -> Self {
self.module = module.into();
self
}
/// Builder from raw module
pub fn with_module(mut self, module: elements::Module) -> Self {
self.module = module.into();
self
}
/// Fill module with sections from iterator
pub fn with_sections<I>(mut self, sections: I) -> Self
where I: IntoIterator<Item=elements::Section>
{
self.module.other.extend(sections);
self
}
/// Fill module with sections from iterator
pub fn with_sections<I>(mut self, sections: I) -> Self
where I: IntoIterator<Item=elements::Section>
{
self.module.other.extend(sections);
self
}
/// Add additional section
pub fn with_section(mut self, section: elements::Section) -> Self {
self.module.other.push(section);
self
}
/// Add additional section
pub fn with_section(mut self, section: elements::Section) -> Self {
self.module.other.push(section);
self
}
/// Binds to the type section, creates additional types when required
pub fn with_signatures(mut self, bindings: code::SignatureBindings) -> Self {
self.push_signatures(bindings);
self
}
/// Binds to the type section, creates additional types when required
pub fn with_signatures(mut self, bindings: code::SignatureBindings) -> Self {
self.push_signatures(bindings);
self
}
/// Push stand-alone function definition, creating sections, signature and code blocks
/// in corresponding sections.
/// `FunctionDefinition` can be build using `builder::function` builder
pub fn push_function(&mut self, func: code::FunctionDefinition) -> CodeLocation {
let signature = func.signature;
let body = func.code;
/// Push stand-alone function definition, creating sections, signature and code blocks
/// in corresponding sections.
/// `FunctionDefinition` can be build using `builder::function` builder
pub fn push_function(&mut self, func: code::FunctionDefinition) -> CodeLocation {
let signature = func.signature;
let body = func.code;
let type_ref = self.resolve_type_ref(signature);
let type_ref = self.resolve_type_ref(signature);
self.module.functions.entries_mut().push(elements::Func::new(type_ref));
let signature_index = self.module.functions.entries_mut().len() as u32 - 1;
self.module.code.bodies_mut().push(body);
let body_index = self.module.code.bodies_mut().len() as u32 - 1;
self.module.functions.entries_mut().push(elements::Func::new(type_ref));
let signature_index = self.module.functions.entries_mut().len() as u32 - 1;
self.module.code.bodies_mut().push(body);
let body_index = self.module.code.bodies_mut().len() as u32 - 1;
if func.is_main {
self.module.start = Some(body_index);
}
if func.is_main {
self.module.start = Some(body_index);
}
CodeLocation {
signature: signature_index,
body: body_index,
}
}
CodeLocation {
signature: signature_index,
body: body_index,
}
}
/// Push linear memory region
pub fn push_memory(&mut self, mut memory: memory::MemoryDefinition) -> u32 {
let entries = self.module.memory.entries_mut();
entries.push(elements::MemoryType::new(memory.min, memory.max));
let memory_index = (entries.len() - 1) as u32;
for data in memory.data.drain(..) {
self.module.data.entries_mut()
.push(elements::DataSegment::new(memory_index, data.offset, data.values))
}
memory_index
}
/// Push linear memory region
pub fn push_memory(&mut self, mut memory: memory::MemoryDefinition) -> u32 {
let entries = self.module.memory.entries_mut();
entries.push(elements::MemoryType::new(memory.min, memory.max));
let memory_index = (entries.len() - 1) as u32;
for data in memory.data.drain(..) {
self.module.data.entries_mut()
.push(elements::DataSegment::new(memory_index, data.offset, data.values))
}
memory_index
}
/// Push table
pub fn push_table(&mut self, mut table: table::TableDefinition) -> u32 {
let entries = self.module.table.entries_mut();
entries.push(elements::TableType::new(table.min, table.max));
let table_index = (entries.len() - 1) as u32;
for entry in table.elements.drain(..) {
self.module.element.entries_mut()
.push(elements::ElementSegment::new(table_index, entry.offset, entry.values))
}
table_index
}
/// Push table
pub fn push_table(&mut self, mut table: table::TableDefinition) -> u32 {
let entries = self.module.table.entries_mut();
entries.push(elements::TableType::new(table.min, table.max));
let table_index = (entries.len() - 1) as u32;
for entry in table.elements.drain(..) {
self.module.element.entries_mut()
.push(elements::ElementSegment::new(table_index, entry.offset, entry.values))
}
table_index
}
fn resolve_type_ref(&mut self, signature: code::Signature) -> u32 {
match signature {
code::Signature::Inline(func_type) => {
// todo: maybe search for existing type
self.module.types.types_mut().push(elements::Type::Function(func_type));
self.module.types.types().len() as u32 - 1
}
code::Signature::TypeReference(type_ref) => {
type_ref
}
}
}
fn resolve_type_ref(&mut self, signature: code::Signature) -> u32 {
match signature {
code::Signature::Inline(func_type) => {
// todo: maybe search for existing type
self.module.types.types_mut().push(elements::Type::Function(func_type));
self.module.types.types().len() as u32 - 1
}
code::Signature::TypeReference(type_ref) => {
type_ref
}
}
}
/// Push one function signature, returning it's calling index.
/// Can create corresponding type in type section.
pub fn push_signature(&mut self, signature: code::Signature) -> u32 {
self.resolve_type_ref(signature)
}
/// Push one function signature, returning it's calling index.
/// Can create corresponding type in type section.
pub fn push_signature(&mut self, signature: code::Signature) -> u32 {
self.resolve_type_ref(signature)
}
/// Push signatures in the module, returning corresponding indices of pushed signatures
pub fn push_signatures(&mut self, signatures: code::SignatureBindings) -> Vec<u32> {
signatures.into_iter().map(|binding|
self.resolve_type_ref(binding)
).collect()
}
/// Push signatures in the module, returning corresponding indices of pushed signatures
pub fn push_signatures(&mut self, signatures: code::SignatureBindings) -> Vec<u32> {
signatures.into_iter().map(|binding|
self.resolve_type_ref(binding)
).collect()
}
/// Push import entry to module. Not that it does not update calling indices in
/// function bodies.
pub fn push_import(&mut self, import: elements::ImportEntry) -> u32 {
self.module.import.entries_mut().push(import);
// todo: actually update calling addresses in function bodies
// todo: also batch push
/// Push import entry to module. Not that it does not update calling indices in
/// function bodies.
pub fn push_import(&mut self, import: elements::ImportEntry) -> u32 {
self.module.import.entries_mut().push(import);
// todo: actually update calling addresses in function bodies
// todo: also batch push
self.module.import.entries_mut().len() as u32 - 1
}
self.module.import.entries_mut().len() as u32 - 1
}
/// Push export entry to module.
pub fn push_export(&mut self, export: elements::ExportEntry) -> u32 {
self.module.export.entries_mut().push(export);
self.module.export.entries_mut().len() as u32 - 1
}
/// Push export entry to module.
pub fn push_export(&mut self, export: elements::ExportEntry) -> u32 {
self.module.export.entries_mut().push(export);
self.module.export.entries_mut().len() as u32 - 1
}
/// Add new function using dedicated builder
pub fn function(self) -> FunctionBuilder<Self> {
FunctionBuilder::with_callback(self)
}
/// Add new function using dedicated builder
pub fn function(self) -> FunctionBuilder<Self> {
FunctionBuilder::with_callback(self)
}
/// Add new linear memory using dedicated builder
pub fn memory(self) -> MemoryBuilder<Self> {
MemoryBuilder::with_callback(self)
}
/// Add new linear memory using dedicated builder
pub fn memory(self) -> MemoryBuilder<Self> {
MemoryBuilder::with_callback(self)
}
/// Add new table using dedicated builder
pub fn table(self) -> TableBuilder<Self> {
TableBuilder::with_callback(self)
}
/// Add new table using dedicated builder
pub fn table(self) -> TableBuilder<Self> {
TableBuilder::with_callback(self)
}
/// Define functions section
pub fn functions(self) -> SignaturesBuilder<Self> {
SignaturesBuilder::with_callback(self)
}
/// Define functions section
pub fn functions(self) -> SignaturesBuilder<Self> {
SignaturesBuilder::with_callback(self)
}
/// With inserted export entry
pub fn with_export(mut self, entry: elements::ExportEntry) -> Self {
self.module.export.entries_mut().push(entry);
self
}
/// With inserted export entry
pub fn with_export(mut self, entry: elements::ExportEntry) -> Self {
self.module.export.entries_mut().push(entry);
self
}
/// With inserted import entry
pub fn with_import(mut self, entry: elements::ImportEntry) -> Self {
self.module.import.entries_mut().push(entry);
self
}
/// With inserted import entry
pub fn with_import(mut self, entry: elements::ImportEntry) -> Self {
self.module.import.entries_mut().push(entry);
self
}
/// Import entry builder
/// # Examples
/// ```
/// use parity_wasm::builder::module;
///
/// let module = module()
/// .import()
/// .module("env")
/// .field("memory")
/// .external().memory(256, Some(256))
/// .build()
/// .build();
///
/// assert_eq!(module.import_section().expect("import section to exist").entries().len(), 1);
/// ```
pub fn import(self) -> import::ImportBuilder<Self> {
import::ImportBuilder::with_callback(self)
}
/// Import entry builder
/// # Examples
/// ```
/// use parity_wasm::builder::module;
///
/// let module = module()
/// .import()
/// .module("env")
/// .field("memory")
/// .external().memory(256, Some(256))
/// .build()
/// .build();
///
/// assert_eq!(module.import_section().expect("import section to exist").entries().len(), 1);
/// ```
pub fn import(self) -> import::ImportBuilder<Self> {
import::ImportBuilder::with_callback(self)
}
/// With global variable
pub fn with_global(mut self, global: elements::GlobalEntry) -> Self {
self.module.global.entries_mut().push(global);
self
}
/// With global variable
pub fn with_global(mut self, global: elements::GlobalEntry) -> Self {
self.module.global.entries_mut().push(global);
self
}
/// With table
pub fn with_table(mut self, table: elements::TableType) -> Self {
self.module.table.entries_mut().push(table);
self
}
/// With table
pub fn with_table(mut self, table: elements::TableType) -> Self {
self.module.table.entries_mut().push(table);
self
}
/// Export entry builder
/// # Examples
/// ```
/// use parity_wasm::builder::module;
/// use parity_wasm::elements::Opcode::*;
///
/// let module = module()
/// .global()
/// .value_type().i32()
/// .init_expr(I32Const(0))
/// .build()
/// .export()
/// .field("_zero")
/// .internal().global(0)
/// .build()
/// .build();
///
/// assert_eq!(module.export_section().expect("export section to exist").entries().len(), 1);
/// ```
pub fn export(self) -> export::ExportBuilder<Self> {
export::ExportBuilder::with_callback(self)
}
/// Export entry builder
/// # Examples
/// ```
/// use parity_wasm::builder::module;
/// use parity_wasm::elements::Opcode::*;
///
/// let module = module()
/// .global()
/// .value_type().i32()
/// .init_expr(I32Const(0))
/// .build()
/// .export()
/// .field("_zero")
/// .internal().global(0)
/// .build()
/// .build();
///
/// assert_eq!(module.export_section().expect("export section to exist").entries().len(), 1);
/// ```
pub fn export(self) -> export::ExportBuilder<Self> {
export::ExportBuilder::with_callback(self)
}
/// Glboal entry builder
/// # Examples
/// ```
/// use parity_wasm::builder::module;
/// use parity_wasm::elements::Opcode::*;
///
/// let module = module()
/// .global()
/// .value_type().i32()
/// .init_expr(I32Const(0))
/// .build()
/// .build();
///
/// assert_eq!(module.global_section().expect("global section to exist").entries().len(), 1);
/// ```
pub fn global(self) -> global::GlobalBuilder<Self> {
global::GlobalBuilder::with_callback(self)
}
/// Glboal entry builder
/// # Examples
/// ```
/// use parity_wasm::builder::module;
/// use parity_wasm::elements::Opcode::*;
///
/// let module = module()
/// .global()
/// .value_type().i32()
/// .init_expr(I32Const(0))
/// .build()
/// .build();
///
/// assert_eq!(module.global_section().expect("global section to exist").entries().len(), 1);
/// ```
pub fn global(self) -> global::GlobalBuilder<Self> {
global::GlobalBuilder::with_callback(self)
}
/// Add data segment to the builder
pub fn with_data_segment(mut self, segment: elements::DataSegment) -> Self {
self.module.data.entries_mut().push(segment);
self
}
/// Add data segment to the builder
pub fn with_data_segment(mut self, segment: elements::DataSegment) -> Self {
self.module.data.entries_mut().push(segment);
self
}
/// Data entry builder
pub fn data(self) -> data::DataSegmentBuilder<Self> {
data::DataSegmentBuilder::with_callback(self)
}
/// Data entry builder
pub fn data(self) -> data::DataSegmentBuilder<Self> {
data::DataSegmentBuilder::with_callback(self)
}
/// Build module (final step)
pub fn build(self) -> F::Result {
self.callback.invoke(self.module.into())
}
/// Build module (final step)
pub fn build(self) -> F::Result {
self.callback.invoke(self.module.into())
}
}
impl<F> Invoke<elements::FunctionSection> for ModuleBuilder<F>
where F: Invoke<elements::Module>
impl<F> Invoke<elements::FunctionSection> for ModuleBuilder<F>
where F: Invoke<elements::Module>
{
type Result = Self;
fn invoke(self, section: elements::FunctionSection) -> Self {
self.with_section(elements::Section::Function(section))
}
}
}
impl<F> Invoke<code::SignatureBindings> for ModuleBuilder<F>
where F: Invoke<elements::Module>
where F: Invoke<elements::Module>
{
type Result = Self;
type Result = Self;
fn invoke(self, bindings: code::SignatureBindings) -> Self {
self.with_signatures(bindings)
}
fn invoke(self, bindings: code::SignatureBindings) -> Self {
self.with_signatures(bindings)
}
}
impl<F> Invoke<code::FunctionDefinition> for ModuleBuilder<F>
where F: Invoke<elements::Module>
where F: Invoke<elements::Module>
{
type Result = Self;
type Result = Self;
fn invoke(self, def: code::FunctionDefinition) -> Self {
let mut b = self;
b.push_function(def);
b
}
fn invoke(self, def: code::FunctionDefinition) -> Self {
let mut b = self;
b.push_function(def);
b
}
}
impl<F> Invoke<memory::MemoryDefinition> for ModuleBuilder<F>
where F: Invoke<elements::Module>
where F: Invoke<elements::Module>
{
type Result = Self;
type Result = Self;
fn invoke(self, def: memory::MemoryDefinition) -> Self {
let mut b = self;
b.push_memory(def);
b
}
fn invoke(self, def: memory::MemoryDefinition) -> Self {
let mut b = self;
b.push_memory(def);
b
}
}
impl<F> Invoke<table::TableDefinition> for ModuleBuilder<F>
where F: Invoke<elements::Module>
where F: Invoke<elements::Module>
{
type Result = Self;
type Result = Self;
fn invoke(self, def: table::TableDefinition) -> Self {
let mut b = self;
b.push_table(def);
b
}
fn invoke(self, def: table::TableDefinition) -> Self {
let mut b = self;
b.push_table(def);
b
}
}
impl<F> Invoke<elements::ImportEntry> for ModuleBuilder<F>
where F: Invoke<elements::Module>
where F: Invoke<elements::Module>
{
type Result = Self;
type Result = Self;
fn invoke(self, entry: elements::ImportEntry) -> Self::Result {
self.with_import(entry)
}
fn invoke(self, entry: elements::ImportEntry) -> Self::Result {
self.with_import(entry)
}
}
impl<F> Invoke<elements::ExportEntry> for ModuleBuilder<F>
where F: Invoke<elements::Module>
where F: Invoke<elements::Module>
{
type Result = Self;
type Result = Self;
fn invoke(self, entry: elements::ExportEntry) -> Self::Result {
self.with_export(entry)
}
fn invoke(self, entry: elements::ExportEntry) -> Self::Result {
self.with_export(entry)
}
}
impl<F> Invoke<elements::GlobalEntry> for ModuleBuilder<F>
where F: Invoke<elements::Module>
where F: Invoke<elements::Module>
{
type Result = Self;
type Result = Self;
fn invoke(self, entry: elements::GlobalEntry) -> Self::Result {
self.with_global(entry)
}
fn invoke(self, entry: elements::GlobalEntry) -> Self::Result {
self.with_global(entry)
}
}
impl<F> Invoke<elements::DataSegment> for ModuleBuilder<F>
where F: Invoke<elements::Module>
impl<F> Invoke<elements::DataSegment> for ModuleBuilder<F>
where F: Invoke<elements::Module>
{
type Result = Self;
fn invoke(self, segment: elements::DataSegment) -> Self {
self.with_data_segment(segment)
}
}
}
/// Start new module builder
@ -492,7 +492,7 @@ impl<F> Invoke<elements::DataSegment> for ModuleBuilder<F>
///
/// ```
/// use parity_wasm::builder;
///
///
/// let module = builder::module()
/// .function()
/// .signature().param().i32().build()
@ -505,66 +505,66 @@ impl<F> Invoke<elements::DataSegment> for ModuleBuilder<F>
/// assert_eq!(module.code_section().expect("code section to exist").bodies().len(), 1);
/// ```
pub fn module() -> ModuleBuilder {
ModuleBuilder::new()
ModuleBuilder::new()
}
/// Start builder to extend existing module
pub fn from_module(module: elements::Module) -> ModuleBuilder {
ModuleBuilder::new().with_module(module)
ModuleBuilder::new().with_module(module)
}
#[cfg(test)]
mod tests {
use super::module;
use super::module;
#[test]
fn smoky() {
let module = module().build();
assert_eq!(module.sections().len(), 0);
}
#[test]
fn smoky() {
let module = module().build();
assert_eq!(module.sections().len(), 0);
}
#[test]
fn functions() {
let module = module()
.function()
.signature().param().i32().build()
.body().build()
.build()
.build();
#[test]
fn functions() {
let module = module()
.function()
.signature().param().i32().build()
.body().build()
.build()
.build();
assert_eq!(module.type_section().expect("type section to exist").types().len(), 1);
assert_eq!(module.function_section().expect("function section to exist").entries().len(), 1);
assert_eq!(module.code_section().expect("code section to exist").bodies().len(), 1);
}
assert_eq!(module.type_section().expect("type section to exist").types().len(), 1);
assert_eq!(module.function_section().expect("function section to exist").entries().len(), 1);
assert_eq!(module.code_section().expect("code section to exist").bodies().len(), 1);
}
#[test]
fn export() {
let module = module()
.export().field("call").internal().func(0).build()
.build();
#[test]
fn export() {
let module = module()
.export().field("call").internal().func(0).build()
.build();
assert_eq!(module.export_section().expect("export section to exist").entries().len(), 1);
}
assert_eq!(module.export_section().expect("export section to exist").entries().len(), 1);
}
#[test]
fn global() {
let module = module()
.global().value_type().i64().mutable().init_expr(::elements::Opcode::I64Const(5)).build()
.build();
#[test]
fn global() {
let module = module()
.global().value_type().i64().mutable().init_expr(::elements::Opcode::I64Const(5)).build()
.build();
assert_eq!(module.global_section().expect("global section to exist").entries().len(), 1);
}
assert_eq!(module.global_section().expect("global section to exist").entries().len(), 1);
}
#[test]
fn data() {
let module = module()
.data()
.offset(::elements::Opcode::I32Const(16))
.value(vec![0u8, 15, 10, 5, 25])
.build()
.build();
#[test]
fn data() {
let module = module()
.data()
.offset(::elements::Opcode::I32Const(16))
.value(vec![0u8, 15, 10, 5, 25])
.build()
.build();
assert_eq!(module.data_section().expect("data section to exist").entries().len(), 1);
}
assert_eq!(module.data_section().expect("data section to exist").entries().len(), 1);
}
}

View File

@ -4,81 +4,81 @@ use super::invoke::{Invoke, Identity};
/// Table definition
#[derive(Debug)]
pub struct TableDefinition {
/// Minimum length
pub min: u32,
/// Maximum length, if any
pub max: Option<u32>,
/// Element segments, if any
pub elements: Vec<TableEntryDefinition>,
/// Minimum length
pub min: u32,
/// Maximum length, if any
pub max: Option<u32>,
/// Element segments, if any
pub elements: Vec<TableEntryDefinition>,
}
/// Table elements entry definition
#[derive(Debug)]
pub struct TableEntryDefinition {
/// Offset initialization expression
pub offset: elements::InitExpr,
/// Values of initialization
pub values: Vec<u32>,
/// Offset initialization expression
pub offset: elements::InitExpr,
/// Values of initialization
pub values: Vec<u32>,
}
/// Table builder
pub struct TableBuilder<F=Identity> {
callback: F,
table: TableDefinition,
callback: F,
table: TableDefinition,
}
impl TableBuilder {
/// New table builder
pub fn new() -> Self {
TableBuilder::with_callback(Identity)
}
/// New table builder
pub fn new() -> Self {
TableBuilder::with_callback(Identity)
}
}
impl<F> TableBuilder<F> where F: Invoke<TableDefinition> {
/// New table builder with callback in chained context
pub fn with_callback(callback: F) -> Self {
TableBuilder {
callback: callback,
table: Default::default(),
}
}
/// New table builder with callback in chained context
pub fn with_callback(callback: F) -> Self {
TableBuilder {
callback: callback,
table: Default::default(),
}
}
/// Set/override minimum length
pub fn with_min(mut self, min: u32) -> Self {
self.table.min = min;
self
}
/// Set/override minimum length
pub fn with_min(mut self, min: u32) -> Self {
self.table.min = min;
self
}
/// Set/override maximum length
pub fn with_max(mut self, max: Option<u32>) -> Self {
self.table.max = max;
self
}
/// Set/override maximum length
pub fn with_max(mut self, max: Option<u32>) -> Self {
self.table.max = max;
self
}
/// Generate initialization expression and element values on specified index
pub fn with_element(mut self, index: u32, values: Vec<u32>) -> Self {
self.table.elements.push(TableEntryDefinition {
offset: elements::InitExpr::new(vec![
elements::Opcode::I32Const(index as i32),
elements::Opcode::End,
]),
values: values,
});
self
}
/// Generate initialization expression and element values on specified index
pub fn with_element(mut self, index: u32, values: Vec<u32>) -> Self {
self.table.elements.push(TableEntryDefinition {
offset: elements::InitExpr::new(vec![
elements::Opcode::I32Const(index as i32),
elements::Opcode::End,
]),
values: values,
});
self
}
/// Finalize current builder spawning resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(self.table)
}
/// Finalize current builder spawning resulting struct
pub fn build(self) -> F::Result {
self.callback.invoke(self.table)
}
}
impl Default for TableDefinition {
fn default() -> Self {
TableDefinition {
min: 0,
max: None,
elements: Vec::new(),
}
}
fn default() -> Self {
TableDefinition {
min: 0,
max: None,
elements: Vec::new(),
}
}
}

View File

@ -4,98 +4,98 @@ use super::{Deserialize, Serialize, Error, VarUint7, VarUint32};
/// Internal reference of the exported entry.
#[derive(Debug, Clone, Copy)]
pub enum Internal {
/// Function reference.
Function(u32),
/// Table reference.
Table(u32),
/// Memory reference.
Memory(u32),
/// Global reference.
Global(u32),
/// Function reference.
Function(u32),
/// Table reference.
Table(u32),
/// Memory reference.
Memory(u32),
/// Global reference.
Global(u32),
}
impl Deserialize for Internal {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let kind = VarUint7::deserialize(reader)?;
match kind.into() {
0x00 => Ok(Internal::Function(VarUint32::deserialize(reader)?.into())),
0x01 => Ok(Internal::Table(VarUint32::deserialize(reader)?.into())),
0x02 => Ok(Internal::Memory(VarUint32::deserialize(reader)?.into())),
0x03 => Ok(Internal::Global(VarUint32::deserialize(reader)?.into())),
_ => Err(Error::UnknownInternalKind(kind.into())),
}
}
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let kind = VarUint7::deserialize(reader)?;
match kind.into() {
0x00 => Ok(Internal::Function(VarUint32::deserialize(reader)?.into())),
0x01 => Ok(Internal::Table(VarUint32::deserialize(reader)?.into())),
0x02 => Ok(Internal::Memory(VarUint32::deserialize(reader)?.into())),
0x03 => Ok(Internal::Global(VarUint32::deserialize(reader)?.into())),
_ => Err(Error::UnknownInternalKind(kind.into())),
}
}
}
impl Serialize for Internal {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let (bt, arg) = match self {
Internal::Function(arg) => (0x00, arg),
Internal::Table(arg) => (0x01, arg),
Internal::Memory(arg) => (0x02, arg),
Internal::Global(arg) => (0x03, arg),
};
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let (bt, arg) = match self {
Internal::Function(arg) => (0x00, arg),
Internal::Table(arg) => (0x01, arg),
Internal::Memory(arg) => (0x02, arg),
Internal::Global(arg) => (0x03, arg),
};
VarUint7::from(bt).serialize(writer)?;
VarUint32::from(arg).serialize(writer)?;
VarUint7::from(bt).serialize(writer)?;
VarUint32::from(arg).serialize(writer)?;
Ok(())
}
Ok(())
}
}
/// Export entry.
#[derive(Debug, Clone)]
pub struct ExportEntry {
field_str: String,
internal: Internal,
field_str: String,
internal: Internal,
}
impl ExportEntry {
/// New export entry
pub fn new(field: String, internal: Internal) -> Self {
ExportEntry {
field_str: field,
internal: internal
}
}
/// New export entry
pub fn new(field: String, internal: Internal) -> Self {
ExportEntry {
field_str: field,
internal: internal
}
}
/// Public name
pub fn field(&self) -> &str { &self.field_str }
/// Public name
pub fn field(&self) -> &str { &self.field_str }
/// Public name (mutable)
pub fn field_mut(&mut self) -> &mut String { &mut self.field_str }
/// Public name (mutable)
pub fn field_mut(&mut self) -> &mut String { &mut self.field_str }
/// Internal reference of the export entry.
pub fn internal(&self) -> &Internal { &self.internal }
/// Internal reference of the export entry.
pub fn internal(&self) -> &Internal { &self.internal }
/// Internal reference of the export entry (mutable).
pub fn internal_mut(&mut self) -> &mut Internal { &mut self.internal }
/// Internal reference of the export entry (mutable).
pub fn internal_mut(&mut self) -> &mut Internal { &mut self.internal }
}
impl Deserialize for ExportEntry {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let field_str = String::deserialize(reader)?;
let internal = Internal::deserialize(reader)?;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let field_str = String::deserialize(reader)?;
let internal = Internal::deserialize(reader)?;
Ok(ExportEntry {
field_str: field_str,
internal: internal,
})
}
Ok(ExportEntry {
field_str: field_str,
internal: internal,
})
}
}
impl Serialize for ExportEntry {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.field_str.serialize(writer)?;
self.internal.serialize(writer)?;
Ok(())
}
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.field_str.serialize(writer)?;
self.internal.serialize(writer)?;
Ok(())
}
}

View File

@ -1,7 +1,7 @@
use std::io;
use super::{
Deserialize, Error, ValueType, VarUint32, CountedList, Opcodes,
Serialize, CountedWriter, CountedListWriter,
Deserialize, Error, ValueType, VarUint32, CountedList, Opcodes,
Serialize, CountedWriter, CountedListWriter,
};
/// Function signature (type reference)
@ -9,122 +9,122 @@ use super::{
pub struct Func(u32);
impl Func {
/// New function signature
pub fn new(type_ref: u32) -> Self { Func(type_ref) }
/// New function signature
pub fn new(type_ref: u32) -> Self { Func(type_ref) }
/// Function signature type reference.
pub fn type_ref(&self) -> u32 {
self.0
}
/// Function signature type reference.
pub fn type_ref(&self) -> u32 {
self.0
}
/// Function signature type reference (mutable).
pub fn type_ref_mut(&mut self) -> &mut u32 {
&mut self.0
}
/// Function signature type reference (mutable).
pub fn type_ref_mut(&mut self) -> &mut u32 {
&mut self.0
}
}
/// Local definition inside the function body.
#[derive(Debug, Copy, Clone)]
pub struct Local {
count: u32,
value_type: ValueType,
count: u32,
value_type: ValueType,
}
impl Local {
/// New local with `count` and `value_type`.
pub fn new(count: u32, value_type: ValueType) -> Self {
Local { count: count, value_type: value_type }
}
/// New local with `count` and `value_type`.
pub fn new(count: u32, value_type: ValueType) -> Self {
Local { count: count, value_type: value_type }
}
/// Number of locals with the shared type.
pub fn count(&self) -> u32 { self.count }
/// Number of locals with the shared type.
pub fn count(&self) -> u32 { self.count }
/// Type of the locals.
pub fn value_type(&self) -> ValueType { self.value_type }
/// Type of the locals.
pub fn value_type(&self) -> ValueType { self.value_type }
}
impl Deserialize for Local {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let count = VarUint32::deserialize(reader)?;
let value_type = ValueType::deserialize(reader)?;
Ok(Local { count: count.into(), value_type: value_type })
}
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let count = VarUint32::deserialize(reader)?;
let value_type = ValueType::deserialize(reader)?;
Ok(Local { count: count.into(), value_type: value_type })
}
}
impl Serialize for Local {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
VarUint32::from(self.count).serialize(writer)?;
self.value_type.serialize(writer)?;
Ok(())
}
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
VarUint32::from(self.count).serialize(writer)?;
self.value_type.serialize(writer)?;
Ok(())
}
}
/// Function body definition.
#[derive(Debug, Clone)]
pub struct FuncBody {
locals: Vec<Local>,
opcodes: Opcodes,
locals: Vec<Local>,
opcodes: Opcodes,
}
impl FuncBody {
/// New function body with given `locals` and `opcodes`
pub fn new(locals: Vec<Local>, opcodes: Opcodes) -> Self {
FuncBody { locals: locals, opcodes: opcodes }
}
/// New function body with given `locals` and `opcodes`
pub fn new(locals: Vec<Local>, opcodes: Opcodes) -> Self {
FuncBody { locals: locals, opcodes: opcodes }
}
/// List of individual opcodes
pub fn empty() -> Self {
FuncBody { locals: Vec::new(), opcodes: Opcodes::empty() }
}
/// List of individual opcodes
pub fn empty() -> Self {
FuncBody { locals: Vec::new(), opcodes: Opcodes::empty() }
}
/// Locals declared in function body.
pub fn locals(&self) -> &[Local] { &self.locals }
/// Locals declared in function body.
pub fn locals(&self) -> &[Local] { &self.locals }
/// Opcode sequence of the function body. Minimal opcode sequence
/// is just `&[Opcode::End]`
pub fn code(&self) -> &Opcodes { &self.opcodes }
/// Opcode sequence of the function body. Minimal opcode sequence
/// is just `&[Opcode::End]`
pub fn code(&self) -> &Opcodes { &self.opcodes }
/// Locals declared in function body (mutable).
pub fn locals_mut(&mut self) -> &mut Vec<Local> { &mut self.locals }
/// Locals declared in function body (mutable).
pub fn locals_mut(&mut self) -> &mut Vec<Local> { &mut self.locals }
/// Opcode sequence of the function body (mutable).
pub fn code_mut(&mut self) -> &mut Opcodes { &mut self.opcodes }
/// Opcode sequence of the function body (mutable).
pub fn code_mut(&mut self) -> &mut Opcodes { &mut self.opcodes }
}
impl Deserialize for FuncBody {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
// todo: maybe use reader.take(section_length)
let _body_size = VarUint32::deserialize(reader)?;
let locals: Vec<Local> = CountedList::deserialize(reader)?.into_inner();
let opcodes = Opcodes::deserialize(reader)?;
Ok(FuncBody { locals: locals, opcodes: opcodes })
}
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
// todo: maybe use reader.take(section_length)
let _body_size = VarUint32::deserialize(reader)?;
let locals: Vec<Local> = CountedList::deserialize(reader)?.into_inner();
let opcodes = Opcodes::deserialize(reader)?;
Ok(FuncBody { locals: locals, opcodes: opcodes })
}
}
impl Serialize for FuncBody {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.locals;
let counted_list = CountedListWriter::<Local, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(&mut counted_writer)?;
let data = self.locals;
let counted_list = CountedListWriter::<Local, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(&mut counted_writer)?;
let code = self.opcodes;
code.serialize(&mut counted_writer)?;
let code = self.opcodes;
code.serialize(&mut counted_writer)?;
counted_writer.done()?;
counted_writer.done()?;
Ok(())
}
Ok(())
}
}

View File

@ -4,47 +4,47 @@ use super::{Deserialize, Serialize, Error, GlobalType, InitExpr};
/// Global entry in the module.
#[derive(Clone, Debug)]
pub struct GlobalEntry {
global_type: GlobalType,
init_expr: InitExpr,
global_type: GlobalType,
init_expr: InitExpr,
}
impl GlobalEntry {
/// New global entry
pub fn new(global_type: GlobalType, init_expr: InitExpr) -> Self {
GlobalEntry {
global_type: global_type,
init_expr: init_expr,
}
}
/// Global type.
pub fn global_type(&self) -> &GlobalType { &self.global_type }
/// Initialization expression (opcodes) for global.
pub fn init_expr(&self) -> &InitExpr { &self.init_expr }
/// Global type (mutable)
pub fn global_type_mut(&mut self) -> &mut GlobalType { &mut self.global_type }
/// Initialization expression (opcodes) for global (mutable)
pub fn init_expr_mut(&mut self) -> &mut InitExpr { &mut self.init_expr }
/// New global entry
pub fn new(global_type: GlobalType, init_expr: InitExpr) -> Self {
GlobalEntry {
global_type: global_type,
init_expr: init_expr,
}
}
/// Global type.
pub fn global_type(&self) -> &GlobalType { &self.global_type }
/// Initialization expression (opcodes) for global.
pub fn init_expr(&self) -> &InitExpr { &self.init_expr }
/// Global type (mutable)
pub fn global_type_mut(&mut self) -> &mut GlobalType { &mut self.global_type }
/// Initialization expression (opcodes) for global (mutable)
pub fn init_expr_mut(&mut self) -> &mut InitExpr { &mut self.init_expr }
}
impl Deserialize for GlobalEntry {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let global_type = GlobalType::deserialize(reader)?;
let init_expr = InitExpr::deserialize(reader)?;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let global_type = GlobalType::deserialize(reader)?;
let init_expr = InitExpr::deserialize(reader)?;
Ok(GlobalEntry {
global_type: global_type,
init_expr: init_expr,
})
}
Ok(GlobalEntry {
global_type: global_type,
init_expr: init_expr,
})
}
}
impl Serialize for GlobalEntry {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.global_type.serialize(writer)?;
self.init_expr.serialize(writer)
}
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.global_type.serialize(writer)?;
self.init_expr.serialize(writer)
}
}

View File

@ -1,152 +1,152 @@
use std::io;
use super::{
Deserialize, Serialize, Error, VarUint7, VarInt7, VarUint32, VarUint1,
ValueType, TableElementType
Deserialize, Serialize, Error, VarUint7, VarInt7, VarUint32, VarUint1,
ValueType, TableElementType
};
/// Global definition struct
#[derive(Debug, Copy, Clone)]
pub struct GlobalType {
content_type: ValueType,
is_mutable: bool,
content_type: ValueType,
is_mutable: bool,
}
impl GlobalType {
/// New global type
pub fn new(content_type: ValueType, is_mutable: bool) -> Self {
GlobalType {
content_type: content_type,
is_mutable: is_mutable,
}
}
/// New global type
pub fn new(content_type: ValueType, is_mutable: bool) -> Self {
GlobalType {
content_type: content_type,
is_mutable: is_mutable,
}
}
/// Type of the global entry
pub fn content_type(&self) -> ValueType { self.content_type }
/// Type of the global entry
pub fn content_type(&self) -> ValueType { self.content_type }
/// Is global entry is declared as mutable
pub fn is_mutable(&self) -> bool { self.is_mutable }
/// Is global entry is declared as mutable
pub fn is_mutable(&self) -> bool { self.is_mutable }
}
impl Deserialize for GlobalType {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let content_type = ValueType::deserialize(reader)?;
let is_mutable = VarUint1::deserialize(reader)?;
Ok(GlobalType {
content_type: content_type,
is_mutable: is_mutable.into(),
})
}
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let content_type = ValueType::deserialize(reader)?;
let is_mutable = VarUint1::deserialize(reader)?;
Ok(GlobalType {
content_type: content_type,
is_mutable: is_mutable.into(),
})
}
}
impl Serialize for GlobalType {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.content_type.serialize(writer)?;
VarUint1::from(self.is_mutable).serialize(writer)?;
Ok(())
}
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.content_type.serialize(writer)?;
VarUint1::from(self.is_mutable).serialize(writer)?;
Ok(())
}
}
/// Table entry
#[derive(Debug, Copy, Clone)]
pub struct TableType {
elem_type: TableElementType,
limits: ResizableLimits,
elem_type: TableElementType,
limits: ResizableLimits,
}
impl TableType {
/// New table definition
pub fn new(min: u32, max: Option<u32>) -> Self {
TableType {
elem_type: TableElementType::AnyFunc,
limits: ResizableLimits::new(min, max),
}
}
/// New table definition
pub fn new(min: u32, max: Option<u32>) -> Self {
TableType {
elem_type: TableElementType::AnyFunc,
limits: ResizableLimits::new(min, max),
}
}
/// Table memory specification
pub fn limits(&self) -> &ResizableLimits { &self.limits }
/// Table memory specification
pub fn limits(&self) -> &ResizableLimits { &self.limits }
/// Table element type
pub fn elem_type(&self) -> TableElementType { self.elem_type }
/// Table element type
pub fn elem_type(&self) -> TableElementType { self.elem_type }
}
impl Deserialize for TableType {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let elem_type = TableElementType::deserialize(reader)?;
let limits = ResizableLimits::deserialize(reader)?;
Ok(TableType {
elem_type: elem_type,
limits: limits,
})
}
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let elem_type = TableElementType::deserialize(reader)?;
let limits = ResizableLimits::deserialize(reader)?;
Ok(TableType {
elem_type: elem_type,
limits: limits,
})
}
}
impl Serialize for TableType {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.elem_type.serialize(writer)?;
self.limits.serialize(writer)
}
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.elem_type.serialize(writer)?;
self.limits.serialize(writer)
}
}
/// Memory limits
#[derive(Debug, Copy, Clone)]
pub struct ResizableLimits {
initial: u32,
maximum: Option<u32>,
initial: u32,
maximum: Option<u32>,
}
impl ResizableLimits {
/// New memory limits definition
pub fn new(min: u32, max: Option<u32>) -> Self {
ResizableLimits {
initial: min,
maximum: max,
}
}
/// Initial size
pub fn initial(&self) -> u32 { self.initial }
/// Maximum size
pub fn maximum(&self) -> Option<u32> { self.maximum }
/// New memory limits definition
pub fn new(min: u32, max: Option<u32>) -> Self {
ResizableLimits {
initial: min,
maximum: max,
}
}
/// Initial size
pub fn initial(&self) -> u32 { self.initial }
/// Maximum size
pub fn maximum(&self) -> Option<u32> { self.maximum }
}
impl Deserialize for ResizableLimits {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let has_max = VarUint1::deserialize(reader)?;
let initial = VarUint32::deserialize(reader)?;
let maximum = if has_max.into() {
Some(VarUint32::deserialize(reader)?.into())
} else {
None
};
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let has_max = VarUint1::deserialize(reader)?;
let initial = VarUint32::deserialize(reader)?;
let maximum = if has_max.into() {
Some(VarUint32::deserialize(reader)?.into())
} else {
None
};
Ok(ResizableLimits {
initial: initial.into(),
maximum: maximum,
})
}
Ok(ResizableLimits {
initial: initial.into(),
maximum: maximum,
})
}
}
impl Serialize for ResizableLimits {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let max = self.maximum;
VarUint1::from(max.is_some()).serialize(writer)?;
VarUint32::from(self.initial).serialize(writer)?;
if let Some(val) = max {
VarUint32::from(val).serialize(writer)?;
}
Ok(())
}
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let max = self.maximum;
VarUint1::from(max.is_some()).serialize(writer)?;
VarUint32::from(self.initial).serialize(writer)?;
if let Some(val) = max {
VarUint32::from(val).serialize(writer)?;
}
Ok(())
}
}
/// Memory entry.
@ -154,152 +154,152 @@ impl Serialize for ResizableLimits {
pub struct MemoryType(ResizableLimits);
impl MemoryType {
/// New memory definition
pub fn new(min: u32, max: Option<u32>) -> Self {
MemoryType(ResizableLimits::new(min, max))
}
/// Limits of the memory entry.
pub fn limits(&self) -> &ResizableLimits {
&self.0
}
/// New memory definition
pub fn new(min: u32, max: Option<u32>) -> Self {
MemoryType(ResizableLimits::new(min, max))
}
/// Limits of the memory entry.
pub fn limits(&self) -> &ResizableLimits {
&self.0
}
}
impl Deserialize for MemoryType {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(MemoryType(ResizableLimits::deserialize(reader)?))
}
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(MemoryType(ResizableLimits::deserialize(reader)?))
}
}
impl Serialize for MemoryType {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.0.serialize(writer)
}
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.0.serialize(writer)
}
}
/// External to local binding.
#[derive(Debug, Copy, Clone)]
pub enum External {
/// Binds to function with index.
Function(u32),
/// Describes local table definition to be imported as.
Table(TableType),
/// Describes local memory definition to be imported as.
Memory(MemoryType),
/// Describes local global entry to be imported as.
Global(GlobalType),
/// Binds to function with index.
Function(u32),
/// Describes local table definition to be imported as.
Table(TableType),
/// Describes local memory definition to be imported as.
Memory(MemoryType),
/// Describes local global entry to be imported as.
Global(GlobalType),
}
impl Deserialize for External {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let kind = VarUint7::deserialize(reader)?;
match kind.into() {
0x00 => Ok(External::Function(VarUint32::deserialize(reader)?.into())),
0x01 => Ok(External::Table(TableType::deserialize(reader)?)),
0x02 => Ok(External::Memory(MemoryType::deserialize(reader)?)),
0x03 => Ok(External::Global(GlobalType::deserialize(reader)?)),
_ => Err(Error::UnknownExternalKind(kind.into())),
}
}
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let kind = VarUint7::deserialize(reader)?;
match kind.into() {
0x00 => Ok(External::Function(VarUint32::deserialize(reader)?.into())),
0x01 => Ok(External::Table(TableType::deserialize(reader)?)),
0x02 => Ok(External::Memory(MemoryType::deserialize(reader)?)),
0x03 => Ok(External::Global(GlobalType::deserialize(reader)?)),
_ => Err(Error::UnknownExternalKind(kind.into())),
}
}
}
impl Serialize for External {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
use self::External::*;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
use self::External::*;
match self {
Function(index) => {
VarUint7::from(0x00).serialize(writer)?;
VarUint32::from(index).serialize(writer)?;
},
Table(tt) => {
VarInt7::from(0x01).serialize(writer)?;
tt.serialize(writer)?;
},
Memory(mt) => {
VarInt7::from(0x02).serialize(writer)?;
mt.serialize(writer)?;
},
Global(gt) => {
VarInt7::from(0x03).serialize(writer)?;
gt.serialize(writer)?;
},
}
match self {
Function(index) => {
VarUint7::from(0x00).serialize(writer)?;
VarUint32::from(index).serialize(writer)?;
},
Table(tt) => {
VarInt7::from(0x01).serialize(writer)?;
tt.serialize(writer)?;
},
Memory(mt) => {
VarInt7::from(0x02).serialize(writer)?;
mt.serialize(writer)?;
},
Global(gt) => {
VarInt7::from(0x03).serialize(writer)?;
gt.serialize(writer)?;
},
}
Ok(())
}
Ok(())
}
}
/// Import entry.
#[derive(Debug, Clone)]
pub struct ImportEntry {
module_str: String,
field_str: String,
external: External,
module_str: String,
field_str: String,
external: External,
}
impl ImportEntry {
/// New import entry.
pub fn new(module_str: String, field_str: String, external: External) -> Self {
ImportEntry {
module_str: module_str,
field_str: field_str,
external: external,
}
}
/// New import entry.
pub fn new(module_str: String, field_str: String, external: External) -> Self {
ImportEntry {
module_str: module_str,
field_str: field_str,
external: external,
}
}
/// Module reference of the import entry.
pub fn module(&self) -> &str { &self.module_str }
/// Module reference of the import entry.
pub fn module(&self) -> &str { &self.module_str }
/// Module reference of the import entry (mutable).
pub fn module_mut(&mut self) -> &mut String {
&mut self.module_str
}
/// Module reference of the import entry (mutable).
pub fn module_mut(&mut self) -> &mut String {
&mut self.module_str
}
/// Field reference of the import entry.
pub fn field(&self) -> &str { &self.field_str }
/// Field reference of the import entry.
pub fn field(&self) -> &str { &self.field_str }
/// Field reference of the import entry (mutable)
pub fn field_mut(&mut self) -> &mut String {
&mut self.field_str
}
/// Field reference of the import entry (mutable)
pub fn field_mut(&mut self) -> &mut String {
&mut self.field_str
}
/// Local binidng of the import entry.
pub fn external(&self) -> &External { &self.external }
/// Local binidng of the import entry.
pub fn external(&self) -> &External { &self.external }
/// Local binidng of the import entry (mutable)
pub fn external_mut(&mut self) -> &mut External { &mut self.external }
/// Local binidng of the import entry (mutable)
pub fn external_mut(&mut self) -> &mut External { &mut self.external }
}
impl Deserialize for ImportEntry {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let module_str = String::deserialize(reader)?;
let field_str = String::deserialize(reader)?;
let external = External::deserialize(reader)?;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let module_str = String::deserialize(reader)?;
let field_str = String::deserialize(reader)?;
let external = External::deserialize(reader)?;
Ok(ImportEntry {
module_str: module_str,
field_str: field_str,
external: external,
})
}
Ok(ImportEntry {
module_str: module_str,
field_str: field_str,
external: external,
})
}
}
impl Serialize for ImportEntry {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.module_str.serialize(writer)?;
self.field_str.serialize(writer)?;
self.external.serialize(writer)
}
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.module_str.serialize(writer)?;
self.field_str.serialize(writer)?;
self.external.serialize(writer)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -19,16 +19,16 @@ mod name_section;
pub use self::module::{Module, peek_size, ImportCountType};
pub use self::section::{
Section, FunctionSection, CodeSection, MemorySection, DataSection,
ImportSection, ExportSection, GlobalSection, TypeSection, ElementSection,
TableSection, CustomSection,
Section, FunctionSection, CodeSection, MemorySection, DataSection,
ImportSection, ExportSection, GlobalSection, TypeSection, ElementSection,
TableSection, CustomSection,
};
pub use self::import_entry::{ImportEntry, ResizableLimits, MemoryType, TableType, GlobalType, External};
pub use self::export_entry::{ExportEntry, Internal};
pub use self::global_entry::GlobalEntry;
pub use self::primitives::{
VarUint32, VarUint7, Uint8, VarUint1, VarInt7, Uint32, VarInt32, VarInt64,
Uint64, VarUint64, CountedList, CountedWriter, CountedListWriter,
VarUint32, VarUint7, Uint8, VarUint1, VarInt7, Uint32, VarInt32, VarInt64,
Uint64, VarUint64, CountedList, CountedWriter, CountedListWriter,
};
pub use self::types::{Type, ValueType, BlockType, FunctionType, TableElementType};
pub use self::ops::{Opcode, Opcodes, InitExpr};
@ -36,164 +36,164 @@ pub use self::func::{Func, FuncBody, Local};
pub use self::segment::{ElementSegment, DataSegment};
pub use self::index_map::IndexMap;
pub use self::name_section::{
NameMap, NameSection, ModuleNameSection, FunctionNameSection,
LocalNameSection,
NameMap, NameSection, ModuleNameSection, FunctionNameSection,
LocalNameSection,
};
/// Deserialization from serial i/o
pub trait Deserialize : Sized {
/// Serialization error produced by deserialization routine.
type Error;
/// Deserialize type from serial i/o
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>;
/// Serialization error produced by deserialization routine.
type Error;
/// Deserialize type from serial i/o
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>;
}
/// Serialization to serial i/o
pub trait Serialize {
/// Serialization error produced by serialization routine.
type Error;
/// Serialize type to serial i/o
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>;
/// Serialization error produced by serialization routine.
type Error;
/// Serialize type to serial i/o
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>;
}
/// Deserialization/serialization error
#[derive(Debug, Clone)]
pub enum Error {
/// Unexpected end of input
UnexpectedEof,
/// Invalid magic
InvalidMagic,
/// Unsupported version
UnsupportedVersion(u32),
/// Inconsistence between declared and actual length
InconsistentLength {
/// Expected length of the definition
expected: usize,
/// Actual length of the definition
actual: usize
},
/// Other static error
Other(&'static str),
/// Other allocated error
HeapOther(String),
/// Invalid/unknown value type declaration
UnknownValueType(i8),
/// Invalid/unknown table element type declaration
UnknownTableElementType(i8),
/// Non-utf8 string
NonUtf8String,
/// Unknown external kind code
UnknownExternalKind(u8),
/// Unknown internal kind code
UnknownInternalKind(u8),
/// Unknown opcode encountered
UnknownOpcode(u8),
/// Invalid VarUint1 value
InvalidVarUint1(u8),
/// Invalid VarInt32 value
InvalidVarInt32,
/// Invalid VarInt64 value
InvalidVarInt64,
/// Unexpected end of input
UnexpectedEof,
/// Invalid magic
InvalidMagic,
/// Unsupported version
UnsupportedVersion(u32),
/// Inconsistence between declared and actual length
InconsistentLength {
/// Expected length of the definition
expected: usize,
/// Actual length of the definition
actual: usize
},
/// Other static error
Other(&'static str),
/// Other allocated error
HeapOther(String),
/// Invalid/unknown value type declaration
UnknownValueType(i8),
/// Invalid/unknown table element type declaration
UnknownTableElementType(i8),
/// Non-utf8 string
NonUtf8String,
/// Unknown external kind code
UnknownExternalKind(u8),
/// Unknown internal kind code
UnknownInternalKind(u8),
/// Unknown opcode encountered
UnknownOpcode(u8),
/// Invalid VarUint1 value
InvalidVarUint1(u8),
/// Invalid VarInt32 value
InvalidVarInt32,
/// Invalid VarInt64 value
InvalidVarInt64,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::UnexpectedEof => write!(f, "Unexpected end of input"),
Error::InvalidMagic => write!(f, "Invalid magic number at start of file"),
Error::UnsupportedVersion(v) => write!(f, "Unsupported wasm version {}", v),
Error::InconsistentLength { expected, actual } => {
write!(f, "Expected length {}, found {}", expected, actual)
}
Error::Other(msg) => write!(f, "{}", msg),
Error::HeapOther(ref msg) => write!(f, "{}", msg),
Error::UnknownValueType(ty) => write!(f, "Invalid or unknown value type {}", ty),
Error::UnknownTableElementType(ty) => write!(f, "Unknown table element type {}", ty),
Error::NonUtf8String => write!(f, "Non-UTF-8 string"),
Error::UnknownExternalKind(kind) => write!(f, "Unknown external kind {}", kind),
Error::UnknownInternalKind(kind) => write!(f, "Unknown internal kind {}", kind),
Error::UnknownOpcode(opcode) => write!(f, "Unknown opcode {}", opcode),
Error::InvalidVarUint1(val) => write!(f, "Not an unsigned 1-bit integer: {}", val),
Error::InvalidVarInt32 => write!(f, "Not a signed 32-bit integer"),
Error::InvalidVarInt64 => write!(f, "Not a signed 64-bit integer"),
}
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::UnexpectedEof => write!(f, "Unexpected end of input"),
Error::InvalidMagic => write!(f, "Invalid magic number at start of file"),
Error::UnsupportedVersion(v) => write!(f, "Unsupported wasm version {}", v),
Error::InconsistentLength { expected, actual } => {
write!(f, "Expected length {}, found {}", expected, actual)
}
Error::Other(msg) => write!(f, "{}", msg),
Error::HeapOther(ref msg) => write!(f, "{}", msg),
Error::UnknownValueType(ty) => write!(f, "Invalid or unknown value type {}", ty),
Error::UnknownTableElementType(ty) => write!(f, "Unknown table element type {}", ty),
Error::NonUtf8String => write!(f, "Non-UTF-8 string"),
Error::UnknownExternalKind(kind) => write!(f, "Unknown external kind {}", kind),
Error::UnknownInternalKind(kind) => write!(f, "Unknown internal kind {}", kind),
Error::UnknownOpcode(opcode) => write!(f, "Unknown opcode {}", opcode),
Error::InvalidVarUint1(val) => write!(f, "Not an unsigned 1-bit integer: {}", val),
Error::InvalidVarInt32 => write!(f, "Not a signed 32-bit integer"),
Error::InvalidVarInt64 => write!(f, "Not a signed 64-bit integer"),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::UnexpectedEof => "Unexpected end of input",
Error::InvalidMagic => "Invalid magic number at start of file",
Error::UnsupportedVersion(_) => "Unsupported wasm version",
Error::InconsistentLength { .. } => "Inconsistent length",
Error::Other(msg) => msg,
Error::HeapOther(ref msg) => &msg[..],
Error::UnknownValueType(_) => "Invalid or unknown value type",
Error::UnknownTableElementType(_) => "Unknown table element type",
Error::NonUtf8String => "Non-UTF-8 string",
Error::UnknownExternalKind(_) => "Unknown external kind",
Error::UnknownInternalKind(_) => "Unknown internal kind",
Error::UnknownOpcode(_) => "Unknown opcode",
Error::InvalidVarUint1(_) => "Not an unsigned 1-bit integer",
Error::InvalidVarInt32 => "Not a signed 32-bit integer",
Error::InvalidVarInt64 => "Not a signed 64-bit integer",
}
}
fn description(&self) -> &str {
match *self {
Error::UnexpectedEof => "Unexpected end of input",
Error::InvalidMagic => "Invalid magic number at start of file",
Error::UnsupportedVersion(_) => "Unsupported wasm version",
Error::InconsistentLength { .. } => "Inconsistent length",
Error::Other(msg) => msg,
Error::HeapOther(ref msg) => &msg[..],
Error::UnknownValueType(_) => "Invalid or unknown value type",
Error::UnknownTableElementType(_) => "Unknown table element type",
Error::NonUtf8String => "Non-UTF-8 string",
Error::UnknownExternalKind(_) => "Unknown external kind",
Error::UnknownInternalKind(_) => "Unknown internal kind",
Error::UnknownOpcode(_) => "Unknown opcode",
Error::InvalidVarUint1(_) => "Not an unsigned 1-bit integer",
Error::InvalidVarInt32 => "Not a signed 32-bit integer",
Error::InvalidVarInt64 => "Not a signed 64-bit integer",
}
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
Error::HeapOther(format!("I/O Error: {}", err))
}
fn from(err: io::Error) -> Self {
Error::HeapOther(format!("I/O Error: {}", err))
}
}
/// Unparsed part of the module/section
pub struct Unparsed(pub Vec<u8>);
impl Deserialize for Unparsed {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let len = VarUint32::deserialize(reader)?.into();
let mut vec = vec![0u8; len];
reader.read_exact(&mut vec[..])?;
Ok(Unparsed(vec))
}
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let len = VarUint32::deserialize(reader)?.into();
let mut vec = vec![0u8; len];
reader.read_exact(&mut vec[..])?;
Ok(Unparsed(vec))
}
}
impl From<Unparsed> for Vec<u8> {
fn from(u: Unparsed) -> Vec<u8> {
u.0
}
fn from(u: Unparsed) -> Vec<u8> {
u.0
}
}
/// Deserialize module from file.
pub fn deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error> {
use std::io::Read;
use std::io::Read;
let mut contents = Vec::new();
::std::fs::File::open(p)?.read_to_end(&mut contents)?;
let mut contents = Vec::new();
::std::fs::File::open(p)?.read_to_end(&mut contents)?;
deserialize_buffer(&contents)
deserialize_buffer(&contents)
}
/// Deserialize deserializable type from buffer.
pub fn deserialize_buffer<T: Deserialize>(contents: &[u8]) -> Result<T, T::Error> {
let mut reader = io::Cursor::new(contents);
T::deserialize(&mut reader)
let mut reader = io::Cursor::new(contents);
T::deserialize(&mut reader)
}
/// Create buffer with serialized value.
pub fn serialize<T: Serialize>(val: T) -> Result<Vec<u8>, T::Error> {
let mut buf = Vec::new();
val.serialize(&mut buf)?;
Ok(buf)
let mut buf = Vec::new();
val.serialize(&mut buf)?;
Ok(buf)
}
/// Serialize module to the file
pub fn serialize_to_file<P: AsRef<::std::path::Path>>(p: P, module: Module) -> Result<(), Error>
{
let mut io = ::std::fs::File::create(p)?;
module.serialize(&mut io)
let mut io = ::std::fs::File::create(p)?;
module.serialize(&mut io)
}

View File

@ -3,8 +3,8 @@ use byteorder::{LittleEndian, ByteOrder};
use super::{Deserialize, Serialize, Error, Uint32, External};
use super::section::{
Section, CodeSection, TypeSection, ImportSection, ExportSection, FunctionSection,
GlobalSection, TableSection, ElementSection, DataSection, MemorySection
Section, CodeSection, TypeSection, ImportSection, ExportSection, FunctionSection,
GlobalSection, TableSection, ElementSection, DataSection, MemorySection
};
use super::name_section::NameSection;
@ -13,494 +13,494 @@ const WASM_MAGIC_NUMBER: [u8; 4] = [0x00, 0x61, 0x73, 0x6d];
/// WebAssembly module
#[derive(Debug, Clone)]
pub struct Module {
magic: u32,
version: u32,
sections: Vec<Section>,
magic: u32,
version: u32,
sections: Vec<Section>,
}
#[derive(Debug, Clone, Copy)]
/// Type of the import entry to count
pub enum ImportCountType {
/// Count functions
Function,
/// Count globals
Global,
/// Count functions
Function,
/// Count globals
Global,
}
impl Default for Module {
fn default() -> Self {
Module {
magic: LittleEndian::read_u32(&WASM_MAGIC_NUMBER),
version: 1,
sections: Vec::with_capacity(16),
}
}
fn default() -> Self {
Module {
magic: LittleEndian::read_u32(&WASM_MAGIC_NUMBER),
version: 1,
sections: Vec::with_capacity(16),
}
}
}
impl Module {
/// New module with sections
pub fn new(sections: Vec<Section>) -> Self {
Module {
sections: sections, ..Default::default()
}
}
/// New module with sections
pub fn new(sections: Vec<Section>) -> Self {
Module {
sections: sections, ..Default::default()
}
}
/// Destructure the module, yielding sections
pub fn into_sections(self) -> Vec<Section> {
self.sections
}
/// Destructure the module, yielding sections
pub fn into_sections(self) -> Vec<Section> {
self.sections
}
/// Version of module.
pub fn version(&self) -> u32 { self.version }
/// Version of module.
pub fn version(&self) -> u32 { self.version }
/// Sections list.
/// Each known section is optional and may appear at most once.
pub fn sections(&self) -> &[Section] {
&self.sections
}
/// Sections list.
/// Each known section is optional and may appear at most once.
pub fn sections(&self) -> &[Section] {
&self.sections
}
/// Sections list (mutable)
/// Each known section is optional and may appear at most once.
pub fn sections_mut(&mut self) -> &mut Vec<Section> {
&mut self.sections
}
/// Sections list (mutable)
/// Each known section is optional and may appear at most once.
pub fn sections_mut(&mut self) -> &mut Vec<Section> {
&mut self.sections
}
/// Code section, if any.
pub fn code_section(&self) -> Option<&CodeSection> {
for section in self.sections() {
if let &Section::Code(ref code_section) = section { return Some(code_section); }
}
None
}
/// Code section, if any.
pub fn code_section(&self) -> Option<&CodeSection> {
for section in self.sections() {
if let &Section::Code(ref code_section) = section { return Some(code_section); }
}
None
}
/// Types section, if any.
pub fn type_section(&self) -> Option<&TypeSection> {
for section in self.sections() {
if let &Section::Type(ref type_section) = section { return Some(type_section); }
}
None
}
/// Types section, if any.
pub fn type_section(&self) -> Option<&TypeSection> {
for section in self.sections() {
if let &Section::Type(ref type_section) = section { return Some(type_section); }
}
None
}
/// Imports section, if any.
pub fn import_section(&self) -> Option<&ImportSection> {
for section in self.sections() {
if let &Section::Import(ref import_section) = section { return Some(import_section); }
}
None
}
/// Imports section, if any.
pub fn import_section(&self) -> Option<&ImportSection> {
for section in self.sections() {
if let &Section::Import(ref import_section) = section { return Some(import_section); }
}
None
}
/// Globals section, if any.
pub fn global_section(&self) -> Option<&GlobalSection> {
for section in self.sections() {
if let &Section::Global(ref section) = section { return Some(section); }
}
None
}
/// Globals section, if any.
pub fn global_section(&self) -> Option<&GlobalSection> {
for section in self.sections() {
if let &Section::Global(ref section) = section { return Some(section); }
}
None
}
/// Exports section, if any.
pub fn export_section(&self) -> Option<&ExportSection> {
for section in self.sections() {
if let &Section::Export(ref export_section) = section { return Some(export_section); }
}
None
}
/// Exports section, if any.
pub fn export_section(&self) -> Option<&ExportSection> {
for section in self.sections() {
if let &Section::Export(ref export_section) = section { return Some(export_section); }
}
None
}
/// Table section, if any.
pub fn table_section(&self) -> Option<&TableSection> {
for section in self.sections() {
if let &Section::Table(ref section) = section { return Some(section); }
}
None
}
/// Table section, if any.
pub fn table_section(&self) -> Option<&TableSection> {
for section in self.sections() {
if let &Section::Table(ref section) = section { return Some(section); }
}
None
}
/// Data section, if any.
pub fn data_section(&self) -> Option<&DataSection> {
for section in self.sections() {
if let &Section::Data(ref section) = section { return Some(section); }
}
None
}
/// Data section, if any.
pub fn data_section(&self) -> Option<&DataSection> {
for section in self.sections() {
if let &Section::Data(ref section) = section { return Some(section); }
}
None
}
/// Element section, if any.
pub fn elements_section(&self) -> Option<&ElementSection> {
for section in self.sections() {
if let &Section::Element(ref section) = section { return Some(section); }
}
None
}
/// Element section, if any.
pub fn elements_section(&self) -> Option<&ElementSection> {
for section in self.sections() {
if let &Section::Element(ref section) = section { return Some(section); }
}
None
}
/// Memory section, if any.
pub fn memory_section(&self) -> Option<&MemorySection> {
for section in self.sections() {
if let &Section::Memory(ref section) = section { return Some(section); }
}
None
}
/// Memory section, if any.
pub fn memory_section(&self) -> Option<&MemorySection> {
for section in self.sections() {
if let &Section::Memory(ref section) = section { return Some(section); }
}
None
}
/// Functions signatures section, if any.
pub fn function_section(&self) -> Option<&FunctionSection> {
for section in self.sections() {
if let &Section::Function(ref sect) = section { return Some(sect); }
}
None
}
/// Functions signatures section, if any.
pub fn function_section(&self) -> Option<&FunctionSection> {
for section in self.sections() {
if let &Section::Function(ref sect) = section { return Some(sect); }
}
None
}
/// Start section, if any.
pub fn start_section(&self) -> Option<u32> {
for section in self.sections() {
if let &Section::Start(sect) = section { return Some(sect); }
}
None
}
/// Start section, if any.
pub fn start_section(&self) -> Option<u32> {
for section in self.sections() {
if let &Section::Start(sect) = section { return Some(sect); }
}
None
}
/// Try to parse name section in place
/// Corresponding custom section with proper header will convert to name sections
/// If some of them will fail to be decoded, Err variant is returned with the list of
/// (index, Error) tuples of failed sections.
pub fn parse_names(mut self) -> Result<Self, (Vec<(usize, Error)>, Self)> {
let mut parse_errors = Vec::new();
/// Try to parse name section in place
/// Corresponding custom section with proper header will convert to name sections
/// If some of them will fail to be decoded, Err variant is returned with the list of
/// (index, Error) tuples of failed sections.
pub fn parse_names(mut self) -> Result<Self, (Vec<(usize, Error)>, Self)> {
let mut parse_errors = Vec::new();
for i in 0..self.sections.len() {
if let Some(name_section) = {
let section = self.sections.get(i).expect("cannot fail because i in range 0..len; qed");
if let Section::Custom(ref custom) = *section {
if custom.name() == "name" {
let mut rdr = io::Cursor::new(custom.payload());
let name_section = match NameSection::deserialize(&self, &mut rdr) {
Ok(ns) => ns,
Err(e) => { parse_errors.push((i, e)); continue; }
};
Some(name_section)
} else {
None
}
} else { None }
} {
*self.sections.get_mut(i).expect("cannot fail because i in range 0..len; qed") = Section::Name(name_section);
}
}
for i in 0..self.sections.len() {
if let Some(name_section) = {
let section = self.sections.get(i).expect("cannot fail because i in range 0..len; qed");
if let Section::Custom(ref custom) = *section {
if custom.name() == "name" {
let mut rdr = io::Cursor::new(custom.payload());
let name_section = match NameSection::deserialize(&self, &mut rdr) {
Ok(ns) => ns,
Err(e) => { parse_errors.push((i, e)); continue; }
};
Some(name_section)
} else {
None
}
} else { None }
} {
*self.sections.get_mut(i).expect("cannot fail because i in range 0..len; qed") = Section::Name(name_section);
}
}
if parse_errors.len() > 0 {
Err((parse_errors, self))
} else {
Ok(self)
}
}
if parse_errors.len() > 0 {
Err((parse_errors, self))
} else {
Ok(self)
}
}
/// Count imports by provided type
pub fn import_count(&self, count_type: ImportCountType) -> usize {
self.import_section()
.map(|is|
is.entries().iter().filter(|import| match (count_type, *import.external()) {
(ImportCountType::Function, External::Function(_)) => true,
(ImportCountType::Global, External::Global(_)) => true,
_ => false
}).count())
.unwrap_or(0)
}
/// Count imports by provided type
pub fn import_count(&self, count_type: ImportCountType) -> usize {
self.import_section()
.map(|is|
is.entries().iter().filter(|import| match (count_type, *import.external()) {
(ImportCountType::Function, External::Function(_)) => true,
(ImportCountType::Global, External::Global(_)) => true,
_ => false
}).count())
.unwrap_or(0)
}
/// Query functions space
pub fn functions_space(&self) -> usize {
self.import_count(ImportCountType::Function) +
self.function_section().map(|fs| fs.entries().len()).unwrap_or(0)
}
/// Query functions space
pub fn functions_space(&self) -> usize {
self.import_count(ImportCountType::Function) +
self.function_section().map(|fs| fs.entries().len()).unwrap_or(0)
}
/// Query globals space
pub fn globals_space(&self) -> usize {
self.import_count(ImportCountType::Global) +
self.global_section().map(|gs| gs.entries().len()).unwrap_or(0)
}
/// Query globals space
pub fn globals_space(&self) -> usize {
self.import_count(ImportCountType::Global) +
self.global_section().map(|gs| gs.entries().len()).unwrap_or(0)
}
}
impl Deserialize for Module {
type Error = super::Error;
type Error = super::Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let mut sections = Vec::new();
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let mut sections = Vec::new();
let mut magic = [0u8; 4];
reader.read(&mut magic)?;
if magic != WASM_MAGIC_NUMBER {
return Err(Error::InvalidMagic);
}
let mut magic = [0u8; 4];
reader.read(&mut magic)?;
if magic != WASM_MAGIC_NUMBER {
return Err(Error::InvalidMagic);
}
let version: u32 = Uint32::deserialize(reader)?.into();
let version: u32 = Uint32::deserialize(reader)?.into();
if version != 1 {
return Err(Error::UnsupportedVersion(version));
}
if version != 1 {
return Err(Error::UnsupportedVersion(version));
}
loop {
match Section::deserialize(reader) {
Err(Error::UnexpectedEof) => { break; },
Err(e) => { return Err(e) },
Ok(section) => { sections.push(section); }
}
}
loop {
match Section::deserialize(reader) {
Err(Error::UnexpectedEof) => { break; },
Err(e) => { return Err(e) },
Ok(section) => { sections.push(section); }
}
}
Ok(Module {
magic: LittleEndian::read_u32(&magic),
version: version,
sections: sections,
})
}
Ok(Module {
magic: LittleEndian::read_u32(&magic),
version: version,
sections: sections,
})
}
}
impl Serialize for Module {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, w: &mut W) -> Result<(), Self::Error> {
Uint32::from(self.magic).serialize(w)?;
Uint32::from(self.version).serialize(w)?;
for section in self.sections.into_iter() {
section.serialize(w)?;
}
Ok(())
}
fn serialize<W: io::Write>(self, w: &mut W) -> Result<(), Self::Error> {
Uint32::from(self.magic).serialize(w)?;
Uint32::from(self.version).serialize(w)?;
for section in self.sections.into_iter() {
section.serialize(w)?;
}
Ok(())
}
}
#[derive(Debug, Copy, Clone)]
struct PeekSection<'a> {
cursor: usize,
region: &'a [u8],
cursor: usize,
region: &'a [u8],
}
impl<'a> io::Read for PeekSection<'a> {
fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
let available = ::std::cmp::min(buf.len(), self.region.len() - self.cursor);
if available < buf.len() {
return Err(::std::io::Error::from(::std::io::ErrorKind::UnexpectedEof));
}
fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
let available = ::std::cmp::min(buf.len(), self.region.len() - self.cursor);
if available < buf.len() {
return Err(::std::io::Error::from(::std::io::ErrorKind::UnexpectedEof));
}
let range = self.cursor..self.cursor + buf.len();
buf.copy_from_slice(&self.region[range]);
let range = self.cursor..self.cursor + buf.len();
buf.copy_from_slice(&self.region[range]);
self.cursor += available;
Ok(available)
}
self.cursor += available;
Ok(available)
}
}
/// Returns size of the module in the provided stream
pub fn peek_size(source: &[u8]) -> usize {
if source.len() < 9 {
return 0;
}
if source.len() < 9 {
return 0;
}
let mut cursor = 8;
loop {
let (new_cursor, section_id, section_len) = {
let mut peek_section = PeekSection { cursor: 0, region: &source[cursor..] };
let section_id: u8 = match super::VarUint7::deserialize(&mut peek_section) {
Ok(res) => res.into(),
Err(_) => { break; },
};
let section_len: u32 = match super::VarUint32::deserialize(&mut peek_section) {
Ok(res) => res.into(),
Err(_) => { break; },
};
let mut cursor = 8;
loop {
let (new_cursor, section_id, section_len) = {
let mut peek_section = PeekSection { cursor: 0, region: &source[cursor..] };
let section_id: u8 = match super::VarUint7::deserialize(&mut peek_section) {
Ok(res) => res.into(),
Err(_) => { break; },
};
let section_len: u32 = match super::VarUint32::deserialize(&mut peek_section) {
Ok(res) => res.into(),
Err(_) => { break; },
};
(peek_section.cursor, section_id, section_len)
};
(peek_section.cursor, section_id, section_len)
};
if section_id <= 11 && section_len > 0 {
let next_cursor = cursor + new_cursor + section_len as usize;
if next_cursor >= source.len() {
break;
}
cursor = next_cursor;
} else {
break;
}
}
if section_id <= 11 && section_len > 0 {
let next_cursor = cursor + new_cursor + section_len as usize;
if next_cursor >= source.len() {
break;
}
cursor = next_cursor;
} else {
break;
}
}
cursor
cursor
}
#[cfg(test)]
mod integration_tests {
use super::super::{deserialize_file, serialize, deserialize_buffer, Section};
use super::Module;
use super::super::{deserialize_file, serialize, deserialize_buffer, Section};
use super::Module;
#[test]
fn hello() {
let module = deserialize_file("./res/cases/v1/hello.wasm").expect("Should be deserialized");
#[test]
fn hello() {
let module = deserialize_file("./res/cases/v1/hello.wasm").expect("Should be deserialized");
assert_eq!(module.version(), 1);
assert_eq!(module.sections().len(), 8);
}
assert_eq!(module.version(), 1);
assert_eq!(module.sections().len(), 8);
}
#[test]
fn serde() {
let module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
let buf = serialize(module).expect("serialization to succeed");
#[test]
fn serde() {
let module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
let buf = serialize(module).expect("serialization to succeed");
let module_new: Module = deserialize_buffer(&buf).expect("deserialization to succeed");
let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
let module_new: Module = deserialize_buffer(&buf).expect("deserialization to succeed");
let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
assert_eq!(module_old.sections().len(), module_new.sections().len());
}
assert_eq!(module_old.sections().len(), module_new.sections().len());
}
#[test]
fn serde_type() {
let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
module.sections_mut().retain(|x| {
if let &Section::Type(_) = x { true } else { false }
});
#[test]
fn serde_type() {
let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
module.sections_mut().retain(|x| {
if let &Section::Type(_) = x { true } else { false }
});
let buf = serialize(module).expect("serialization to succeed");
let buf = serialize(module).expect("serialization to succeed");
let module_new: Module = deserialize_buffer(&buf).expect("deserialization to succeed");
let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
assert_eq!(
module_old.type_section().expect("type section exists").types().len(),
module_new.type_section().expect("type section exists").types().len(),
"There should be equal amount of types before and after serialization"
);
}
let module_new: Module = deserialize_buffer(&buf).expect("deserialization to succeed");
let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
assert_eq!(
module_old.type_section().expect("type section exists").types().len(),
module_new.type_section().expect("type section exists").types().len(),
"There should be equal amount of types before and after serialization"
);
}
#[test]
fn serde_import() {
let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
module.sections_mut().retain(|x| {
if let &Section::Import(_) = x { true } else { false }
});
#[test]
fn serde_import() {
let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
module.sections_mut().retain(|x| {
if let &Section::Import(_) = x { true } else { false }
});
let buf = serialize(module).expect("serialization to succeed");
let buf = serialize(module).expect("serialization to succeed");
let module_new: Module = deserialize_buffer(&buf).expect("deserialization to succeed");
let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
assert_eq!(
module_old.import_section().expect("import section exists").entries().len(),
module_new.import_section().expect("import section exists").entries().len(),
"There should be equal amount of import entries before and after serialization"
);
}
let module_new: Module = deserialize_buffer(&buf).expect("deserialization to succeed");
let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
assert_eq!(
module_old.import_section().expect("import section exists").entries().len(),
module_new.import_section().expect("import section exists").entries().len(),
"There should be equal amount of import entries before and after serialization"
);
}
#[test]
fn serde_code() {
let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
module.sections_mut().retain(|x| {
if let &Section::Code(_) = x { true } else { false }
});
#[test]
fn serde_code() {
let mut module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
module.sections_mut().retain(|x| {
if let &Section::Code(_) = x { true } else { false }
});
let buf = serialize(module).expect("serialization to succeed");
let buf = serialize(module).expect("serialization to succeed");
let module_new: Module = deserialize_buffer(&buf).expect("deserialization to succeed");
let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
assert_eq!(
module_old.code_section().expect("code section exists").bodies().len(),
module_new.code_section().expect("code section exists").bodies().len(),
"There should be equal amount of function bodies before and after serialization"
);
}
let module_new: Module = deserialize_buffer(&buf).expect("deserialization to succeed");
let module_old = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
assert_eq!(
module_old.code_section().expect("code section exists").bodies().len(),
module_new.code_section().expect("code section exists").bodies().len(),
"There should be equal amount of function bodies before and after serialization"
);
}
#[test]
fn const_() {
use super::super::Opcode::*;
#[test]
fn const_() {
use super::super::Opcode::*;
let module = deserialize_file("./res/cases/v1/const.wasm").expect("Should be deserialized");
let func = &module.code_section().expect("Code section to exist").bodies()[0];
assert_eq!(func.code().elements().len(), 20);
let module = deserialize_file("./res/cases/v1/const.wasm").expect("Should be deserialized");
let func = &module.code_section().expect("Code section to exist").bodies()[0];
assert_eq!(func.code().elements().len(), 20);
assert_eq!(I64Const(9223372036854775807), func.code().elements()[0]);
assert_eq!(I64Const(-9223372036854775808), func.code().elements()[1]);
assert_eq!(I64Const(-1152894205662152753), func.code().elements()[2]);
assert_eq!(I64Const(-8192), func.code().elements()[3]);
assert_eq!(I32Const(1024), func.code().elements()[4]);
assert_eq!(I32Const(2048), func.code().elements()[5]);
assert_eq!(I32Const(4096), func.code().elements()[6]);
assert_eq!(I32Const(8192), func.code().elements()[7]);
assert_eq!(I32Const(16384), func.code().elements()[8]);
assert_eq!(I32Const(32767), func.code().elements()[9]);
assert_eq!(I32Const(-1024), func.code().elements()[10]);
assert_eq!(I32Const(-2048), func.code().elements()[11]);
assert_eq!(I32Const(-4096), func.code().elements()[12]);
assert_eq!(I32Const(-8192), func.code().elements()[13]);
assert_eq!(I32Const(-16384), func.code().elements()[14]);
assert_eq!(I32Const(-32768), func.code().elements()[15]);
assert_eq!(I32Const(-2147483648), func.code().elements()[16]);
assert_eq!(I32Const(2147483647), func.code().elements()[17]);
}
assert_eq!(I64Const(9223372036854775807), func.code().elements()[0]);
assert_eq!(I64Const(-9223372036854775808), func.code().elements()[1]);
assert_eq!(I64Const(-1152894205662152753), func.code().elements()[2]);
assert_eq!(I64Const(-8192), func.code().elements()[3]);
assert_eq!(I32Const(1024), func.code().elements()[4]);
assert_eq!(I32Const(2048), func.code().elements()[5]);
assert_eq!(I32Const(4096), func.code().elements()[6]);
assert_eq!(I32Const(8192), func.code().elements()[7]);
assert_eq!(I32Const(16384), func.code().elements()[8]);
assert_eq!(I32Const(32767), func.code().elements()[9]);
assert_eq!(I32Const(-1024), func.code().elements()[10]);
assert_eq!(I32Const(-2048), func.code().elements()[11]);
assert_eq!(I32Const(-4096), func.code().elements()[12]);
assert_eq!(I32Const(-8192), func.code().elements()[13]);
assert_eq!(I32Const(-16384), func.code().elements()[14]);
assert_eq!(I32Const(-32768), func.code().elements()[15]);
assert_eq!(I32Const(-2147483648), func.code().elements()[16]);
assert_eq!(I32Const(2147483647), func.code().elements()[17]);
}
#[test]
fn store() {
use super::super::Opcode::*;
#[test]
fn store() {
use super::super::Opcode::*;
let module = deserialize_file("./res/cases/v1/offset.wasm").expect("Should be deserialized");
let func = &module.code_section().expect("Code section to exist").bodies()[0];
let module = deserialize_file("./res/cases/v1/offset.wasm").expect("Should be deserialized");
let func = &module.code_section().expect("Code section to exist").bodies()[0];
assert_eq!(func.code().elements().len(), 5);
assert_eq!(I64Store(0, 32), func.code().elements()[2]);
}
assert_eq!(func.code().elements().len(), 5);
assert_eq!(I64Store(0, 32), func.code().elements()[2]);
}
#[test]
fn peek() {
use super::peek_size;
#[test]
fn peek() {
use super::peek_size;
let module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
let mut buf = serialize(module).expect("serialization to succeed");
let module = deserialize_file("./res/cases/v1/test5.wasm").expect("Should be deserialized");
let mut buf = serialize(module).expect("serialization to succeed");
buf.extend_from_slice(&[1, 5, 12, 17]);
buf.extend_from_slice(&[1, 5, 12, 17]);
assert_eq!(peek_size(&buf), buf.len() - 4);
}
assert_eq!(peek_size(&buf), buf.len() - 4);
}
#[test]
fn peek_2() {
use super::peek_size;
#[test]
fn peek_2() {
use super::peek_size;
let module = deserialize_file("./res/cases/v1/offset.wasm").expect("Should be deserialized");
let mut buf = serialize(module).expect("serialization to succeed");
let module = deserialize_file("./res/cases/v1/offset.wasm").expect("Should be deserialized");
let mut buf = serialize(module).expect("serialization to succeed");
buf.extend_from_slice(&[0, 0, 0, 0, 0, 1, 5, 12, 17]);
buf.extend_from_slice(&[0, 0, 0, 0, 0, 1, 5, 12, 17]);
assert_eq!(peek_size(&buf), buf.len() - 9);
}
assert_eq!(peek_size(&buf), buf.len() - 9);
}
#[test]
fn module_default_round_trip() {
let module1 = Module::default();
let buf = serialize(module1).expect("Serialization should succeed");
#[test]
fn module_default_round_trip() {
let module1 = Module::default();
let buf = serialize(module1).expect("Serialization should succeed");
let module2: Module = deserialize_buffer(&buf).expect("Deserialization should succeed");
assert_eq!(Module::default().magic, module2.magic);
}
let module2: Module = deserialize_buffer(&buf).expect("Deserialization should succeed");
assert_eq!(Module::default().magic, module2.magic);
}
#[test]
fn names() {
use super::super::name_section::NameSection;
#[test]
fn names() {
use super::super::name_section::NameSection;
let module = deserialize_file("./res/cases/v1/with_names.wasm")
.expect("Should be deserialized")
.parse_names()
.expect("Names to be parsed");
let module = deserialize_file("./res/cases/v1/with_names.wasm")
.expect("Should be deserialized")
.parse_names()
.expect("Names to be parsed");
let mut found_section = false;
for section in module.sections() {
match *section {
Section::Name(ref name_section) => {
match *name_section {
NameSection::Function(ref function_name_section) => {
assert_eq!(
function_name_section.names().get(0).expect("Should be entry #0"),
"elog"
);
assert_eq!(
function_name_section.names().get(11).expect("Should be entry #0"),
"_ZN48_$LT$pwasm_token_contract..Endpoint$LT$T$GT$$GT$3new17hc3ace6dea0978cd9E"
);
let mut found_section = false;
for section in module.sections() {
match *section {
Section::Name(ref name_section) => {
match *name_section {
NameSection::Function(ref function_name_section) => {
assert_eq!(
function_name_section.names().get(0).expect("Should be entry #0"),
"elog"
);
assert_eq!(
function_name_section.names().get(11).expect("Should be entry #0"),
"_ZN48_$LT$pwasm_token_contract..Endpoint$LT$T$GT$$GT$3new17hc3ace6dea0978cd9E"
);
found_section = true;
},
_ => {},
}
},
_ => {},
}
}
found_section = true;
},
_ => {},
}
},
_ => {},
}
}
assert!(found_section, "Name section should be present in dedicated example");
}
assert!(found_section, "Name section should be present in dedicated example");
}
}

View File

@ -10,218 +10,218 @@ const NAME_TYPE_LOCAL: u8 = 2;
/// Debug name information.
#[derive(Clone, Debug, PartialEq)]
pub enum NameSection {
/// Module name section.
Module(ModuleNameSection),
/// Module name section.
Module(ModuleNameSection),
/// Function name section.
Function(FunctionNameSection),
/// Function name section.
Function(FunctionNameSection),
/// Local name section.
Local(LocalNameSection),
/// Local name section.
Local(LocalNameSection),
/// Name section is unparsed.
Unparsed {
/// The numeric identifier for this name section type.
name_type: u8,
/// The contents of this name section, unparsed.
name_payload: Vec<u8>,
},
/// Name section is unparsed.
Unparsed {
/// The numeric identifier for this name section type.
name_type: u8,
/// The contents of this name section, unparsed.
name_payload: Vec<u8>,
},
}
impl NameSection {
/// Deserialize a name section.
pub fn deserialize<R: Read>(
module: &Module,
rdr: &mut R,
) -> Result<NameSection, Error> {
let name_type: u8 = VarUint7::deserialize(rdr)?.into();
let name_payload_len: u32 = VarUint32::deserialize(rdr)?.into();
let name_section = match name_type {
NAME_TYPE_MODULE => NameSection::Module(ModuleNameSection::deserialize(rdr)?),
NAME_TYPE_FUNCTION => NameSection::Function(FunctionNameSection::deserialize(module, rdr)?),
NAME_TYPE_LOCAL => NameSection::Local(LocalNameSection::deserialize(module, rdr)?),
_ => {
let mut name_payload = vec![0u8; name_payload_len as usize];
rdr.read_exact(&mut name_payload)?;
NameSection::Unparsed {
name_type,
name_payload,
}
}
};
Ok(name_section)
}
/// Deserialize a name section.
pub fn deserialize<R: Read>(
module: &Module,
rdr: &mut R,
) -> Result<NameSection, Error> {
let name_type: u8 = VarUint7::deserialize(rdr)?.into();
let name_payload_len: u32 = VarUint32::deserialize(rdr)?.into();
let name_section = match name_type {
NAME_TYPE_MODULE => NameSection::Module(ModuleNameSection::deserialize(rdr)?),
NAME_TYPE_FUNCTION => NameSection::Function(FunctionNameSection::deserialize(module, rdr)?),
NAME_TYPE_LOCAL => NameSection::Local(LocalNameSection::deserialize(module, rdr)?),
_ => {
let mut name_payload = vec![0u8; name_payload_len as usize];
rdr.read_exact(&mut name_payload)?;
NameSection::Unparsed {
name_type,
name_payload,
}
}
};
Ok(name_section)
}
}
impl Serialize for NameSection {
type Error = Error;
type Error = Error;
fn serialize<W: Write>(self, wtr: &mut W) -> Result<(), Error> {
let (name_type, name_payload) = match self {
NameSection::Module(mod_name) => {
let mut buffer = vec![];
mod_name.serialize(&mut buffer)?;
(NAME_TYPE_MODULE, buffer)
}
NameSection::Function(fn_names) => {
let mut buffer = vec![];
fn_names.serialize(&mut buffer)?;
(NAME_TYPE_FUNCTION, buffer)
}
NameSection::Local(local_names) => {
let mut buffer = vec![];
local_names.serialize(&mut buffer)?;
(NAME_TYPE_LOCAL, buffer)
}
NameSection::Unparsed {
name_type,
name_payload,
} => (name_type, name_payload),
};
VarUint7::from(name_type).serialize(wtr)?;
VarUint32::from(name_payload.len()).serialize(wtr)?;
wtr.write_all(&name_payload)?;
Ok(())
}
fn serialize<W: Write>(self, wtr: &mut W) -> Result<(), Error> {
let (name_type, name_payload) = match self {
NameSection::Module(mod_name) => {
let mut buffer = vec![];
mod_name.serialize(&mut buffer)?;
(NAME_TYPE_MODULE, buffer)
}
NameSection::Function(fn_names) => {
let mut buffer = vec![];
fn_names.serialize(&mut buffer)?;
(NAME_TYPE_FUNCTION, buffer)
}
NameSection::Local(local_names) => {
let mut buffer = vec![];
local_names.serialize(&mut buffer)?;
(NAME_TYPE_LOCAL, buffer)
}
NameSection::Unparsed {
name_type,
name_payload,
} => (name_type, name_payload),
};
VarUint7::from(name_type).serialize(wtr)?;
VarUint32::from(name_payload.len()).serialize(wtr)?;
wtr.write_all(&name_payload)?;
Ok(())
}
}
/// The name of this module.
#[derive(Clone, Debug, PartialEq)]
pub struct ModuleNameSection {
name: String,
name: String,
}
impl ModuleNameSection {
/// Create a new module name section with the specified name.
pub fn new<S: Into<String>>(name: S) -> ModuleNameSection {
ModuleNameSection { name: name.into() }
}
/// Create a new module name section with the specified name.
pub fn new<S: Into<String>>(name: S) -> ModuleNameSection {
ModuleNameSection { name: name.into() }
}
/// The name of this module.
pub fn name(&self) -> &str {
&self.name
}
/// The name of this module.
pub fn name(&self) -> &str {
&self.name
}
/// The name of this module (mutable).
pub fn name_mut(&mut self) -> &mut String {
&mut self.name
}
/// The name of this module (mutable).
pub fn name_mut(&mut self) -> &mut String {
&mut self.name
}
}
impl Serialize for ModuleNameSection {
type Error = Error;
type Error = Error;
fn serialize<W: Write>(self, wtr: &mut W) -> Result<(), Error> {
self.name.serialize(wtr)
}
fn serialize<W: Write>(self, wtr: &mut W) -> Result<(), Error> {
self.name.serialize(wtr)
}
}
impl Deserialize for ModuleNameSection {
type Error = Error;
type Error = Error;
fn deserialize<R: Read>(rdr: &mut R) -> Result<ModuleNameSection, Error> {
let name = String::deserialize(rdr)?;
Ok(ModuleNameSection { name })
}
fn deserialize<R: Read>(rdr: &mut R) -> Result<ModuleNameSection, Error> {
let name = String::deserialize(rdr)?;
Ok(ModuleNameSection { name })
}
}
/// The names of the functions in this module.
#[derive(Clone, Debug, Default, PartialEq)]
pub struct FunctionNameSection {
names: NameMap,
names: NameMap,
}
impl FunctionNameSection {
/// A map from function indices to names.
pub fn names(&self) -> &NameMap {
&self.names
}
/// A map from function indices to names.
pub fn names(&self) -> &NameMap {
&self.names
}
/// A map from function indices to names (mutable).
pub fn names_mut(&mut self) -> &mut NameMap {
&mut self.names
}
/// A map from function indices to names (mutable).
pub fn names_mut(&mut self) -> &mut NameMap {
&mut self.names
}
/// Deserialize names, making sure that all names correspond to functions.
pub fn deserialize<R: Read>(
module: &Module,
rdr: &mut R,
) -> Result<FunctionNameSection, Error> {
let names = IndexMap::deserialize(module.functions_space(), rdr)?;
Ok(FunctionNameSection { names })
}
/// Deserialize names, making sure that all names correspond to functions.
pub fn deserialize<R: Read>(
module: &Module,
rdr: &mut R,
) -> Result<FunctionNameSection, Error> {
let names = IndexMap::deserialize(module.functions_space(), rdr)?;
Ok(FunctionNameSection { names })
}
}
impl Serialize for FunctionNameSection {
type Error = Error;
type Error = Error;
fn serialize<W: Write>(self, wtr: &mut W) -> Result<(), Error> {
self.names.serialize(wtr)
}
fn serialize<W: Write>(self, wtr: &mut W) -> Result<(), Error> {
self.names.serialize(wtr)
}
}
/// The names of the local variables in this module's functions.
#[derive(Clone, Debug, Default, PartialEq)]
pub struct LocalNameSection {
local_names: IndexMap<NameMap>,
local_names: IndexMap<NameMap>,
}
impl LocalNameSection {
/// A map from function indices to a map from variables indices to names.
pub fn local_names(&self) -> &IndexMap<NameMap> {
&self.local_names
}
/// A map from function indices to a map from variables indices to names.
pub fn local_names(&self) -> &IndexMap<NameMap> {
&self.local_names
}
/// A map from function indices to a map from variables indices to names
/// (mutable).
pub fn local_names_mut(&mut self) -> &mut IndexMap<NameMap> {
&mut self.local_names
}
/// A map from function indices to a map from variables indices to names
/// (mutable).
pub fn local_names_mut(&mut self) -> &mut IndexMap<NameMap> {
&mut self.local_names
}
/// Deserialize names, making sure that all names correspond to local
/// variables.
pub fn deserialize<R: Read>(
module: &Module,
rdr: &mut R,
) -> Result<LocalNameSection, Error> {
let funcs = module.function_section().ok_or_else(|| {
Error::Other("cannot deserialize local names without a function section")
})?;
let max_entry_space = funcs.entries().len();
/// Deserialize names, making sure that all names correspond to local
/// variables.
pub fn deserialize<R: Read>(
module: &Module,
rdr: &mut R,
) -> Result<LocalNameSection, Error> {
let funcs = module.function_section().ok_or_else(|| {
Error::Other("cannot deserialize local names without a function section")
})?;
let max_entry_space = funcs.entries().len();
let max_signature_args = module
.type_section()
.map(|ts|
ts.types()
.iter()
.map(|x| { let Type::Function(ref func) = *x; func.params().len() })
.max()
.unwrap_or(0))
.unwrap_or(0);
let max_signature_args = module
.type_section()
.map(|ts|
ts.types()
.iter()
.map(|x| { let Type::Function(ref func) = *x; func.params().len() })
.max()
.unwrap_or(0))
.unwrap_or(0);
let max_locals = module
.code_section()
.map(|cs| cs.bodies().iter().map(|f| f.locals().len()).max().unwrap_or(0))
.unwrap_or(0);
let max_locals = module
.code_section()
.map(|cs| cs.bodies().iter().map(|f| f.locals().len()).max().unwrap_or(0))
.unwrap_or(0);
let max_space = max_signature_args + max_locals;
let max_space = max_signature_args + max_locals;
let deserialize_locals = |_: u32, rdr: &mut R| IndexMap::deserialize(max_space, rdr);
let deserialize_locals = |_: u32, rdr: &mut R| IndexMap::deserialize(max_space, rdr);
let local_names = IndexMap::deserialize_with(
max_entry_space,
&deserialize_locals,
rdr,
)?;
Ok(LocalNameSection { local_names })
}}
let local_names = IndexMap::deserialize_with(
max_entry_space,
&deserialize_locals,
rdr,
)?;
Ok(LocalNameSection { local_names })
}}
impl Serialize for LocalNameSection {
type Error = Error;
type Error = Error;
fn serialize<W: Write>(self, wtr: &mut W) -> Result<(), Error> {
self.local_names.serialize(wtr)
}
fn serialize<W: Write>(self, wtr: &mut W) -> Result<(), Error> {
self.local_names.serialize(wtr)
}
}
/// A map from indices to names.
@ -229,48 +229,48 @@ pub type NameMap = IndexMap<String>;
#[cfg(test)]
mod tests {
use super::*;
use super::*;
// A helper funtion for the tests. Serialize a section, deserialize it,
// and make sure it matches the original.
fn serialize_test(original: NameSection) -> Vec<u8> {
let mut buffer = vec![];
original
.serialize(&mut buffer)
.expect("serialize error");
buffer
}
// A helper funtion for the tests. Serialize a section, deserialize it,
// and make sure it matches the original.
fn serialize_test(original: NameSection) -> Vec<u8> {
let mut buffer = vec![];
original
.serialize(&mut buffer)
.expect("serialize error");
buffer
}
#[test]
fn serialize_module_name() {
let original = NameSection::Module(ModuleNameSection::new("my_mod"));
serialize_test(original.clone());
}
#[test]
fn serialize_module_name() {
let original = NameSection::Module(ModuleNameSection::new("my_mod"));
serialize_test(original.clone());
}
#[test]
fn serialize_function_names() {
let mut sect = FunctionNameSection::default();
sect.names_mut().insert(0, "hello_world".to_string());
serialize_test(NameSection::Function(sect));
}
#[test]
fn serialize_function_names() {
let mut sect = FunctionNameSection::default();
sect.names_mut().insert(0, "hello_world".to_string());
serialize_test(NameSection::Function(sect));
}
#[test]
fn serialize_local_names() {
let mut sect = LocalNameSection::default();
let mut locals = NameMap::default();
locals.insert(0, "msg".to_string());
sect.local_names_mut().insert(0, locals);
serialize_test(NameSection::Local(sect));
}
#[test]
fn serialize_local_names() {
let mut sect = LocalNameSection::default();
let mut locals = NameMap::default();
locals.insert(0, "msg".to_string());
sect.local_names_mut().insert(0, locals);
serialize_test(NameSection::Local(sect));
}
#[test]
fn serialize_and_deserialize_unparsed() {
let original = NameSection::Unparsed {
// A made-up name section type which is unlikely to be allocated
// soon, in order to allow us to test `Unparsed`.
name_type: 120,
name_payload: vec![0u8, 1, 2],
};
serialize_test(original.clone());
}
#[test]
fn serialize_and_deserialize_unparsed() {
let original = NameSection::Unparsed {
// A made-up name section type which is unlikely to be allocated
// soon, in order to allow us to test `Unparsed`.
name_type: 120,
name_payload: vec![0u8, 1, 2],
};
serialize_test(original.clone());
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,132 +4,132 @@ use super::{Deserialize, Serialize, Error, VarUint32, CountedList, InitExpr, Cou
/// Entry in the element section.
#[derive(Debug, Clone)]
pub struct ElementSegment {
index: u32,
offset: InitExpr,
members: Vec<u32>,
index: u32,
offset: InitExpr,
members: Vec<u32>,
}
impl ElementSegment {
/// New element segment.
pub fn new(index: u32, offset: InitExpr, members: Vec<u32>) -> Self {
ElementSegment { index: index, offset: offset, members: members }
}
/// New element segment.
pub fn new(index: u32, offset: InitExpr, members: Vec<u32>) -> Self {
ElementSegment { index: index, offset: offset, members: members }
}
/// Sequence of function indices.
pub fn members(&self) -> &[u32] { &self.members }
/// Sequence of function indices.
pub fn members(&self) -> &[u32] { &self.members }
/// Sequence of function indices (mutable)
pub fn members_mut(&mut self) -> &mut Vec<u32> { &mut self.members }
/// Sequence of function indices (mutable)
pub fn members_mut(&mut self) -> &mut Vec<u32> { &mut self.members }
/// Table index (currently valid only value of `0`)
pub fn index(&self) -> u32 { self.index }
/// Table index (currently valid only value of `0`)
pub fn index(&self) -> u32 { self.index }
/// An i32 initializer expression that computes the offset at which to place the elements.
pub fn offset(&self) -> &InitExpr { &self.offset }
/// An i32 initializer expression that computes the offset at which to place the elements.
pub fn offset(&self) -> &InitExpr { &self.offset }
/// An i32 initializer expression that computes the offset at which to place the elements (mutable)
pub fn offset_mut(&mut self) -> &mut InitExpr { &mut self.offset }
/// An i32 initializer expression that computes the offset at which to place the elements (mutable)
pub fn offset_mut(&mut self) -> &mut InitExpr { &mut self.offset }
}
impl Deserialize for ElementSegment {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let index = VarUint32::deserialize(reader)?;
let offset = InitExpr::deserialize(reader)?;
let funcs: Vec<u32> = CountedList::<VarUint32>::deserialize(reader)?
.into_inner()
.into_iter()
.map(Into::into)
.collect();
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let index = VarUint32::deserialize(reader)?;
let offset = InitExpr::deserialize(reader)?;
let funcs: Vec<u32> = CountedList::<VarUint32>::deserialize(reader)?
.into_inner()
.into_iter()
.map(Into::into)
.collect();
Ok(ElementSegment {
index: index.into(),
offset: offset,
members: funcs,
})
}
Ok(ElementSegment {
index: index.into(),
offset: offset,
members: funcs,
})
}
}
impl Serialize for ElementSegment {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
VarUint32::from(self.index).serialize(writer)?;
self.offset.serialize(writer)?;
let data = self.members;
let counted_list = CountedListWriter::<VarUint32, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(writer)?;
Ok(())
}
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
VarUint32::from(self.index).serialize(writer)?;
self.offset.serialize(writer)?;
let data = self.members;
let counted_list = CountedListWriter::<VarUint32, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(writer)?;
Ok(())
}
}
/// Data segment definition.
#[derive(Clone, Debug)]
pub struct DataSegment {
index: u32,
offset: InitExpr,
value: Vec<u8>,
index: u32,
offset: InitExpr,
value: Vec<u8>,
}
impl DataSegment {
/// New data segments.
pub fn new(index: u32, offset: InitExpr, value: Vec<u8>) -> Self {
DataSegment {
index: index,
offset: offset,
value: value,
}
}
/// New data segments.
pub fn new(index: u32, offset: InitExpr, value: Vec<u8>) -> Self {
DataSegment {
index: index,
offset: offset,
value: value,
}
}
/// Linear memory index (currently the only valid value is `0`).
pub fn index(&self) -> u32 { self.index }
/// Linear memory index (currently the only valid value is `0`).
pub fn index(&self) -> u32 { self.index }
/// An i32 initializer expression that computes the offset at which to place the data.
pub fn offset(&self) -> &InitExpr { &self.offset }
/// An i32 initializer expression that computes the offset at which to place the data.
pub fn offset(&self) -> &InitExpr { &self.offset }
/// An i32 initializer expression that computes the offset at which to place the data (mutable)
pub fn offset_mut(&mut self) -> &mut InitExpr { &mut self.offset }
/// An i32 initializer expression that computes the offset at which to place the data (mutable)
pub fn offset_mut(&mut self) -> &mut InitExpr { &mut self.offset }
/// Initial value of the data segment.
pub fn value(&self) -> &[u8] { &self.value }
/// Initial value of the data segment.
pub fn value(&self) -> &[u8] { &self.value }
/// Initial value of the data segment (mutable).
pub fn value_mut(&mut self) -> &mut Vec<u8> { &mut self.value }
/// Initial value of the data segment (mutable).
pub fn value_mut(&mut self) -> &mut Vec<u8> { &mut self.value }
}
impl Deserialize for DataSegment {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let index = VarUint32::deserialize(reader)?;
let offset = InitExpr::deserialize(reader)?;
let value_len = VarUint32::deserialize(reader)?;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let index = VarUint32::deserialize(reader)?;
let offset = InitExpr::deserialize(reader)?;
let value_len = VarUint32::deserialize(reader)?;
let mut value_buf = vec![0u8; value_len.into()];
reader.read_exact(&mut value_buf[..])?;
let mut value_buf = vec![0u8; value_len.into()];
reader.read_exact(&mut value_buf[..])?;
Ok(DataSegment {
index: index.into(),
offset: offset,
value: value_buf,
})
}
Ok(DataSegment {
index: index.into(),
offset: offset,
value: value_buf,
})
}
}
impl Serialize for DataSegment {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
VarUint32::from(self.index).serialize(writer)?;
self.offset.serialize(writer)?;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
VarUint32::from(self.index).serialize(writer)?;
self.offset.serialize(writer)?;
let value = self.value;
VarUint32::from(value.len()).serialize(writer)?;
writer.write_all(&value[..])?;
Ok(())
}
let value = self.value;
VarUint32::from(value.len()).serialize(writer)?;
writer.write_all(&value[..])?;
Ok(())
}
}

View File

@ -1,245 +1,245 @@
use std::{io, fmt};
use super::{
Deserialize, Serialize, Error, VarUint7, VarInt7, VarUint1, CountedList,
CountedListWriter
Deserialize, Serialize, Error, VarUint7, VarInt7, VarUint1, CountedList,
CountedListWriter
};
/// Type definition in types section. Currently can be only of the function type.
#[derive(Debug, PartialEq, Clone)]
pub enum Type {
/// Function type.
Function(FunctionType),
/// Function type.
Function(FunctionType),
}
impl Deserialize for Type {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(Type::Function(FunctionType::deserialize(reader)?))
}
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(Type::Function(FunctionType::deserialize(reader)?))
}
}
impl Serialize for Type {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
match self {
Type::Function(fn_type) => fn_type.serialize(writer)
}
}
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
match self {
Type::Function(fn_type) => fn_type.serialize(writer)
}
}
}
/// Value type.
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ValueType {
/// 32-bit signed integer
I32,
/// 64-bit signed integer
I64,
/// 32-bit float
F32,
/// 64-bit float
F64,
/// 32-bit signed integer
I32,
/// 64-bit signed integer
I64,
/// 32-bit float
F32,
/// 64-bit float
F64,
}
impl Deserialize for ValueType {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let val = VarInt7::deserialize(reader)?;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let val = VarInt7::deserialize(reader)?;
match val.into() {
-0x01 => Ok(ValueType::I32),
-0x02 => Ok(ValueType::I64),
-0x03 => Ok(ValueType::F32),
-0x04 => Ok(ValueType::F64),
_ => Err(Error::UnknownValueType(val.into())),
}
}
match val.into() {
-0x01 => Ok(ValueType::I32),
-0x02 => Ok(ValueType::I64),
-0x03 => Ok(ValueType::F32),
-0x04 => Ok(ValueType::F64),
_ => Err(Error::UnknownValueType(val.into())),
}
}
}
impl Serialize for ValueType {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let val: VarInt7 = match self {
ValueType::I32 => -0x01,
ValueType::I64 => -0x02,
ValueType::F32 => -0x03,
ValueType::F64 => -0x04,
}.into();
val.serialize(writer)?;
Ok(())
}
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let val: VarInt7 = match self {
ValueType::I32 => -0x01,
ValueType::I64 => -0x02,
ValueType::F32 => -0x03,
ValueType::F64 => -0x04,
}.into();
val.serialize(writer)?;
Ok(())
}
}
impl fmt::Display for ValueType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ValueType::I32 => write!(f, "i32"),
ValueType::I64 => write!(f, "i64"),
ValueType::F32 => write!(f, "f32"),
ValueType::F64 => write!(f, "f64"),
}
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ValueType::I32 => write!(f, "i32"),
ValueType::I64 => write!(f, "i64"),
ValueType::F32 => write!(f, "f32"),
ValueType::F64 => write!(f, "f64"),
}
}
}
/// Block type which is basically `ValueType` + NoResult (to define blocks that have no return type)
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum BlockType {
/// Value-type specified block type
Value(ValueType),
/// No specified block type
NoResult,
/// Value-type specified block type
Value(ValueType),
/// No specified block type
NoResult,
}
impl Deserialize for BlockType {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let val = VarInt7::deserialize(reader)?;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let val = VarInt7::deserialize(reader)?;
match val.into() {
-0x01 => Ok(BlockType::Value(ValueType::I32)),
-0x02 => Ok(BlockType::Value(ValueType::I64)),
-0x03 => Ok(BlockType::Value(ValueType::F32)),
-0x04 => Ok(BlockType::Value(ValueType::F64)),
-0x40 => Ok(BlockType::NoResult),
_ => Err(Error::UnknownValueType(val.into())),
}
}
match val.into() {
-0x01 => Ok(BlockType::Value(ValueType::I32)),
-0x02 => Ok(BlockType::Value(ValueType::I64)),
-0x03 => Ok(BlockType::Value(ValueType::F32)),
-0x04 => Ok(BlockType::Value(ValueType::F64)),
-0x40 => Ok(BlockType::NoResult),
_ => Err(Error::UnknownValueType(val.into())),
}
}
}
impl Serialize for BlockType {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let val: VarInt7 = match self {
BlockType::NoResult => -0x40i8,
BlockType::Value(ValueType::I32) => -0x01,
BlockType::Value(ValueType::I64) => -0x02,
BlockType::Value(ValueType::F32) => -0x03,
BlockType::Value(ValueType::F64) => -0x04,
}.into();
val.serialize(writer)?;
Ok(())
}
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let val: VarInt7 = match self {
BlockType::NoResult => -0x40i8,
BlockType::Value(ValueType::I32) => -0x01,
BlockType::Value(ValueType::I64) => -0x02,
BlockType::Value(ValueType::F32) => -0x03,
BlockType::Value(ValueType::F64) => -0x04,
}.into();
val.serialize(writer)?;
Ok(())
}
}
/// Function signature type.
#[derive(Debug, Clone, PartialEq)]
pub struct FunctionType {
form: u8,
params: Vec<ValueType>,
return_type: Option<ValueType>,
form: u8,
params: Vec<ValueType>,
return_type: Option<ValueType>,
}
impl Default for FunctionType {
fn default() -> Self {
FunctionType {
form: 0x60,
params: Vec::new(),
return_type: None,
}
}
fn default() -> Self {
FunctionType {
form: 0x60,
params: Vec::new(),
return_type: None,
}
}
}
impl FunctionType {
/// New function type given the signature in-params(`params`) and return type (`return_type`)
pub fn new(params: Vec<ValueType>, return_type: Option<ValueType>) -> Self {
FunctionType {
params: params,
return_type: return_type,
..Default::default()
}
}
/// Function form (currently only valid value is `0x60`)
pub fn form(&self) -> u8 { self.form }
/// Parameters in the function signature.
pub fn params(&self) -> &[ValueType] { &self.params }
/// Mutable parameters in the function signature.
pub fn params_mut(&mut self) -> &mut Vec<ValueType> { &mut self.params }
/// Return type in the function signature, if any.
pub fn return_type(&self) -> Option<ValueType> { self.return_type }
/// Mutable type in the function signature, if any.
pub fn return_type_mut(&mut self) -> &mut Option<ValueType> { &mut self.return_type }
/// New function type given the signature in-params(`params`) and return type (`return_type`)
pub fn new(params: Vec<ValueType>, return_type: Option<ValueType>) -> Self {
FunctionType {
params: params,
return_type: return_type,
..Default::default()
}
}
/// Function form (currently only valid value is `0x60`)
pub fn form(&self) -> u8 { self.form }
/// Parameters in the function signature.
pub fn params(&self) -> &[ValueType] { &self.params }
/// Mutable parameters in the function signature.
pub fn params_mut(&mut self) -> &mut Vec<ValueType> { &mut self.params }
/// Return type in the function signature, if any.
pub fn return_type(&self) -> Option<ValueType> { self.return_type }
/// Mutable type in the function signature, if any.
pub fn return_type_mut(&mut self) -> &mut Option<ValueType> { &mut self.return_type }
}
impl Deserialize for FunctionType {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let form: u8 = VarUint7::deserialize(reader)?.into();
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let form: u8 = VarUint7::deserialize(reader)?.into();
let params: Vec<ValueType> = CountedList::deserialize(reader)?.into_inner();
let params: Vec<ValueType> = CountedList::deserialize(reader)?.into_inner();
let has_return_type = VarUint1::deserialize(reader)?;
let return_type = if has_return_type.into() {
Some(ValueType::deserialize(reader)?)
} else {
None
};
let has_return_type = VarUint1::deserialize(reader)?;
let return_type = if has_return_type.into() {
Some(ValueType::deserialize(reader)?)
} else {
None
};
Ok(FunctionType {
form: form,
params: params,
return_type: return_type,
})
}
Ok(FunctionType {
form: form,
params: params,
return_type: return_type,
})
}
}
impl Serialize for FunctionType {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
VarUint7::from(self.form).serialize(writer)?;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
VarUint7::from(self.form).serialize(writer)?;
let data = self.params;
let counted_list = CountedListWriter::<ValueType, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(writer)?;
let data = self.params;
let counted_list = CountedListWriter::<ValueType, _>(
data.len(),
data.into_iter().map(Into::into),
);
counted_list.serialize(writer)?;
if let Some(return_type) = self.return_type {
VarUint1::from(true).serialize(writer)?;
return_type.serialize(writer)?;
} else {
VarUint1::from(false).serialize(writer)?;
}
if let Some(return_type) = self.return_type {
VarUint1::from(true).serialize(writer)?;
return_type.serialize(writer)?;
} else {
VarUint1::from(false).serialize(writer)?;
}
Ok(())
}
Ok(())
}
}
/// Table element type.
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum TableElementType {
/// A reference to a function with any signature.
AnyFunc,
/// A reference to a function with any signature.
AnyFunc,
}
impl Deserialize for TableElementType {
type Error = Error;
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let val = VarInt7::deserialize(reader)?;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let val = VarInt7::deserialize(reader)?;
match val.into() {
-0x10 => Ok(TableElementType::AnyFunc),
_ => Err(Error::UnknownTableElementType(val.into())),
}
}
match val.into() {
-0x10 => Ok(TableElementType::AnyFunc),
_ => Err(Error::UnknownTableElementType(val.into())),
}
}
}
impl Serialize for TableElementType {
type Error = Error;
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let val: VarInt7 = match self {
TableElementType::AnyFunc => 0x70,
}.into();
val.serialize(writer)?;
Ok(())
}
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let val: VarInt7 = match self {
TableElementType::AnyFunc => 0x70,
}.into();
val.serialize(writer)?;
Ok(())
}
}

View File

@ -14,18 +14,18 @@ mod validation;
mod common;
pub use elements::{
Error as SerializationError,
deserialize_buffer,
deserialize_file,
serialize,
serialize_to_file,
peek_size,
Error as SerializationError,
deserialize_buffer,
deserialize_file,
serialize,
serialize_to_file,
peek_size,
};
#[allow(deprecated)]
pub use interpreter::{
ProgramInstance,
ModuleInstance,
ModuleInstanceInterface,
RuntimeValue,
ProgramInstance,
ModuleInstance,
ModuleInstanceInterface,
RuntimeValue,
};