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