//! A WebAssembly encoder. //! //! The main builder is the [`Module`]. You can build a section with a //! section-specific builder, like [`TypeSection`] or [`ImportSection`], and //! then add it to the module with [`Module::section`]. When you are finished //! building the module, call either [`Module::as_slice`] or [`Module::finish`] //! to get the encoded bytes. The former gives a shared reference to the //! underlying bytes as a slice, while the latter gives you ownership of them as //! a vector. //! //! # Example //! //! If we wanted to build this module: //! //! ```wasm //! (module //! (type (func (param i32 i32) (result i32))) //! (func (type 0) //! local.get 0 //! local.get 1 //! i32.add) //! (export "f" (func 0))) //! ``` //! //! then we would do this: //! //! ``` //! use wasm_encoder::{ //! CodeSection, ExportKind, ExportSection, Function, FunctionSection, Instruction, //! Module, TypeSection, ValType, //! }; //! //! let mut module = Module::new(); //! //! // Encode the type section. //! let mut types = TypeSection::new(); //! let params = vec![ValType::I32, ValType::I32]; //! let results = vec![ValType::I32]; //! types.function(params, results); //! module.section(&types); //! //! // Encode the function section. //! let mut functions = FunctionSection::new(); //! let type_index = 0; //! functions.function(type_index); //! module.section(&functions); //! //! // Encode the export section. //! let mut exports = ExportSection::new(); //! exports.export("f", ExportKind::Func, 0); //! module.section(&exports); //! //! // Encode the code section. //! let mut codes = CodeSection::new(); //! let locals = vec![]; //! let mut f = Function::new(locals); //! f.instruction(&Instruction::LocalGet(0)); //! f.instruction(&Instruction::LocalGet(1)); //! f.instruction(&Instruction::I32Add); //! f.instruction(&Instruction::End); //! codes.function(&f); //! module.section(&codes); //! //! // Extract the encoded Wasm bytes for this module. //! let wasm_bytes = module.finish(); //! //! // We generated a valid Wasm module! //! assert!(wasmparser::validate(&wasm_bytes).is_ok()); //! ``` #![deny(missing_docs, missing_debug_implementations)] mod component; mod core; mod raw; pub use self::component::*; pub use self::core::*; pub use self::raw::*; /// Implemented by types that can be encoded into a byte sink. pub trait Encode { /// Encode the type into the given byte sink. fn encode(&self, sink: &mut Vec); } impl Encode for &'_ T { fn encode(&self, sink: &mut Vec) { T::encode(self, sink) } } impl Encode for [T] { fn encode(&self, sink: &mut Vec) { self.len().encode(sink); for item in self { item.encode(sink); } } } impl Encode for [u8] { fn encode(&self, sink: &mut Vec) { self.len().encode(sink); sink.extend(self); } } impl Encode for str { fn encode(&self, sink: &mut Vec) { self.len().encode(sink); sink.extend_from_slice(self.as_bytes()); } } impl Encode for usize { fn encode(&self, sink: &mut Vec) { assert!(*self <= u32::max_value() as usize); (*self as u32).encode(sink) } } impl Encode for u32 { fn encode(&self, sink: &mut Vec) { leb128::write::unsigned(sink, (*self).into()).unwrap(); } } impl Encode for i32 { fn encode(&self, sink: &mut Vec) { leb128::write::signed(sink, (*self).into()).unwrap(); } } impl Encode for u64 { fn encode(&self, sink: &mut Vec) { leb128::write::unsigned(sink, *self).unwrap(); } } impl Encode for i64 { fn encode(&self, sink: &mut Vec) { leb128::write::signed(sink, *self).unwrap(); } } impl Encode for Option where T: Encode, { fn encode(&self, sink: &mut Vec) { match self { Some(v) => { sink.push(0x01); v.encode(sink); } None => sink.push(0x00), } } } fn encoding_size(n: u32) -> usize { let mut buf = [0u8; 5]; leb128::write::unsigned(&mut &mut buf[..], n.into()).unwrap() } fn encode_section(sink: &mut Vec, count: u32, bytes: &[u8]) { (encoding_size(count) + bytes.len()).encode(sink); count.encode(sink); sink.extend(bytes); } #[cfg(test)] mod test { use super::*; #[test] fn it_encodes_an_empty_module() { let bytes = Module::new().finish(); assert_eq!(bytes, [0x00, b'a', b's', b'm', 0x01, 0x00, 0x00, 0x00]); } #[test] fn it_encodes_an_empty_component() { let bytes = Component::new().finish(); assert_eq!(bytes, [0x00, b'a', b's', b'm', 0x0c, 0x00, 0x01, 0x00]); } }