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