wasm_encoder/core/names.rs
1use crate::{CustomSection, Encode, Section, SectionId, encoding_size};
2use alloc::borrow::Cow;
3use alloc::vec;
4use alloc::vec::Vec;
5
6/// An encoder for the custom `name` section.
7///
8/// # Example
9///
10/// ```
11/// use wasm_encoder::{Module, NameSection, NameMap};
12///
13/// let mut names = NameSection::new();
14/// names.module("the module name");
15///
16/// let mut function_names = NameMap::new();
17/// function_names.append(0, "name of function 0");
18/// function_names.append(1, "a better function");
19/// function_names.append(3, "the best function");
20/// names.functions(&function_names);
21///
22/// let mut module = Module::new();
23/// module.section(&names);
24///
25/// let wasm_bytes = module.finish();
26/// ```
27#[derive(Clone, Debug, Default)]
28pub struct NameSection {
29 bytes: Vec<u8>,
30}
31
32enum Subsection {
33 // Currently specified in the wasm spec's appendix
34 Module = 0,
35 Function = 1,
36 Local = 2,
37
38 // specified as part of the extended name section proposal
39 //
40 // https://github.com/WebAssembly/extended-name-section/blob/main/proposals/extended-name-section/Overview.md
41 Label = 3,
42 Type = 4,
43 Table = 5,
44 Memory = 6,
45 Global = 7,
46 Element = 8,
47 Data = 9,
48 Parameter = 12,
49 TagParameter = 13,
50
51 // https://github.com/WebAssembly/gc/issues/193
52 Field = 10,
53
54 // https://github.com/WebAssembly/exception-handling/pull/213
55 Tag = 11,
56}
57
58impl NameSection {
59 /// Creates a new blank `name` custom section.
60 pub fn new() -> Self {
61 Self::default()
62 }
63
64 /// Appends a module name subsection to this section.
65 ///
66 /// This will indicate that the name of the entire module should be the
67 /// `name` specified. Note that this should be encoded first before other
68 /// subsections.
69 pub fn module(&mut self, name: &str) {
70 let len = encoding_size(u32::try_from(name.len()).unwrap());
71 self.subsection_header(Subsection::Module, len + name.len());
72 name.encode(&mut self.bytes);
73 }
74
75 /// Appends a subsection for the names of all functions in this wasm module.
76 ///
77 /// Function names are declared in the `names` map provided where the index
78 /// in the map corresponds to the wasm index of the function. This section
79 /// should come after the module name subsection (if present) and before the
80 /// locals subsection (if present).
81 pub fn functions(&mut self, names: &NameMap) {
82 self.subsection_header(Subsection::Function, names.size());
83 names.encode(&mut self.bytes);
84 }
85
86 /// Appends a subsection for the names of locals within functions in this
87 /// wasm module.
88 ///
89 /// This section should come after the function name subsection (if present)
90 /// and before the labels subsection (if present).
91 pub fn locals(&mut self, names: &IndirectNameMap) {
92 self.subsection_header(Subsection::Local, names.size());
93 names.encode(&mut self.bytes);
94 }
95
96 /// Appends a subsection for the names of labels within functions in this
97 /// wasm module.
98 ///
99 /// This section should come after the local name subsection (if present)
100 /// and before the type subsection (if present).
101 pub fn labels(&mut self, names: &IndirectNameMap) {
102 self.subsection_header(Subsection::Label, names.size());
103 names.encode(&mut self.bytes);
104 }
105
106 /// Appends a subsection for the names of all types in this wasm module.
107 ///
108 /// This section should come after the label name subsection (if present)
109 /// and before the table subsection (if present).
110 pub fn types(&mut self, names: &NameMap) {
111 self.subsection_header(Subsection::Type, names.size());
112 names.encode(&mut self.bytes);
113 }
114
115 /// Appends a subsection for the names of all tables in this wasm module.
116 ///
117 /// This section should come after the type name subsection (if present)
118 /// and before the memory subsection (if present).
119 pub fn tables(&mut self, names: &NameMap) {
120 self.subsection_header(Subsection::Table, names.size());
121 names.encode(&mut self.bytes);
122 }
123
124 /// Appends a subsection for the names of all memories in this wasm module.
125 ///
126 /// This section should come after the table name subsection (if present)
127 /// and before the global subsection (if present).
128 pub fn memories(&mut self, names: &NameMap) {
129 self.subsection_header(Subsection::Memory, names.size());
130 names.encode(&mut self.bytes);
131 }
132
133 /// Appends a subsection for the names of all globals in this wasm module.
134 ///
135 /// This section should come after the memory name subsection (if present)
136 /// and before the element subsection (if present).
137 pub fn globals(&mut self, names: &NameMap) {
138 self.subsection_header(Subsection::Global, names.size());
139 names.encode(&mut self.bytes);
140 }
141
142 /// Appends a subsection for the names of all elements in this wasm module.
143 ///
144 /// This section should come after the global name subsection (if present)
145 /// and before the data subsection (if present).
146 pub fn elements(&mut self, names: &NameMap) {
147 self.subsection_header(Subsection::Element, names.size());
148 names.encode(&mut self.bytes);
149 }
150
151 /// Appends a subsection for the names of all data in this wasm module.
152 ///
153 /// This section should come after the element name subsection (if present)
154 /// and before the field subsection (if present).
155 pub fn data(&mut self, names: &NameMap) {
156 self.subsection_header(Subsection::Data, names.size());
157 names.encode(&mut self.bytes);
158 }
159
160 /// Appends a subsection for the names of all tags in this wasm module.
161 ///
162 /// This section should come after the data name subsection (if present).
163 pub fn tag(&mut self, names: &NameMap) {
164 self.subsection_header(Subsection::Tag, names.size());
165 names.encode(&mut self.bytes);
166 }
167
168 /// Appends a subsection for the names of fields within types in this
169 /// wasm module.
170 ///
171 /// This section should come after the data name subsection (if present)
172 /// and before the tag subsection (if present).
173 pub fn fields(&mut self, names: &IndirectNameMap) {
174 self.subsection_header(Subsection::Field, names.size());
175 names.encode(&mut self.bytes);
176 }
177
178 /// Appends a subsection for the names of all tags in this wasm module.
179 ///
180 /// This section should come after the field name subsection (if present).
181 pub fn tags(&mut self, names: &NameMap) {
182 self.subsection_header(Subsection::Tag, names.size());
183 names.encode(&mut self.bytes);
184 }
185
186 /// Appends a subsection for the names of parameters within function types.
187 pub fn parameters(&mut self, names: &IndirectNameMap) {
188 self.subsection_header(Subsection::Parameter, names.size());
189 names.encode(&mut self.bytes);
190 }
191
192 /// Appends a subsection for the names of parameters within tag types.
193 pub fn tag_parameters(&mut self, names: &IndirectNameMap) {
194 self.subsection_header(Subsection::TagParameter, names.size());
195 names.encode(&mut self.bytes);
196 }
197
198 /// Appends a raw subsection with the given id and data.
199 pub fn raw(&mut self, id: u8, data: &[u8]) {
200 self.bytes.push(id);
201 data.encode(&mut self.bytes);
202 }
203
204 fn subsection_header(&mut self, id: Subsection, len: usize) {
205 self.bytes.push(id as u8);
206 len.encode(&mut self.bytes);
207 }
208
209 /// View the encoded section as a CustomSection.
210 pub fn as_custom<'a>(&'a self) -> CustomSection<'a> {
211 CustomSection {
212 name: "name".into(),
213 data: Cow::Borrowed(&self.bytes),
214 }
215 }
216}
217
218impl Encode for NameSection {
219 fn encode(&self, sink: &mut Vec<u8>) {
220 self.as_custom().encode(sink);
221 }
222}
223
224impl Section for NameSection {
225 fn id(&self) -> u8 {
226 SectionId::Custom.into()
227 }
228}
229
230/// A map used to name items in a wasm module, organized by naming each
231/// individual index.
232///
233/// This is used in conjunction with [`NameSection::functions`] and similar
234/// methods.
235#[derive(Clone, Debug, Default)]
236pub struct NameMap {
237 bytes: Vec<u8>,
238 count: u32,
239}
240
241impl NameMap {
242 /// Creates a new empty `NameMap`.
243 pub fn new() -> NameMap {
244 NameMap {
245 bytes: vec![],
246 count: 0,
247 }
248 }
249
250 /// Adds a an entry where the item at `idx` has the `name` specified.
251 ///
252 /// Note that indices should be appended in ascending order of the index
253 /// value. Each index may only be named once, but not all indices must be
254 /// named (e.g. `0 foo; 1 bar; 7 qux` is valid but `0 foo; 0 bar` is not).
255 /// Names do not have to be unique (e.g. `0 foo; 1 foo; 2 foo` is valid).
256 pub fn append(&mut self, idx: u32, name: &str) {
257 idx.encode(&mut self.bytes);
258 name.encode(&mut self.bytes);
259 self.count += 1;
260 }
261
262 pub(crate) fn size(&self) -> usize {
263 encoding_size(self.count) + self.bytes.len()
264 }
265
266 /// Returns whether no names have been added to this map.
267 pub fn is_empty(&self) -> bool {
268 self.count == 0
269 }
270}
271
272impl Encode for NameMap {
273 fn encode(&self, sink: &mut Vec<u8>) {
274 self.count.encode(sink);
275 sink.extend(&self.bytes);
276 }
277}
278
279/// A map used to describe names with two levels of indirection, as opposed to a
280/// [`NameMap`] which has one level of indirection.
281///
282/// This naming map is used with [`NameSection::locals`], for example.
283#[derive(Clone, Debug, Default)]
284pub struct IndirectNameMap {
285 bytes: Vec<u8>,
286 count: u32,
287}
288
289impl IndirectNameMap {
290 /// Creates a new empty name map.
291 pub fn new() -> IndirectNameMap {
292 IndirectNameMap {
293 bytes: vec![],
294 count: 0,
295 }
296 }
297
298 /// Adds a new entry where the item at `idx` has sub-items named within
299 /// `names` as specified.
300 ///
301 /// For example if this is describing local names then `idx` is a function
302 /// index where the indexes within `names` are local indices.
303 pub fn append(&mut self, idx: u32, names: &NameMap) {
304 idx.encode(&mut self.bytes);
305 names.encode(&mut self.bytes);
306 self.count += 1;
307 }
308
309 fn size(&self) -> usize {
310 encoding_size(self.count) + self.bytes.len()
311 }
312}
313
314impl Encode for IndirectNameMap {
315 fn encode(&self, sink: &mut Vec<u8>) {
316 self.count.encode(sink);
317 sink.extend(&self.bytes);
318 }
319}