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