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