| 1 | //! A WebAssembly encoder. | 
| 2 | //! | 
|---|
| 3 | //! The main builder is the [`Module`]. You can build a section with a | 
|---|
| 4 | //! section-specific builder, like [`TypeSection`] or [`ImportSection`], and | 
|---|
| 5 | //! then add it to the module with [`Module::section`]. When you are finished | 
|---|
| 6 | //! building the module, call either [`Module::as_slice`] or [`Module::finish`] | 
|---|
| 7 | //! to get the encoded bytes. The former gives a shared reference to the | 
|---|
| 8 | //! underlying bytes as a slice, while the latter gives you ownership of them as | 
|---|
| 9 | //! a vector. | 
|---|
| 10 | //! | 
|---|
| 11 | //! # Example | 
|---|
| 12 | //! | 
|---|
| 13 | //! If we wanted to build this module: | 
|---|
| 14 | //! | 
|---|
| 15 | //! ```wasm | 
|---|
| 16 | //! (module | 
|---|
| 17 | //!   (type (func (param i32 i32) (result i32))) | 
|---|
| 18 | //!   (func (type 0) | 
|---|
| 19 | //!     local.get 0 | 
|---|
| 20 | //!     local.get 1 | 
|---|
| 21 | //!     i32.add) | 
|---|
| 22 | //!   (export "f" (func 0))) | 
|---|
| 23 | //! ``` | 
|---|
| 24 | //! | 
|---|
| 25 | //! then we would do this: | 
|---|
| 26 | //! | 
|---|
| 27 | //! ``` | 
|---|
| 28 | //! use wasm_encoder::{ | 
|---|
| 29 | //!     CodeSection, ExportKind, ExportSection, Function, FunctionSection, Instruction, | 
|---|
| 30 | //!     Module, TypeSection, ValType, | 
|---|
| 31 | //! }; | 
|---|
| 32 | //! | 
|---|
| 33 | //! let mut module = Module::new(); | 
|---|
| 34 | //! | 
|---|
| 35 | //! // Encode the type section. | 
|---|
| 36 | //! let mut types = TypeSection::new(); | 
|---|
| 37 | //! let params = vec![ValType::I32, ValType::I32]; | 
|---|
| 38 | //! let results = vec![ValType::I32]; | 
|---|
| 39 | //! types.ty().function(params, results); | 
|---|
| 40 | //! module.section(&types); | 
|---|
| 41 | //! | 
|---|
| 42 | //! // Encode the function section. | 
|---|
| 43 | //! let mut functions = FunctionSection::new(); | 
|---|
| 44 | //! let type_index = 0; | 
|---|
| 45 | //! functions.function(type_index); | 
|---|
| 46 | //! module.section(&functions); | 
|---|
| 47 | //! | 
|---|
| 48 | //! // Encode the export section. | 
|---|
| 49 | //! let mut exports = ExportSection::new(); | 
|---|
| 50 | //! exports.export( "f", ExportKind::Func, 0); | 
|---|
| 51 | //! module.section(&exports); | 
|---|
| 52 | //! | 
|---|
| 53 | //! // Encode the code section. | 
|---|
| 54 | //! let mut codes = CodeSection::new(); | 
|---|
| 55 | //! let locals = vec![]; | 
|---|
| 56 | //! let mut f = Function::new(locals); | 
|---|
| 57 | //! f.instruction(&Instruction::LocalGet(0)); | 
|---|
| 58 | //! f.instruction(&Instruction::LocalGet(1)); | 
|---|
| 59 | //! f.instruction(&Instruction::I32Add); | 
|---|
| 60 | //! f.instruction(&Instruction::End); | 
|---|
| 61 | //! codes.function(&f); | 
|---|
| 62 | //! module.section(&codes); | 
|---|
| 63 | //! | 
|---|
| 64 | //! // Extract the encoded Wasm bytes for this module. | 
|---|
| 65 | //! let wasm_bytes = module.finish(); | 
|---|
| 66 | //! | 
|---|
| 67 | //! // We generated a valid Wasm module! | 
|---|
| 68 | //! assert!(wasmparser::validate(&wasm_bytes).is_ok()); | 
|---|
| 69 | //! ``` | 
|---|
| 70 |  | 
|---|
| 71 | #![ cfg_attr(docsrs, feature(doc_auto_cfg))] | 
|---|
| 72 | #![ deny(missing_docs, missing_debug_implementations)] | 
|---|
| 73 |  | 
|---|
| 74 | #[ cfg(feature = "component-model")] | 
|---|
| 75 | mod component; | 
|---|
| 76 | mod core; | 
|---|
| 77 | mod raw; | 
|---|
| 78 | #[ cfg(feature = "wasmparser")] | 
|---|
| 79 | pub mod reencode; | 
|---|
| 80 |  | 
|---|
| 81 | #[ cfg(feature = "component-model")] | 
|---|
| 82 | pub use self::component::*; | 
|---|
| 83 | pub use self::core::*; | 
|---|
| 84 | pub use self::raw::*; | 
|---|
| 85 |  | 
|---|
| 86 | /// Implemented by types that can be encoded into a byte sink. | 
|---|
| 87 | pub trait Encode { | 
|---|
| 88 | /// Encode the type into the given byte sink. | 
|---|
| 89 | fn encode(&self, sink: &mut Vec<u8>); | 
|---|
| 90 | } | 
|---|
| 91 |  | 
|---|
| 92 | impl<T: Encode + ?Sized> Encode for &'_ T { | 
|---|
| 93 | fn encode(&self, sink: &mut Vec<u8>) { | 
|---|
| 94 | T::encode(self, sink) | 
|---|
| 95 | } | 
|---|
| 96 | } | 
|---|
| 97 |  | 
|---|
| 98 | impl<T: Encode> Encode for [T] { | 
|---|
| 99 | fn encode(&self, sink: &mut Vec<u8>) { | 
|---|
| 100 | self.len().encode(sink); | 
|---|
| 101 | for item: &T in self { | 
|---|
| 102 | item.encode(sink); | 
|---|
| 103 | } | 
|---|
| 104 | } | 
|---|
| 105 | } | 
|---|
| 106 |  | 
|---|
| 107 | impl Encode for [u8] { | 
|---|
| 108 | fn encode(&self, sink: &mut Vec<u8>) { | 
|---|
| 109 | self.len().encode(sink); | 
|---|
| 110 | sink.extend(self); | 
|---|
| 111 | } | 
|---|
| 112 | } | 
|---|
| 113 |  | 
|---|
| 114 | impl Encode for str { | 
|---|
| 115 | fn encode(&self, sink: &mut Vec<u8>) { | 
|---|
| 116 | self.len().encode(sink); | 
|---|
| 117 | sink.extend_from_slice(self.as_bytes()); | 
|---|
| 118 | } | 
|---|
| 119 | } | 
|---|
| 120 |  | 
|---|
| 121 | impl Encode for usize { | 
|---|
| 122 | fn encode(&self, sink: &mut Vec<u8>) { | 
|---|
| 123 | assert!(*self <= u32::max_value() as usize); | 
|---|
| 124 | (*self as u32).encode(sink) | 
|---|
| 125 | } | 
|---|
| 126 | } | 
|---|
| 127 |  | 
|---|
| 128 | impl Encode for u32 { | 
|---|
| 129 | fn encode(&self, sink: &mut Vec<u8>) { | 
|---|
| 130 | leb128::write::unsigned(w:sink, (*self).into()).unwrap(); | 
|---|
| 131 | } | 
|---|
| 132 | } | 
|---|
| 133 |  | 
|---|
| 134 | impl Encode for i32 { | 
|---|
| 135 | fn encode(&self, sink: &mut Vec<u8>) { | 
|---|
| 136 | leb128::write::signed(w:sink, (*self).into()).unwrap(); | 
|---|
| 137 | } | 
|---|
| 138 | } | 
|---|
| 139 |  | 
|---|
| 140 | impl Encode for u64 { | 
|---|
| 141 | fn encode(&self, sink: &mut Vec<u8>) { | 
|---|
| 142 | leb128::write::unsigned(w:sink, *self).unwrap(); | 
|---|
| 143 | } | 
|---|
| 144 | } | 
|---|
| 145 |  | 
|---|
| 146 | impl Encode for i64 { | 
|---|
| 147 | fn encode(&self, sink: &mut Vec<u8>) { | 
|---|
| 148 | leb128::write::signed(w:sink, *self).unwrap(); | 
|---|
| 149 | } | 
|---|
| 150 | } | 
|---|
| 151 |  | 
|---|
| 152 | impl Encode for f32 { | 
|---|
| 153 | fn encode(&self, sink: &mut Vec<u8>) { | 
|---|
| 154 | let bits: u32 = self.to_bits(); | 
|---|
| 155 | sink.extend(iter:bits.to_le_bytes()) | 
|---|
| 156 | } | 
|---|
| 157 | } | 
|---|
| 158 |  | 
|---|
| 159 | impl Encode for f64 { | 
|---|
| 160 | fn encode(&self, sink: &mut Vec<u8>) { | 
|---|
| 161 | let bits: u64 = self.to_bits(); | 
|---|
| 162 | sink.extend(iter:bits.to_le_bytes()) | 
|---|
| 163 | } | 
|---|
| 164 | } | 
|---|
| 165 |  | 
|---|
| 166 | fn encode_vec<T, V>(elements: V, sink: &mut Vec<u8>) | 
|---|
| 167 | where | 
|---|
| 168 | T: Encode, | 
|---|
| 169 | V: IntoIterator<Item = T>, | 
|---|
| 170 | V::IntoIter: ExactSizeIterator, | 
|---|
| 171 | { | 
|---|
| 172 | let elements: impl ExactSizeIterator = elements.into_iter(); | 
|---|
| 173 | u32::try_from(elements.len()).unwrap().encode(sink); | 
|---|
| 174 | for x: T in elements { | 
|---|
| 175 | x.encode(sink); | 
|---|
| 176 | } | 
|---|
| 177 | } | 
|---|
| 178 |  | 
|---|
| 179 | impl<T> Encode for Option<T> | 
|---|
| 180 | where | 
|---|
| 181 | T: Encode, | 
|---|
| 182 | { | 
|---|
| 183 | fn encode(&self, sink: &mut Vec<u8>) { | 
|---|
| 184 | match self { | 
|---|
| 185 | Some(v: &T) => { | 
|---|
| 186 | sink.push(0x01); | 
|---|
| 187 | v.encode(sink); | 
|---|
| 188 | } | 
|---|
| 189 | None => sink.push(0x00), | 
|---|
| 190 | } | 
|---|
| 191 | } | 
|---|
| 192 | } | 
|---|
| 193 |  | 
|---|
| 194 | fn encoding_size(n: u32) -> usize { | 
|---|
| 195 | let mut buf: [u8; 5] = [0u8; 5]; | 
|---|
| 196 | leb128::write::unsigned(&mut &mut buf[..], val:n.into()).unwrap() | 
|---|
| 197 | } | 
|---|
| 198 |  | 
|---|
| 199 | fn encode_section(sink: &mut Vec<u8>, count: u32, bytes: &[u8]) { | 
|---|
| 200 | (encoding_size(count) + bytes.len()).encode(sink); | 
|---|
| 201 | count.encode(sink); | 
|---|
| 202 | sink.extend(iter:bytes); | 
|---|
| 203 | } | 
|---|
| 204 |  | 
|---|
| 205 | #[ cfg(test)] | 
|---|
| 206 | mod test { | 
|---|
| 207 | use super::*; | 
|---|
| 208 |  | 
|---|
| 209 | #[ test] | 
|---|
| 210 | fn it_encodes_an_empty_module() { | 
|---|
| 211 | let bytes = Module::new().finish(); | 
|---|
| 212 | assert_eq!(bytes, [0x00, b'a', b's', b'm', 0x01, 0x00, 0x00, 0x00]); | 
|---|
| 213 | } | 
|---|
| 214 |  | 
|---|
| 215 | #[ test] | 
|---|
| 216 | fn it_encodes_an_empty_component() { | 
|---|
| 217 | let bytes = Component::new().finish(); | 
|---|
| 218 | assert_eq!(bytes, [0x00, b'a', b's', b'm', 0x0d, 0x00, 0x01, 0x00]); | 
|---|
| 219 | } | 
|---|
| 220 | } | 
|---|
| 221 |  | 
|---|