Skip to main content

wasm_metadata/names/
component.rs

1use std::fmt::{self, Debug};
2
3use anyhow::Result;
4use wasm_encoder::Encode;
5use wasm_encoder::reencode::{ReencodeComponent, RoundtripReencoder};
6use wasmparser::{BinaryReader, ComponentNameSectionReader};
7
8/// Helper for rewriting a component's component-name section with a new component name.
9pub struct ComponentNames<'a> {
10    component_name: Option<String>,
11    names: Vec<wasmparser::ComponentName<'a>>,
12}
13
14impl<'a> Debug for ComponentNames<'a> {
15    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16        f.debug_struct("ComponentNames")
17            .field("component_name", &self.component_name)
18            .finish_non_exhaustive()
19    }
20}
21
22impl<'a> ComponentNames<'a> {
23    /// Create an empty component-name section.
24    pub fn empty() -> Self {
25        ComponentNames {
26            component_name: None,
27            names: Vec::new(),
28        }
29    }
30    /// Read a component-name section from a WebAssembly binary. Records the component name, as
31    /// well as all other component name fields for later serialization.
32    pub fn from_bytes(bytes: &'a [u8], offset: u64) -> Result<ComponentNames<'a>> {
33        let reader = BinaryReader::new(bytes, offset);
34        let section = ComponentNameSectionReader::new(reader);
35        let mut s = Self::empty();
36        for name in section.into_iter() {
37            let name = name?;
38            match name {
39                wasmparser::ComponentName::Component { name, .. } => {
40                    s.component_name = Some(name.to_owned())
41                }
42                _ => s.names.push(name),
43            }
44        }
45        Ok(s)
46    }
47    /// Set component name according to [`AddMetadata`]
48    pub(crate) fn from_name(name: &Option<String>) -> Self {
49        let mut s = Self::empty();
50        s.component_name = name.clone();
51        s
52    }
53
54    /// Merge with another section
55    pub(crate) fn merge(&mut self, other: &Self) {
56        if other.component_name.is_some() {
57            self.component_name = other.component_name.clone();
58        }
59        self.names.extend_from_slice(&other.names);
60    }
61
62    /// Set component name
63    pub fn set_name(&mut self, name: &str) {
64        self.component_name = Some(name.to_owned())
65    }
66    /// Get component name
67    pub fn get_name(&self) -> Option<&String> {
68        self.component_name.as_ref()
69    }
70    /// Serialize into [`wasm_encoder::ComponentNameSection`]
71    pub(crate) fn section(&self) -> Result<wasm_encoder::ComponentNameSection> {
72        let mut section = wasm_encoder::ComponentNameSection::new();
73        if let Some(component_name) = &self.component_name {
74            section.component(&component_name);
75        }
76        for n in self.names.iter() {
77            RoundtripReencoder.parse_custom_component_name_subsection(&mut section, n.clone())?;
78        }
79        Ok(section)
80    }
81
82    /// Serialize into the raw bytes of a wasm custom section.
83    pub fn raw_custom_section(&self) -> Result<Vec<u8>> {
84        let mut ret = Vec::new();
85        self.section()?.encode(&mut ret);
86        Ok(ret)
87    }
88}