1use super::EncodingState;
2use anyhow::Result;
3use std::collections::HashMap;
4use wasm_encoder::*;
5use wit_parser::{
6 Enum, Flags, Function, Handle, InterfaceId, Params, Record, Resolve, Result_, Results, Tuple,
7 Type, TypeDefKind, TypeId, TypeOwner, Variant,
8};
9
10/// Represents a key type for interface function definitions.
11#[derive(Hash, PartialEq, Eq)]
12pub struct FunctionKey<'a> {
13 params: &'a Params,
14 results: &'a Results,
15}
16
17/// Support for encoding a wit-parser type into a component.
18///
19/// This is a `trait` to enable different implementations which define types
20/// slightly differently in different contexts. For example types might be
21/// defined within an instance type's index space or might be defined in the
22/// component's root index space in a type section. The default trait methods
23/// here are intended to assist in multiplexing over this difference.
24pub trait ValtypeEncoder<'a> {
25 /// Returns a new type encoder used to define a new type in this type
26 /// section.
27 ///
28 /// The `u32` returned is the index of the type being defined in this type
29 /// index space and the encoder returned must be used to define a type.
30 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>);
31
32 /// Returns the index of a new function type and the encoder of where to
33 /// place its results.
34 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>);
35
36 /// Creates an export item for the specified type index.
37 fn export_type(&mut self, index: u32, name: &'a str) -> Option<u32>;
38
39 /// Creates a new `(type (sub resource))` export with the given name,
40 /// returning the type index that refers to the fresh type created.
41 fn export_resource(&mut self, name: &'a str) -> u32;
42
43 /// Returns a map of all types previously defined in this type index space.
44 fn type_map(&mut self) -> &mut HashMap<TypeId, u32>;
45
46 /// Imports `id` from a different interface, returning the index of the
47 /// imported type into this index space.
48 fn import_type(&mut self, interface: InterfaceId, id: TypeId) -> u32;
49
50 /// Returns the identifier of the interface that generation is for.
51 fn interface(&self) -> Option<InterfaceId>;
52
53 /// Returns the map of already-defined function types in this type index
54 /// space.
55 fn func_type_map(&mut self) -> &mut HashMap<FunctionKey<'a>, u32>;
56
57 /// Encodes a new function type which is defined within the provided
58 /// document.
59 fn encode_func_type(&mut self, resolve: &'a Resolve, func: &'a Function) -> Result<u32> {
60 let key = FunctionKey {
61 params: &func.params,
62 results: &func.results,
63 };
64 if let Some(index) = self.func_type_map().get(&key) {
65 return Ok(*index);
66 }
67
68 // Encode all referenced parameter types from this function.
69 let params: Vec<_> = self.encode_params(resolve, &func.params)?;
70
71 enum EncodedResults<'a> {
72 Named(Vec<(&'a str, ComponentValType)>),
73 Anon(ComponentValType),
74 }
75
76 let results = match &func.results {
77 Results::Named(rs) => EncodedResults::Named(self.encode_params(resolve, rs)?),
78 Results::Anon(ty) => EncodedResults::Anon(self.encode_valtype(resolve, ty)?),
79 };
80
81 // Encode the function type
82 let (index, mut f) = self.define_function_type();
83 f.params(params);
84 match results {
85 EncodedResults::Named(rs) => f.results(rs),
86 EncodedResults::Anon(ty) => f.result(ty),
87 };
88 let prev = self.func_type_map().insert(key, index);
89 assert!(prev.is_none());
90 Ok(index)
91 }
92
93 fn encode_params(
94 &mut self,
95 resolve: &'a Resolve,
96 params: &'a Params,
97 ) -> Result<Vec<(&'a str, ComponentValType)>> {
98 params
99 .iter()
100 .map(|(name, ty)| Ok((name.as_str(), self.encode_valtype(resolve, ty)?)))
101 .collect::<Result<_>>()
102 }
103
104 /// Encodes the `ty`, defined within `resolve`, into this encoder and returns
105 /// the corresponding `ComponentValType` that it represents.
106 ///
107 /// This will recursively define the entire structure of `ty` within `self`
108 /// if necessary.
109 fn encode_valtype(&mut self, resolve: &'a Resolve, ty: &Type) -> Result<ComponentValType> {
110 Ok(match *ty {
111 Type::Bool => ComponentValType::Primitive(PrimitiveValType::Bool),
112 Type::U8 => ComponentValType::Primitive(PrimitiveValType::U8),
113 Type::U16 => ComponentValType::Primitive(PrimitiveValType::U16),
114 Type::U32 => ComponentValType::Primitive(PrimitiveValType::U32),
115 Type::U64 => ComponentValType::Primitive(PrimitiveValType::U64),
116 Type::S8 => ComponentValType::Primitive(PrimitiveValType::S8),
117 Type::S16 => ComponentValType::Primitive(PrimitiveValType::S16),
118 Type::S32 => ComponentValType::Primitive(PrimitiveValType::S32),
119 Type::S64 => ComponentValType::Primitive(PrimitiveValType::S64),
120 Type::F32 => ComponentValType::Primitive(PrimitiveValType::F32),
121 Type::F64 => ComponentValType::Primitive(PrimitiveValType::F64),
122 Type::Char => ComponentValType::Primitive(PrimitiveValType::Char),
123 Type::String => ComponentValType::Primitive(PrimitiveValType::String),
124 Type::Id(id) => {
125 // If this id has already been prior defined into this section
126 // refer to that definition.
127 if let Some(index) = self.type_map().get(&id) {
128 return Ok(ComponentValType::Type(*index));
129 }
130
131 // If this type is imported from another interface then return
132 // it as it was bound here with an alias.
133 let ty = &resolve.types[id];
134 log::trace!("encode type name={:?} {:?}", ty.name, &ty.kind);
135 if let Some(index) = self.maybe_import_type(resolve, id) {
136 self.type_map().insert(id, index);
137 return Ok(ComponentValType::Type(index));
138 }
139
140 // ... and failing all that insert the type export.
141 let mut encoded = match &ty.kind {
142 TypeDefKind::Record(r) => self.encode_record(resolve, r)?,
143 TypeDefKind::Tuple(t) => self.encode_tuple(resolve, t)?,
144 TypeDefKind::Flags(r) => self.encode_flags(r)?,
145 TypeDefKind::Variant(v) => self.encode_variant(resolve, v)?,
146 TypeDefKind::Option(t) => self.encode_option(resolve, t)?,
147 TypeDefKind::Result(r) => self.encode_result(resolve, r)?,
148 TypeDefKind::Enum(e) => self.encode_enum(e)?,
149 TypeDefKind::List(ty) => {
150 let ty = self.encode_valtype(resolve, ty)?;
151 let (index, encoder) = self.defined_type();
152 encoder.list(ty);
153 ComponentValType::Type(index)
154 }
155 TypeDefKind::Type(ty) => self.encode_valtype(resolve, ty)?,
156 TypeDefKind::Future(ty) => self.encode_future(resolve, ty)?,
157 TypeDefKind::Stream(ty) => self.encode_stream(resolve, ty)?,
158 TypeDefKind::ErrorContext => self.encode_error_context()?,
159 TypeDefKind::Unknown => unreachable!(),
160 TypeDefKind::Resource => {
161 let name = ty.name.as_ref().expect("resources must be named");
162 let index = self.export_resource(name);
163 self.type_map().insert(id, index);
164 return Ok(ComponentValType::Type(index));
165 }
166 TypeDefKind::Handle(Handle::Own(id)) => {
167 let ty = match self.encode_valtype(resolve, &Type::Id(*id))? {
168 ComponentValType::Type(index) => index,
169 _ => panic!("must be an indexed type"),
170 };
171 let (index, encoder) = self.defined_type();
172 encoder.own(ty);
173 ComponentValType::Type(index)
174 }
175 TypeDefKind::Handle(Handle::Borrow(id)) => {
176 let ty = match self.encode_valtype(resolve, &Type::Id(*id))? {
177 ComponentValType::Type(index) => index,
178 _ => panic!("must be an indexed type"),
179 };
180 let (index, encoder) = self.defined_type();
181 encoder.borrow(ty);
182 ComponentValType::Type(index)
183 }
184 };
185
186 if let Some(name) = &ty.name {
187 let index = match encoded {
188 ComponentValType::Type(index) => index,
189 ComponentValType::Primitive(ty) => {
190 // Named primitive types need entries in the type
191 // section, so convert this to a type reference
192 let (index, encoder) = self.defined_type();
193 encoder.primitive(ty);
194 index
195 }
196 };
197 let index = self.export_type(index, name).unwrap_or(index);
198
199 encoded = ComponentValType::Type(index);
200 }
201
202 if let ComponentValType::Type(index) = encoded {
203 self.type_map().insert(id, index);
204 }
205
206 encoded
207 }
208 })
209 }
210
211 /// Optionally imports `id` from a different interface, returning the index
212 /// of the imported type into this index space.
213 ///
214 /// Returns `None` if `id` can't be imported.
215 fn maybe_import_type(&mut self, resolve: &Resolve, id: TypeId) -> Option<u32> {
216 let ty = &resolve.types[id];
217 let owner = match ty.owner {
218 TypeOwner::Interface(i) => i,
219 _ => return None,
220 };
221 if Some(owner) == self.interface() {
222 return None;
223 }
224 Some(self.import_type(owner, id))
225 }
226
227 fn encode_optional_valtype(
228 &mut self,
229 resolve: &'a Resolve,
230 ty: Option<&Type>,
231 ) -> Result<Option<ComponentValType>> {
232 match ty {
233 Some(ty) => self.encode_valtype(resolve, ty).map(Some),
234 None => Ok(None),
235 }
236 }
237
238 fn encode_record(&mut self, resolve: &'a Resolve, record: &Record) -> Result<ComponentValType> {
239 let fields = record
240 .fields
241 .iter()
242 .map(|f| Ok((f.name.as_str(), self.encode_valtype(resolve, &f.ty)?)))
243 .collect::<Result<Vec<_>>>()?;
244
245 let (index, encoder) = self.defined_type();
246 encoder.record(fields);
247 Ok(ComponentValType::Type(index))
248 }
249
250 fn encode_tuple(&mut self, resolve: &'a Resolve, tuple: &Tuple) -> Result<ComponentValType> {
251 let tys = tuple
252 .types
253 .iter()
254 .map(|ty| self.encode_valtype(resolve, ty))
255 .collect::<Result<Vec<_>>>()?;
256 let (index, encoder) = self.defined_type();
257 encoder.tuple(tys);
258 Ok(ComponentValType::Type(index))
259 }
260
261 fn encode_flags(&mut self, flags: &Flags) -> Result<ComponentValType> {
262 let (index, encoder) = self.defined_type();
263 encoder.flags(flags.flags.iter().map(|f| f.name.as_str()));
264 Ok(ComponentValType::Type(index))
265 }
266
267 fn encode_variant(
268 &mut self,
269 resolve: &'a Resolve,
270 variant: &Variant,
271 ) -> Result<ComponentValType> {
272 let cases = variant
273 .cases
274 .iter()
275 .map(|c| {
276 Ok((
277 c.name.as_str(),
278 self.encode_optional_valtype(resolve, c.ty.as_ref())?,
279 None, // TODO: support defaulting case values in the future
280 ))
281 })
282 .collect::<Result<Vec<_>>>()?;
283
284 let (index, encoder) = self.defined_type();
285 encoder.variant(cases);
286 Ok(ComponentValType::Type(index))
287 }
288
289 fn encode_option(&mut self, resolve: &'a Resolve, payload: &Type) -> Result<ComponentValType> {
290 let ty = self.encode_valtype(resolve, payload)?;
291 let (index, encoder) = self.defined_type();
292 encoder.option(ty);
293 Ok(ComponentValType::Type(index))
294 }
295
296 fn encode_result(
297 &mut self,
298 resolve: &'a Resolve,
299 result: &Result_,
300 ) -> Result<ComponentValType> {
301 let ok = self.encode_optional_valtype(resolve, result.ok.as_ref())?;
302 let error = self.encode_optional_valtype(resolve, result.err.as_ref())?;
303 let (index, encoder) = self.defined_type();
304 encoder.result(ok, error);
305 Ok(ComponentValType::Type(index))
306 }
307
308 fn encode_enum(&mut self, enum_: &Enum) -> Result<ComponentValType> {
309 let (index, encoder) = self.defined_type();
310 encoder.enum_type(enum_.cases.iter().map(|c| c.name.as_str()));
311 Ok(ComponentValType::Type(index))
312 }
313
314 fn encode_future(
315 &mut self,
316 resolve: &'a Resolve,
317 payload: &Option<Type>,
318 ) -> Result<ComponentValType> {
319 let ty = self.encode_optional_valtype(resolve, payload.as_ref())?;
320 let (index, encoder) = self.defined_type();
321 encoder.future(ty);
322 Ok(ComponentValType::Type(index))
323 }
324
325 fn encode_stream(&mut self, resolve: &'a Resolve, payload: &Type) -> Result<ComponentValType> {
326 let ty = self.encode_valtype(resolve, payload)?;
327 let (index, encoder) = self.defined_type();
328 encoder.stream(ty);
329 Ok(ComponentValType::Type(index))
330 }
331
332 fn encode_error_context(&mut self) -> Result<ComponentValType> {
333 let (index, encoder) = self.defined_type();
334 encoder.error_context();
335 Ok(ComponentValType::Type(index))
336 }
337}
338
339pub struct RootTypeEncoder<'state, 'a> {
340 pub state: &'state mut EncodingState<'a>,
341 pub interface: Option<InterfaceId>,
342 pub import_types: bool,
343}
344
345impl<'a> ValtypeEncoder<'a> for RootTypeEncoder<'_, 'a> {
346 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
347 self.state.component.type_defined()
348 }
349 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
350 self.state.component.type_function()
351 }
352 fn interface(&self) -> Option<InterfaceId> {
353 self.interface
354 }
355 fn export_type(&mut self, idx: u32, name: &'a str) -> Option<u32> {
356 // When encoding types for the root the root component will export
357 // this type, but when encoding types for a targeted interface then we
358 // can't export types just yet. Interfaces will be created as an
359 // instance with a bag-of-exports construction which can't refer to its
360 // own types.
361 if self.interface.is_none() {
362 Some(if self.import_types {
363 self.state
364 .component
365 .import(name, ComponentTypeRef::Type(TypeBounds::Eq(idx)))
366 } else {
367 self.state
368 .component
369 .export(name, ComponentExportKind::Type, idx, None)
370 })
371 } else {
372 assert!(!self.import_types);
373 None
374 }
375 }
376 fn export_resource(&mut self, name: &'a str) -> u32 {
377 assert!(self.interface.is_none());
378 assert!(self.import_types);
379 self.state
380 .component
381 .import(name, ComponentTypeRef::Type(TypeBounds::SubResource))
382 }
383 fn import_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
384 if !self.import_types {
385 if let Some(cur) = self.interface {
386 let set = &self.state.info.exports_used[&cur];
387 if set.contains(&interface) {
388 return self.state.alias_exported_type(interface, id);
389 }
390 }
391 }
392 self.state.alias_imported_type(interface, id)
393 }
394 fn type_map(&mut self) -> &mut HashMap<TypeId, u32> {
395 if self.import_types {
396 &mut self.state.import_type_map
397 } else {
398 &mut self.state.export_type_map
399 }
400 }
401 fn func_type_map(&mut self) -> &mut HashMap<FunctionKey<'a>, u32> {
402 if self.import_types {
403 &mut self.state.import_func_type_map
404 } else {
405 &mut self.state.export_func_type_map
406 }
407 }
408}
409
410pub struct InstanceTypeEncoder<'state, 'a> {
411 pub state: &'state mut EncodingState<'a>,
412 pub interface: InterfaceId,
413 pub type_map: HashMap<TypeId, u32>,
414 pub func_type_map: HashMap<FunctionKey<'a>, u32>,
415 pub ty: InstanceType,
416}
417
418impl<'a> ValtypeEncoder<'a> for InstanceTypeEncoder<'_, 'a> {
419 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
420 (self.ty.type_count(), self.ty.ty().defined_type())
421 }
422 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
423 (self.ty.type_count(), self.ty.ty().function())
424 }
425 fn export_type(&mut self, idx: u32, name: &str) -> Option<u32> {
426 let ret = self.ty.type_count();
427 self.ty
428 .export(name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
429 Some(ret)
430 }
431 fn export_resource(&mut self, name: &str) -> u32 {
432 let ret = self.ty.type_count();
433 self.ty
434 .export(name, ComponentTypeRef::Type(TypeBounds::SubResource));
435 ret
436 }
437 fn type_map(&mut self) -> &mut HashMap<TypeId, u32> {
438 &mut self.type_map
439 }
440 fn interface(&self) -> Option<InterfaceId> {
441 Some(self.interface)
442 }
443 fn import_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
444 self.ty.alias(Alias::Outer {
445 count: 1,
446 index: self.state.alias_imported_type(interface, id),
447 kind: ComponentOuterAliasKind::Type,
448 });
449 self.ty.type_count() - 1
450 }
451 fn func_type_map(&mut self) -> &mut HashMap<FunctionKey<'a>, u32> {
452 &mut self.func_type_map
453 }
454}
455