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#[derive(Hash, PartialEq, Eq)]
12pub struct FunctionKey<'a> {
13 params: &'a [(String, Type)],
14 result: &'a Option<Type>,
15}
16
17pub trait ValtypeEncoder<'a> {
25 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>);
31
32 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>);
35
36 fn export_type(&mut self, index: u32, name: &'a str) -> Option<u32>;
38
39 fn export_resource(&mut self, name: &'a str) -> u32;
42
43 fn type_map(&mut self) -> &mut HashMap<TypeId, u32>;
45
46 fn import_type(&mut self, interface: InterfaceId, id: TypeId) -> u32;
49
50 fn interface(&self) -> Option<InterfaceId>;
52
53 fn func_type_map(&mut self) -> &mut HashMap<FunctionKey<'a>, u32>;
56
57 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 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 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 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 let Some(index) = self.type_map().get(&id) {
120 return Ok(ComponentValType::Type(*index));
121 }
122
123 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 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 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 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, ))
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 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}