wasm_encoder/
lib.rs

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