| 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 | #![no_std ] |
| 73 | #![deny (missing_docs, missing_debug_implementations)] |
| 74 | |
| 75 | extern crate alloc; |
| 76 | #[cfg (feature = "std" )] |
| 77 | #[macro_use ] |
| 78 | extern crate std; |
| 79 | |
| 80 | #[cfg (feature = "component-model" )] |
| 81 | mod component; |
| 82 | mod core; |
| 83 | mod raw; |
| 84 | #[cfg (feature = "wasmparser" )] |
| 85 | pub mod reencode; |
| 86 | |
| 87 | #[cfg (feature = "component-model" )] |
| 88 | pub use self::component::*; |
| 89 | pub use self::core::*; |
| 90 | pub use self::raw::*; |
| 91 | |
| 92 | use alloc::vec::Vec; |
| 93 | |
| 94 | /// Implemented by types that can be encoded into a byte sink. |
| 95 | pub trait Encode { |
| 96 | /// Encode the type into the given byte sink. |
| 97 | fn encode(&self, sink: &mut Vec<u8>); |
| 98 | } |
| 99 | |
| 100 | impl<T: Encode + ?Sized> Encode for &'_ T { |
| 101 | fn encode(&self, sink: &mut Vec<u8>) { |
| 102 | T::encode(self, sink) |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | impl<T: Encode> Encode for [T] { |
| 107 | fn encode(&self, sink: &mut Vec<u8>) { |
| 108 | self.len().encode(sink); |
| 109 | for item: &T in self { |
| 110 | item.encode(sink); |
| 111 | } |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | impl Encode for [u8] { |
| 116 | fn encode(&self, sink: &mut Vec<u8>) { |
| 117 | self.len().encode(sink); |
| 118 | sink.extend(self); |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | impl Encode for str { |
| 123 | fn encode(&self, sink: &mut Vec<u8>) { |
| 124 | self.len().encode(sink); |
| 125 | sink.extend_from_slice(self.as_bytes()); |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | impl Encode for usize { |
| 130 | fn encode(&self, sink: &mut Vec<u8>) { |
| 131 | assert!(*self <= u32::max_value() as usize); |
| 132 | (*self as u32).encode(sink) |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | impl Encode for u32 { |
| 137 | fn encode(&self, sink: &mut Vec<u8>) { |
| 138 | leb128::write::unsigned(w:sink, (*self).into()).unwrap(); |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | impl Encode for i32 { |
| 143 | fn encode(&self, sink: &mut Vec<u8>) { |
| 144 | leb128::write::signed(w:sink, (*self).into()).unwrap(); |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | impl Encode for u64 { |
| 149 | fn encode(&self, sink: &mut Vec<u8>) { |
| 150 | leb128::write::unsigned(w:sink, *self).unwrap(); |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | impl Encode for i64 { |
| 155 | fn encode(&self, sink: &mut Vec<u8>) { |
| 156 | leb128::write::signed(w:sink, *self).unwrap(); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | impl Encode for f32 { |
| 161 | fn encode(&self, sink: &mut Vec<u8>) { |
| 162 | let bits: u32 = self.to_bits(); |
| 163 | sink.extend(iter:bits.to_le_bytes()) |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | impl Encode for f64 { |
| 168 | fn encode(&self, sink: &mut Vec<u8>) { |
| 169 | let bits: u64 = self.to_bits(); |
| 170 | sink.extend(iter:bits.to_le_bytes()) |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | fn encode_vec<T, V>(elements: V, sink: &mut Vec<u8>) |
| 175 | where |
| 176 | T: Encode, |
| 177 | V: IntoIterator<Item = T>, |
| 178 | V::IntoIter: ExactSizeIterator, |
| 179 | { |
| 180 | let elements: impl ExactSizeIterator = elements.into_iter(); |
| 181 | u32::try_from(elements.len()).unwrap().encode(sink); |
| 182 | for x: T in elements { |
| 183 | x.encode(sink); |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | impl<T> Encode for Option<T> |
| 188 | where |
| 189 | T: Encode, |
| 190 | { |
| 191 | fn encode(&self, sink: &mut Vec<u8>) { |
| 192 | match self { |
| 193 | Some(v: &T) => { |
| 194 | sink.push(0x01); |
| 195 | v.encode(sink); |
| 196 | } |
| 197 | None => sink.push(0x00), |
| 198 | } |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | fn encoding_size(n: u32) -> usize { |
| 203 | let mut buf: [u8; 5] = [0u8; 5]; |
| 204 | leb128::write::unsigned(&mut &mut buf[..], val:n.into()).unwrap() |
| 205 | } |
| 206 | |
| 207 | fn encode_section(sink: &mut Vec<u8>, count: u32, bytes: &[u8]) { |
| 208 | (encoding_size(count) + bytes.len()).encode(sink); |
| 209 | count.encode(sink); |
| 210 | sink.extend(iter:bytes); |
| 211 | } |
| 212 | |
| 213 | #[cfg (test)] |
| 214 | mod test { |
| 215 | use super::*; |
| 216 | |
| 217 | #[test ] |
| 218 | fn it_encodes_an_empty_module() { |
| 219 | let bytes = Module::new().finish(); |
| 220 | assert_eq!(bytes, [0x00, b'a' , b's' , b'm' , 0x01, 0x00, 0x00, 0x00]); |
| 221 | } |
| 222 | |
| 223 | #[test ] |
| 224 | fn it_encodes_an_empty_component() { |
| 225 | let bytes = Component::new().finish(); |
| 226 | assert_eq!(bytes, [0x00, b'a' , b's' , b'm' , 0x0d, 0x00, 0x01, 0x00]); |
| 227 | } |
| 228 | } |
| 229 | |