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 | |