wit_component/encoding/
types.rs

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