Skip to main content

wasm_encoder/component/
instances.rs

1use super::CORE_INSTANCE_SORT;
2use crate::{
3    ComponentExportKind, ComponentExternName, ComponentSection, ComponentSectionId, Encode,
4    ExportKind, encode_section,
5};
6use alloc::vec::Vec;
7
8/// Represents an argument to a module instantiation.
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub enum ModuleArg {
11    /// The argument is an instance.
12    Instance(u32),
13}
14
15impl Encode for ModuleArg {
16    fn encode(&self, sink: &mut Vec<u8>) {
17        let (sort, idx) = match self {
18            Self::Instance(idx) => (CORE_INSTANCE_SORT, *idx),
19        };
20        sink.push(sort);
21        idx.encode(sink);
22    }
23}
24
25/// An encoder for the core instance section of WebAssembly components.
26///
27/// # Example
28///
29/// ```rust
30/// use wasm_encoder::{Component, InstanceSection, ExportKind, ModuleArg};
31///
32/// let mut instances = InstanceSection::new();
33/// instances.export_items([("foo", ExportKind::Func, 0)]);
34/// instances.instantiate(1, [("foo", ModuleArg::Instance(0))]);
35///
36/// let mut component = Component::new();
37/// component.section(&instances);
38///
39/// let bytes = component.finish();
40/// ```
41#[derive(Clone, Debug, Default)]
42pub struct InstanceSection {
43    bytes: Vec<u8>,
44    num_added: u32,
45}
46
47impl InstanceSection {
48    /// Create a new core instance section encoder.
49    pub fn new() -> Self {
50        Self::default()
51    }
52
53    /// The number of instances in the section.
54    pub fn len(&self) -> u32 {
55        self.num_added
56    }
57
58    /// Determines if the section is empty.
59    pub fn is_empty(&self) -> bool {
60        self.num_added == 0
61    }
62
63    /// Define an instance by instantiating a core module.
64    pub fn instantiate<A, S>(&mut self, module_index: u32, args: A) -> &mut Self
65    where
66        A: IntoIterator<Item = (S, ModuleArg)>,
67        A::IntoIter: ExactSizeIterator,
68        S: AsRef<str>,
69    {
70        let args = args.into_iter();
71        self.bytes.push(0x00);
72        module_index.encode(&mut self.bytes);
73        args.len().encode(&mut self.bytes);
74        for (name, arg) in args {
75            name.as_ref().encode(&mut self.bytes);
76            arg.encode(&mut self.bytes);
77        }
78        self.num_added += 1;
79        self
80    }
81
82    /// Define an instance by exporting core WebAssembly items.
83    pub fn export_items<E, S>(&mut self, exports: E) -> &mut Self
84    where
85        E: IntoIterator<Item = (S, ExportKind, u32)>,
86        E::IntoIter: ExactSizeIterator,
87        S: AsRef<str>,
88    {
89        let exports = exports.into_iter();
90        self.bytes.push(0x01);
91        exports.len().encode(&mut self.bytes);
92        for (name, kind, index) in exports {
93            name.as_ref().encode(&mut self.bytes);
94            kind.encode(&mut self.bytes);
95            index.encode(&mut self.bytes);
96        }
97        self.num_added += 1;
98        self
99    }
100}
101
102impl Encode for InstanceSection {
103    fn encode(&self, sink: &mut Vec<u8>) {
104        encode_section(sink, self.num_added, &self.bytes);
105    }
106}
107
108impl ComponentSection for InstanceSection {
109    fn id(&self) -> u8 {
110        ComponentSectionId::CoreInstance.into()
111    }
112}
113
114/// An encoder for the instance section of WebAssembly components.
115///
116/// # Example
117///
118/// ```rust
119/// use wasm_encoder::{Component, ComponentInstanceSection, ComponentExportKind};
120///
121/// let mut instances = ComponentInstanceSection::new();
122/// instances.export_items([("foo", ComponentExportKind::Func, 0)]);
123/// instances.instantiate(1, [("foo", ComponentExportKind::Instance, 0)]);
124///
125/// let mut component = Component::new();
126/// component.section(&instances);
127///
128/// let bytes = component.finish();
129/// ```
130#[derive(Clone, Debug, Default)]
131pub struct ComponentInstanceSection {
132    bytes: Vec<u8>,
133    num_added: u32,
134}
135
136impl ComponentInstanceSection {
137    /// Create a new instance section encoder.
138    pub fn new() -> Self {
139        Self::default()
140    }
141
142    /// The number of instances in the section.
143    pub fn len(&self) -> u32 {
144        self.num_added
145    }
146
147    /// Determines if the section is empty.
148    pub fn is_empty(&self) -> bool {
149        self.num_added == 0
150    }
151
152    /// Define an instance by instantiating a component.
153    pub fn instantiate<A, S>(&mut self, component_index: u32, args: A) -> &mut Self
154    where
155        A: IntoIterator<Item = (S, ComponentExportKind, u32)>,
156        A::IntoIter: ExactSizeIterator,
157        S: AsRef<str>,
158    {
159        let args = args.into_iter();
160        self.bytes.push(0x00);
161        component_index.encode(&mut self.bytes);
162        args.len().encode(&mut self.bytes);
163        for (name, kind, index) in args {
164            name.as_ref().encode(&mut self.bytes);
165            kind.encode(&mut self.bytes);
166            index.encode(&mut self.bytes);
167        }
168        self.num_added += 1;
169        self
170    }
171
172    /// Define an instance by exporting items.
173    pub fn export_items<'a, N, E>(&mut self, exports: E) -> &mut Self
174    where
175        E: IntoIterator<Item = (N, ComponentExportKind, u32)>,
176        E::IntoIter: ExactSizeIterator,
177        N: Into<ComponentExternName<'a>>,
178    {
179        let exports = exports.into_iter();
180        self.bytes.push(0x01);
181        exports.len().encode(&mut self.bytes);
182        for (name, kind, index) in exports {
183            name.into().encode(&mut self.bytes);
184            kind.encode(&mut self.bytes);
185            index.encode(&mut self.bytes);
186        }
187        self.num_added += 1;
188        self
189    }
190}
191
192impl Encode for ComponentInstanceSection {
193    fn encode(&self, sink: &mut Vec<u8>) {
194        encode_section(sink, self.num_added, &self.bytes);
195    }
196}
197
198impl ComponentSection for ComponentInstanceSection {
199    fn id(&self) -> u8 {
200        ComponentSectionId::Instance.into()
201    }
202}