1use std::borrow::Cow;
2
3use crate::core::{CompositeInnerType, CompositeType};
4
5use super::*;
6use wasm_encoder::{ComponentExportKind, ComponentOuterAliasKind, ExportKind};
7
8impl Component {
9 pub fn to_bytes(&self) -> Vec<u8> {
11 self.encoded().finish()
12 }
13
14 fn encoded(&self) -> wasm_encoder::Component {
15 let mut component = wasm_encoder::Component::new();
16 for section in &self.sections {
17 section.encode(&mut component);
18 }
19 component
20 }
21}
22
23impl Section {
24 fn encode(&self, component: &mut wasm_encoder::Component) {
25 match self {
26 Self::Custom(sec) => sec.encode(component),
27 Self::CoreModule(module) => {
28 let bytes = module.to_bytes();
29 component.section(&wasm_encoder::RawSection {
30 id: wasm_encoder::ComponentSectionId::CoreModule as u8,
31 data: &bytes,
32 });
33 }
34 Self::CoreInstance(_) => todo!(),
35 Self::CoreType(sec) => sec.encode(component),
36 Self::Component(comp) => {
37 let bytes = comp.to_bytes();
38 component.section(&wasm_encoder::RawSection {
39 id: wasm_encoder::ComponentSectionId::Component as u8,
40 data: &bytes,
41 });
42 }
43 Self::Instance(_) => todo!(),
44 Self::Alias(_) => todo!(),
45 Self::Type(sec) => sec.encode(component),
46 Self::Canonical(sec) => sec.encode(component),
47 Self::Start(_) => todo!(),
48 Self::Import(sec) => sec.encode(component),
49 Self::Export(_) => todo!(),
50 }
51 }
52}
53
54impl CustomSection {
55 fn encode(&self, component: &mut wasm_encoder::Component) {
56 component.section(&wasm_encoder::CustomSection {
57 name: (&self.name).into(),
58 data: Cow::Borrowed(&self.data),
59 });
60 }
61}
62
63impl TypeSection {
64 fn encode(&self, component: &mut wasm_encoder::Component) {
65 let mut sec = wasm_encoder::ComponentTypeSection::new();
66 for ty in &self.types {
67 ty.encode(sec.ty());
68 }
69 component.section(&sec);
70 }
71}
72
73impl ImportSection {
74 fn encode(&self, component: &mut wasm_encoder::Component) {
75 let mut sec = wasm_encoder::ComponentImportSection::new();
76 for imp in &self.imports {
77 sec.import(&imp.name, imp.ty);
78 }
79 component.section(&sec);
80 }
81}
82
83impl CanonicalSection {
84 fn encode(&self, component: &mut wasm_encoder::Component) {
85 let mut sec = wasm_encoder::CanonicalFunctionSection::new();
86 for func in &self.funcs {
87 match func {
88 Func::CanonLift {
89 func_ty,
90 options,
91 core_func_index,
92 } => {
93 let options = translate_canon_opt(options);
94 sec.lift(*core_func_index, *func_ty, options);
95 }
96 Func::CanonLower {
97 options,
98 func_index,
99 } => {
100 let options = translate_canon_opt(options);
101 sec.lower(*func_index, options);
102 }
103 }
104 }
105 component.section(&sec);
106 }
107}
108
109impl CoreTypeSection {
110 fn encode(&self, component: &mut wasm_encoder::Component) {
111 let mut sec = wasm_encoder::CoreTypeSection::new();
112 for ty in &self.types {
113 ty.encode(sec.ty());
114 }
115 component.section(&sec);
116 }
117}
118
119impl CoreType {
120 fn encode(&self, enc: wasm_encoder::ComponentCoreTypeEncoder<'_>) {
121 match self {
122 Self::Func(ty) => {
123 enc.core()
124 .function(ty.params.iter().copied(), ty.results.iter().copied());
125 }
126 Self::Module(mod_ty) => {
127 let mut enc_mod_ty = wasm_encoder::ModuleType::new();
128 for def in &mod_ty.defs {
129 match def {
130 ModuleTypeDef::TypeDef(CompositeType {
131 inner: CompositeInnerType::Func(func_ty),
132 ..
133 }) => {
134 enc_mod_ty.ty().function(
135 func_ty.params.iter().copied(),
136 func_ty.results.iter().copied(),
137 );
138 }
139 ModuleTypeDef::TypeDef(_) => {
140 unimplemented!("non-func types in a component's module type")
141 }
142 ModuleTypeDef::OuterAlias { count, i, kind } => match kind {
143 CoreOuterAliasKind::Type(_) => {
144 enc_mod_ty.alias_outer_core_type(*count, *i);
145 }
146 },
147 ModuleTypeDef::Import(imp) => {
148 enc_mod_ty.import(
149 &imp.module,
150 &imp.field,
151 crate::core::encode::translate_entity_type(&imp.entity_type),
152 );
153 }
154 ModuleTypeDef::Export(name, ty) => {
155 enc_mod_ty.export(name, crate::core::encode::translate_entity_type(ty));
156 }
157 }
158 }
159 enc.module(&enc_mod_ty);
160 }
161 }
162 }
163}
164
165impl Type {
166 fn encode(&self, enc: wasm_encoder::ComponentTypeEncoder<'_>) {
167 match self {
168 Self::Defined(ty) => {
169 ty.encode(enc.defined_type());
170 }
171 Self::Func(func_ty) => {
172 let mut f = enc.function();
173
174 f.params(func_ty.params.iter().map(|(name, ty)| (name.as_str(), *ty)));
175 f.result(func_ty.unnamed_result_ty());
176 }
177 Self::Component(comp_ty) => {
178 let mut enc_comp_ty = wasm_encoder::ComponentType::new();
179 for def in &comp_ty.defs {
180 match def {
181 ComponentTypeDef::Import(imp) => {
182 enc_comp_ty.import(&imp.name, imp.ty);
183 }
184 ComponentTypeDef::CoreType(ty) => {
185 ty.encode(enc_comp_ty.core_type());
186 }
187 ComponentTypeDef::Type(ty) => {
188 ty.encode(enc_comp_ty.ty());
189 }
190 ComponentTypeDef::Export { name, url: _, ty } => {
191 enc_comp_ty.export(name, *ty);
192 }
193 ComponentTypeDef::Alias(a) => {
194 enc_comp_ty.alias(translate_alias(a));
195 }
196 }
197 }
198 enc.component(&enc_comp_ty);
199 }
200 Self::Instance(inst_ty) => {
201 let mut enc_inst_ty = wasm_encoder::InstanceType::new();
202 for def in &inst_ty.defs {
203 match def {
204 InstanceTypeDecl::CoreType(ty) => {
205 ty.encode(enc_inst_ty.core_type());
206 }
207 InstanceTypeDecl::Type(ty) => {
208 ty.encode(enc_inst_ty.ty());
209 }
210 InstanceTypeDecl::Export { name, url: _, ty } => {
211 enc_inst_ty.export(name, *ty);
212 }
213 InstanceTypeDecl::Alias(a) => {
214 enc_inst_ty.alias(translate_alias(a));
215 }
216 }
217 }
218 enc.instance(&enc_inst_ty);
219 }
220 }
221 }
222}
223
224impl DefinedType {
225 fn encode(&self, enc: wasm_encoder::ComponentDefinedTypeEncoder<'_>) {
226 match self {
227 Self::Primitive(ty) => enc.primitive(*ty),
228 Self::Record(ty) => {
229 enc.record(ty.fields.iter().map(|(name, ty)| (name.as_str(), *ty)));
230 }
231 Self::Variant(ty) => {
232 enc.variant(
233 ty.cases
234 .iter()
235 .map(|(name, ty, refines)| (name.as_str(), *ty, *refines)),
236 );
237 }
238 Self::List(ty) => {
239 enc.list(ty.elem_ty);
240 }
241 Self::Tuple(ty) => {
242 enc.tuple(ty.fields.iter().copied());
243 }
244 Self::Flags(ty) => {
245 enc.flags(ty.fields.iter().map(|f| f.as_str()));
246 }
247 Self::Enum(ty) => {
248 enc.enum_type(ty.variants.iter().map(|v| v.as_str()));
249 }
250 Self::Option(ty) => {
251 enc.option(ty.inner_ty);
252 }
253 Self::Result(ty) => {
254 enc.result(ty.ok_ty, ty.err_ty);
255 }
256 }
257 }
258}
259
260fn translate_canon_opt(options: &[CanonOpt]) -> Vec<wasm_encoder::CanonicalOption> {
261 options
262 .iter()
263 .map(|o| match o {
264 CanonOpt::StringUtf8 => wasm_encoder::CanonicalOption::UTF8,
265 CanonOpt::StringUtf16 => wasm_encoder::CanonicalOption::UTF16,
266 CanonOpt::StringLatin1Utf16 => wasm_encoder::CanonicalOption::CompactUTF16,
267 CanonOpt::Memory(idx) => wasm_encoder::CanonicalOption::Memory(*idx),
268 CanonOpt::Realloc(idx) => wasm_encoder::CanonicalOption::Realloc(*idx),
269 CanonOpt::PostReturn(idx) => wasm_encoder::CanonicalOption::PostReturn(*idx),
270 })
271 .collect()
272}
273
274fn translate_alias(alias: &Alias) -> wasm_encoder::Alias<'_> {
275 match alias {
276 Alias::InstanceExport {
277 instance,
278 name,
279 kind,
280 } => wasm_encoder::Alias::InstanceExport {
281 instance: *instance,
282 name,
283 kind: match kind {
284 InstanceExportAliasKind::Module => ComponentExportKind::Module,
285 InstanceExportAliasKind::Component => ComponentExportKind::Component,
286 InstanceExportAliasKind::Instance => ComponentExportKind::Instance,
287 InstanceExportAliasKind::Func => ComponentExportKind::Func,
288 InstanceExportAliasKind::Value => ComponentExportKind::Value,
289 },
290 },
291 Alias::CoreInstanceExport {
292 instance,
293 name,
294 kind,
295 } => wasm_encoder::Alias::CoreInstanceExport {
296 instance: *instance,
297 name,
298 kind: match kind {
299 CoreInstanceExportAliasKind::Func => ExportKind::Func,
300 CoreInstanceExportAliasKind::Table => ExportKind::Table,
301 CoreInstanceExportAliasKind::Global => ExportKind::Global,
302 CoreInstanceExportAliasKind::Memory => ExportKind::Memory,
303 CoreInstanceExportAliasKind::Tag => ExportKind::Tag,
304 },
305 },
306 Alias::Outer { count, i, kind } => wasm_encoder::Alias::Outer {
307 count: *count,
308 index: *i,
309 kind: match kind {
310 OuterAliasKind::Module => ComponentOuterAliasKind::CoreModule,
311 OuterAliasKind::Component => ComponentOuterAliasKind::Component,
312 OuterAliasKind::Type(_) => ComponentOuterAliasKind::Type,
313 OuterAliasKind::CoreType(_) => ComponentOuterAliasKind::CoreType,
314 },
315 },
316 }
317}