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")]
75mod component;
76mod core;
77mod raw;
78#[cfg(feature = "wasmparser")]
79pub mod reencode;
80
81#[cfg(feature = "component-model")]
82pub use self::component::*;
83pub use self::core::*;
84pub use self::raw::*;
85
86/// Implemented by types that can be encoded into a byte sink.
87pub trait Encode {
88 /// Encode the type into the given byte sink.
89 fn encode(&self, sink: &mut Vec<u8>);
90}
91
92impl<T: Encode + ?Sized> Encode for &'_ T {
93 fn encode(&self, sink: &mut Vec<u8>) {
94 T::encode(self, sink)
95 }
96}
97
98impl<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
107impl Encode for [u8] {
108 fn encode(&self, sink: &mut Vec<u8>) {
109 self.len().encode(sink);
110 sink.extend(self);
111 }
112}
113
114impl 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
121impl 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
128impl Encode for u32 {
129 fn encode(&self, sink: &mut Vec<u8>) {
130 leb128::write::unsigned(w:sink, (*self).into()).unwrap();
131 }
132}
133
134impl Encode for i32 {
135 fn encode(&self, sink: &mut Vec<u8>) {
136 leb128::write::signed(w:sink, (*self).into()).unwrap();
137 }
138}
139
140impl Encode for u64 {
141 fn encode(&self, sink: &mut Vec<u8>) {
142 leb128::write::unsigned(w:sink, *self).unwrap();
143 }
144}
145
146impl Encode for i64 {
147 fn encode(&self, sink: &mut Vec<u8>) {
148 leb128::write::signed(w:sink, *self).unwrap();
149 }
150}
151
152impl 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
159impl 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
166fn encode_vec<T, V>(elements: V, sink: &mut Vec<u8>)
167where
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
179impl<T> Encode for Option<T>
180where
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
194fn 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
199fn 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)]
206mod 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