Coverage Report

Created: 2025-12-09 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}