/src/wasm-tools/crates/wasm-encoder/src/lib.rs
Line | Count | Source |
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, |
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.instructions() |
58 | | //! .local_get(0) |
59 | | //! .local_get(1) |
60 | | //! .i32_add() |
61 | | //! .end(); |
62 | | //! codes.function(&f); |
63 | | //! module.section(&codes); |
64 | | //! |
65 | | //! // Extract the encoded Wasm bytes for this module. |
66 | | //! let wasm_bytes = module.finish(); |
67 | | //! |
68 | | //! // We generated a valid Wasm module! |
69 | | //! assert!(wasmparser::validate(&wasm_bytes).is_ok()); |
70 | | //! ``` |
71 | | |
72 | | #![cfg_attr(docsrs, feature(doc_cfg))] |
73 | | #![no_std] |
74 | | #![deny(missing_docs, missing_debug_implementations)] |
75 | | |
76 | | extern crate alloc; |
77 | | #[cfg(feature = "std")] |
78 | | #[macro_use] |
79 | | extern crate std; |
80 | | |
81 | | #[cfg(feature = "component-model")] |
82 | | mod component; |
83 | | mod core; |
84 | | mod raw; |
85 | | #[cfg(feature = "wasmparser")] |
86 | | pub mod reencode; |
87 | | |
88 | | #[cfg(feature = "component-model")] |
89 | | pub use self::component::*; |
90 | | pub use self::core::*; |
91 | | pub use self::raw::*; |
92 | | |
93 | | use alloc::vec::Vec; |
94 | | |
95 | | /// Implemented by types that can be encoded into a byte sink. |
96 | | pub trait Encode { |
97 | | /// Encode the type into the given byte sink. |
98 | | fn encode(&self, sink: &mut Vec<u8>); |
99 | | } |
100 | | |
101 | | impl<T: Encode + ?Sized> Encode for &'_ T { |
102 | 86.8k | fn encode(&self, sink: &mut Vec<u8>) { |
103 | 86.8k | T::encode(self, sink) |
104 | 86.8k | } <&wasm_encoder::core::code::ConstExpr as wasm_encoder::Encode>::encode Line | Count | Source | 102 | 65.1k | fn encode(&self, sink: &mut Vec<u8>) { | 103 | 65.1k | T::encode(self, sink) | 104 | 65.1k | } |
<&str as wasm_encoder::Encode>::encode Line | Count | Source | 102 | 21.7k | fn encode(&self, sink: &mut Vec<u8>) { | 103 | 21.7k | T::encode(self, sink) | 104 | 21.7k | } |
|
105 | | } |
106 | | |
107 | | impl<T: Encode> Encode for [T] { |
108 | 57.0k | fn encode(&self, sink: &mut Vec<u8>) { |
109 | 57.0k | self.len().encode(sink); |
110 | 890k | for item in self { |
111 | 833k | item.encode(sink); |
112 | 833k | } |
113 | 57.0k | } <[wasm_encoder::core::types::ValType] as wasm_encoder::Encode>::encode Line | Count | Source | 108 | 256 | fn encode(&self, sink: &mut Vec<u8>) { | 109 | 256 | self.len().encode(sink); | 110 | 512 | for item in self { | 111 | 256 | item.encode(sink); | 112 | 256 | } | 113 | 256 | } |
<[u32] as wasm_encoder::Encode>::encode Line | Count | Source | 108 | 56.8k | fn encode(&self, sink: &mut Vec<u8>) { | 109 | 56.8k | self.len().encode(sink); | 110 | 889k | for item in self { | 111 | 833k | item.encode(sink); | 112 | 833k | } | 113 | 56.8k | } |
|
114 | | } |
115 | | |
116 | | impl Encode for [u8] { |
117 | 764k | fn encode(&self, sink: &mut Vec<u8>) { |
118 | 764k | self.len().encode(sink); |
119 | 764k | sink.extend(self); |
120 | 764k | } |
121 | | } |
122 | | |
123 | | impl Encode for str { |
124 | 1.53M | fn encode(&self, sink: &mut Vec<u8>) { |
125 | 1.53M | self.len().encode(sink); |
126 | 1.53M | sink.extend_from_slice(self.as_bytes()); |
127 | 1.53M | } |
128 | | } |
129 | | |
130 | | impl Encode for usize { |
131 | 4.81M | fn encode(&self, sink: &mut Vec<u8>) { |
132 | 4.81M | assert!(*self <= u32::max_value() as usize); |
133 | 4.81M | (*self as u32).encode(sink) |
134 | 4.81M | } |
135 | | } |
136 | | |
137 | | impl Encode for u32 { |
138 | 21.9M | fn encode(&self, sink: &mut Vec<u8>) { |
139 | 21.9M | let (value, pos) = leb128fmt::encode_u32(*self).unwrap(); |
140 | 21.9M | sink.extend_from_slice(&value[..pos]); |
141 | 21.9M | } |
142 | | } |
143 | | |
144 | | impl Encode for i32 { |
145 | 1.19M | fn encode(&self, sink: &mut Vec<u8>) { |
146 | 1.19M | let (value, pos) = leb128fmt::encode_s32(*self).unwrap(); |
147 | 1.19M | sink.extend_from_slice(&value[..pos]); |
148 | 1.19M | } |
149 | | } |
150 | | |
151 | | impl Encode for u64 { |
152 | 660k | fn encode(&self, sink: &mut Vec<u8>) { |
153 | 660k | let (value, pos) = leb128fmt::encode_u64(*self).unwrap(); |
154 | 660k | sink.extend_from_slice(&value[..pos]); |
155 | 660k | } |
156 | | } |
157 | | |
158 | | impl Encode for i64 { |
159 | 2.88M | fn encode(&self, sink: &mut Vec<u8>) { |
160 | 2.88M | let (value, pos) = leb128fmt::encode_s64(*self).unwrap(); |
161 | 2.88M | sink.extend_from_slice(&value[..pos]); |
162 | 2.88M | } |
163 | | } |
164 | | |
165 | 519k | fn encode_vec<T, V>(elements: V, sink: &mut Vec<u8>) |
166 | 519k | where |
167 | 519k | T: Encode, |
168 | 519k | V: IntoIterator<Item = T>, |
169 | 519k | V::IntoIter: ExactSizeIterator, |
170 | | { |
171 | 519k | let elements = elements.into_iter(); |
172 | 519k | u32::try_from(elements.len()).unwrap().encode(sink); |
173 | 1.32M | for x in elements { |
174 | 805k | x.encode(sink); |
175 | 805k | } |
176 | 519k | } wasm_encoder::encode_vec::<wasm_encoder::core::code::Catch, core::iter::adapters::cloned::Cloned<core::slice::iter::Iter<wasm_encoder::core::code::Catch>>> Line | Count | Source | 165 | 494k | fn encode_vec<T, V>(elements: V, sink: &mut Vec<u8>) | 166 | 494k | where | 167 | 494k | T: Encode, | 168 | 494k | V: IntoIterator<Item = T>, | 169 | 494k | V::IntoIter: ExactSizeIterator, | 170 | | { | 171 | 494k | let elements = elements.into_iter(); | 172 | 494k | u32::try_from(elements.len()).unwrap().encode(sink); | 173 | 1.23M | for x in elements { | 174 | 737k | x.encode(sink); | 175 | 737k | } | 176 | 494k | } |
Unexecuted instantiation: wasm_encoder::encode_vec::<wasm_encoder::core::code::Handle, core::iter::adapters::cloned::Cloned<core::slice::iter::Iter<wasm_encoder::core::code::Handle>>> wasm_encoder::encode_vec::<u32, core::iter::adapters::copied::Copied<core::slice::iter::Iter<u32>>> Line | Count | Source | 165 | 25.3k | fn encode_vec<T, V>(elements: V, sink: &mut Vec<u8>) | 166 | 25.3k | where | 167 | 25.3k | T: Encode, | 168 | 25.3k | V: IntoIterator<Item = T>, | 169 | 25.3k | V::IntoIter: ExactSizeIterator, | 170 | | { | 171 | 25.3k | let elements = elements.into_iter(); | 172 | 25.3k | u32::try_from(elements.len()).unwrap().encode(sink); | 173 | 93.9k | for x in elements { | 174 | 68.6k | x.encode(sink); | 175 | 68.6k | } | 176 | 25.3k | } |
|
177 | | |
178 | | impl<T> Encode for Option<T> |
179 | | where |
180 | | T: Encode, |
181 | | { |
182 | 591k | fn encode(&self, sink: &mut Vec<u8>) { |
183 | 591k | match self { |
184 | 455k | Some(v) => { |
185 | 455k | sink.push(0x01); |
186 | 455k | v.encode(sink); |
187 | 455k | } |
188 | 136k | None => sink.push(0x00), |
189 | | } |
190 | 591k | } <core::option::Option<wasm_encoder::component::types::ComponentValType> as wasm_encoder::Encode>::encode Line | Count | Source | 182 | 128k | fn encode(&self, sink: &mut Vec<u8>) { | 183 | 128k | match self { | 184 | 111k | Some(v) => { | 185 | 111k | sink.push(0x01); | 186 | 111k | v.encode(sink); | 187 | 111k | } | 188 | 16.6k | None => sink.push(0x00), | 189 | | } | 190 | 128k | } |
<core::option::Option<u32> as wasm_encoder::Encode>::encode Line | Count | Source | 182 | 463k | fn encode(&self, sink: &mut Vec<u8>) { | 183 | 463k | match self { | 184 | 343k | Some(v) => { | 185 | 343k | sink.push(0x01); | 186 | 343k | v.encode(sink); | 187 | 343k | } | 188 | 119k | None => sink.push(0x00), | 189 | | } | 190 | 463k | } |
|
191 | | } |
192 | | |
193 | 508k | fn encoding_size(n: u32) -> usize { |
194 | 508k | let (_value, pos) = leb128fmt::encode_u32(n).unwrap(); |
195 | 508k | pos |
196 | 508k | } |
197 | | |
198 | 424k | fn encode_section(sink: &mut Vec<u8>, count: u32, bytes: &[u8]) { |
199 | 424k | (encoding_size(count) + bytes.len()).encode(sink); |
200 | 424k | count.encode(sink); |
201 | 424k | sink.extend(bytes); |
202 | 424k | } |
203 | | |
204 | | #[cfg(test)] |
205 | | mod test { |
206 | | use super::*; |
207 | | |
208 | | #[test] |
209 | | fn test_encoding_size() { |
210 | | assert_eq!(encoding_size(624485), 3); |
211 | | } |
212 | | |
213 | | #[test] |
214 | | fn it_encodes_an_empty_module() { |
215 | | let bytes = Module::new().finish(); |
216 | | assert_eq!(bytes, [0x00, b'a', b's', b'm', 0x01, 0x00, 0x00, 0x00]); |
217 | | } |
218 | | |
219 | | #[test] |
220 | | fn it_encodes_an_empty_component() { |
221 | | let bytes = Component::new().finish(); |
222 | | assert_eq!(bytes, [0x00, b'a', b's', b'm', 0x0d, 0x00, 0x01, 0x00]); |
223 | | } |
224 | | } |