1use crate::limits::*;
2use crate::prelude::*;
3use crate::{
4 BinaryReader, ComponentAlias, ComponentExportName, ComponentImport, ComponentTypeRef,
5 FromReader, Import, Result, SectionLimited, SubType, TypeRef, ValType,
6};
7use core::fmt;
8
9#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11pub enum OuterAliasKind {
12 Type,
14}
15
16#[derive(Debug, Clone, Eq, PartialEq)]
18pub enum CoreType<'a> {
19 Sub(SubType),
21 Module(Box<[ModuleTypeDeclaration<'a>]>),
23}
24
25impl<'a> FromReader<'a> for CoreType<'a> {
26 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
27 Ok(match reader.peek()? {
28 0x60 => CoreType::Sub(reader.read()?),
29 0x5e | 0x5f => bail!(
30 reader.current_position(),
31 "no support for GC types in the component model yet"
32 ),
33 0x50 => {
34 reader.read_u8()?;
35 CoreType::Module(
36 reader
37 .read_iter(MAX_WASM_MODULE_TYPE_DECLS, "module type declaration")?
38 .collect::<Result<_>>()?,
39 )
40 }
41 x => return reader.invalid_leading_byte(x, "core type"),
42 })
43 }
44}
45
46#[derive(Debug, Clone, Eq, PartialEq)]
48pub enum ModuleTypeDeclaration<'a> {
49 Type(SubType),
51 Export {
53 name: &'a str,
55 ty: TypeRef,
57 },
58 OuterAlias {
60 kind: OuterAliasKind,
62 count: u32,
64 index: u32,
66 },
67 Import(Import<'a>),
69}
70
71impl<'a> FromReader<'a> for ModuleTypeDeclaration<'a> {
72 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
73 Ok(match reader.read_u8()? {
74 0x00 => ModuleTypeDeclaration::Import(reader.read()?),
75 0x01 => ModuleTypeDeclaration::Type(reader.read()?),
76 0x02 => {
77 let kind = match reader.read_u8()? {
78 0x10 => OuterAliasKind::Type,
79 x => {
80 return reader.invalid_leading_byte(x, "outer alias kind");
81 }
82 };
83 match reader.read_u8()? {
84 0x01 => ModuleTypeDeclaration::OuterAlias {
85 kind,
86 count: reader.read()?,
87 index: reader.read()?,
88 },
89 x => {
90 return reader.invalid_leading_byte(x, "outer alias target");
91 }
92 }
93 }
94 0x03 => ModuleTypeDeclaration::Export {
95 name: reader.read()?,
96 ty: reader.read()?,
97 },
98 x => return reader.invalid_leading_byte(x, "type definition"),
99 })
100 }
101}
102
103pub type CoreTypeSectionReader<'a> = SectionLimited<'a, CoreType<'a>>;
116
117#[derive(Debug, Clone, Copy, PartialEq, Eq)]
119pub enum ComponentValType {
120 Primitive(PrimitiveValType),
122 Type(u32),
124}
125
126impl<'a> FromReader<'a> for ComponentValType {
127 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
128 if let Some(ty) = PrimitiveValType::from_byte(reader.peek()?) {
129 reader.read_u8()?;
130 return Ok(ComponentValType::Primitive(ty));
131 }
132
133 Ok(ComponentValType::Type(reader.read_var_s33()? as u32))
134 }
135}
136
137impl<'a> FromReader<'a> for Option<ComponentValType> {
138 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
139 match reader.read_u8()? {
140 0x0 => Ok(None),
141 0x1 => Ok(Some(reader.read()?)),
142 x => reader.invalid_leading_byte(x, "optional component value type"),
143 }
144 }
145}
146
147#[derive(Debug, Clone, Copy, PartialEq, Eq)]
149pub enum PrimitiveValType {
150 Bool,
152 S8,
154 U8,
156 S16,
158 U16,
160 S32,
162 U32,
164 S64,
166 U64,
168 F32,
170 F64,
172 Char,
174 String,
176}
177
178impl PrimitiveValType {
179 fn from_byte(byte: u8) -> Option<PrimitiveValType> {
180 Some(match byte {
181 0x7f => PrimitiveValType::Bool,
182 0x7e => PrimitiveValType::S8,
183 0x7d => PrimitiveValType::U8,
184 0x7c => PrimitiveValType::S16,
185 0x7b => PrimitiveValType::U16,
186 0x7a => PrimitiveValType::S32,
187 0x79 => PrimitiveValType::U32,
188 0x78 => PrimitiveValType::S64,
189 0x77 => PrimitiveValType::U64,
190 0x76 => PrimitiveValType::F32,
191 0x75 => PrimitiveValType::F64,
192 0x74 => PrimitiveValType::Char,
193 0x73 => PrimitiveValType::String,
194 _ => return None,
195 })
196 }
197
198 #[cfg(feature = "validate")]
199 pub(crate) fn contains_ptr(&self) -> bool {
200 matches!(self, Self::String)
201 }
202
203 pub fn is_subtype_of(a: Self, b: Self) -> bool {
205 a == b
212 }
213}
214
215impl fmt::Display for PrimitiveValType {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 use PrimitiveValType::*;
218 let s = match self {
219 Bool => "bool",
220 S8 => "s8",
221 U8 => "u8",
222 S16 => "s16",
223 U16 => "u16",
224 S32 => "s32",
225 U32 => "u32",
226 S64 => "s64",
227 U64 => "u64",
228 F32 => "f32",
229 F64 => "f64",
230 Char => "char",
231 String => "string",
232 };
233 s.fmt(f)
234 }
235}
236
237#[derive(Debug, Clone, Eq, PartialEq)]
239pub enum ComponentType<'a> {
240 Defined(ComponentDefinedType<'a>),
242 Func(ComponentFuncType<'a>),
244 Component(Box<[ComponentTypeDeclaration<'a>]>),
246 Instance(Box<[InstanceTypeDeclaration<'a>]>),
248 Resource {
250 rep: ValType,
252 dtor: Option<u32>,
255 },
256}
257
258impl<'a> FromReader<'a> for ComponentType<'a> {
259 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
260 Ok(match reader.read_u8()? {
261 0x3f => ComponentType::Resource {
262 rep: reader.read()?,
263 dtor: match reader.read_u8()? {
264 0x00 => None,
265 0x01 => Some(reader.read()?),
266 b => return reader.invalid_leading_byte(b, "resource destructor"),
267 },
268 },
269 0x40 => {
270 let params = reader
271 .read_iter(MAX_WASM_FUNCTION_PARAMS, "component function parameters")?
272 .collect::<Result<_>>()?;
273 let results = reader.read()?;
274 ComponentType::Func(ComponentFuncType { params, results })
275 }
276 0x41 => ComponentType::Component(
277 reader
278 .read_iter(MAX_WASM_COMPONENT_TYPE_DECLS, "component type declaration")?
279 .collect::<Result<_>>()?,
280 ),
281 0x42 => ComponentType::Instance(
282 reader
283 .read_iter(MAX_WASM_INSTANCE_TYPE_DECLS, "instance type declaration")?
284 .collect::<Result<_>>()?,
285 ),
286 x => {
287 if let Some(ty) = PrimitiveValType::from_byte(x) {
288 ComponentType::Defined(ComponentDefinedType::Primitive(ty))
289 } else {
290 ComponentType::Defined(ComponentDefinedType::read(reader, x)?)
291 }
292 }
293 })
294 }
295}
296
297#[derive(Debug, Clone, Eq, PartialEq)]
299pub enum ComponentTypeDeclaration<'a> {
300 CoreType(CoreType<'a>),
302 Type(ComponentType<'a>),
304 Alias(ComponentAlias<'a>),
306 Export {
308 name: ComponentExportName<'a>,
310 ty: ComponentTypeRef,
312 },
313 Import(ComponentImport<'a>),
315}
316
317impl<'a> FromReader<'a> for ComponentTypeDeclaration<'a> {
318 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
319 if reader.peek()? == 0x03 {
323 reader.read_u8()?;
324 return Ok(ComponentTypeDeclaration::Import(reader.read()?));
325 }
326
327 Ok(match reader.read()? {
328 InstanceTypeDeclaration::CoreType(t) => ComponentTypeDeclaration::CoreType(t),
329 InstanceTypeDeclaration::Type(t) => ComponentTypeDeclaration::Type(t),
330 InstanceTypeDeclaration::Alias(a) => ComponentTypeDeclaration::Alias(a),
331 InstanceTypeDeclaration::Export { name, ty } => {
332 ComponentTypeDeclaration::Export { name, ty }
333 }
334 })
335 }
336}
337
338#[derive(Debug, Clone, Eq, PartialEq)]
340pub enum InstanceTypeDeclaration<'a> {
341 CoreType(CoreType<'a>),
343 Type(ComponentType<'a>),
345 Alias(ComponentAlias<'a>),
347 Export {
349 name: ComponentExportName<'a>,
351 ty: ComponentTypeRef,
353 },
354}
355
356impl<'a> FromReader<'a> for InstanceTypeDeclaration<'a> {
357 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
358 Ok(match reader.read_u8()? {
359 0x00 => InstanceTypeDeclaration::CoreType(reader.read()?),
360 0x01 => InstanceTypeDeclaration::Type(reader.read()?),
361 0x02 => InstanceTypeDeclaration::Alias(reader.read()?),
362 0x04 => InstanceTypeDeclaration::Export {
363 name: reader.read()?,
364 ty: reader.read()?,
365 },
366 x => return reader.invalid_leading_byte(x, "component or instance type declaration"),
367 })
368 }
369}
370
371#[derive(Debug, Clone, Eq, PartialEq)]
373pub enum ComponentFuncResult<'a> {
374 Unnamed(ComponentValType),
376 Named(Box<[(&'a str, ComponentValType)]>),
378}
379
380impl<'a> FromReader<'a> for ComponentFuncResult<'a> {
381 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
382 Ok(match reader.read_u8()? {
383 0x00 => ComponentFuncResult::Unnamed(reader.read()?),
384 0x01 => ComponentFuncResult::Named(
385 reader
386 .read_iter(MAX_WASM_FUNCTION_RETURNS, "component function results")?
387 .collect::<Result<_>>()?,
388 ),
389 x => return reader.invalid_leading_byte(x, "component function results"),
390 })
391 }
392}
393
394impl ComponentFuncResult<'_> {
395 pub fn type_count(&self) -> usize {
397 match self {
398 Self::Unnamed(_) => 1,
399 Self::Named(vec) => vec.len(),
400 }
401 }
402
403 pub fn iter(&self) -> impl Iterator<Item = (Option<&str>, &ComponentValType)> {
405 enum Either<L, R> {
406 Left(L),
407 Right(R),
408 }
409
410 impl<L, R> Iterator for Either<L, R>
411 where
412 L: Iterator,
413 R: Iterator<Item = L::Item>,
414 {
415 type Item = L::Item;
416
417 fn next(&mut self) -> Option<Self::Item> {
418 match self {
419 Either::Left(l) => l.next(),
420 Either::Right(r) => r.next(),
421 }
422 }
423 }
424
425 match self {
426 Self::Unnamed(ty) => Either::Left(core::iter::once(ty).map(|ty| (None, ty))),
427 Self::Named(vec) => Either::Right(vec.iter().map(|(n, ty)| (Some(*n), ty))),
428 }
429 }
430}
431
432#[derive(Debug, Clone, Eq, PartialEq)]
434pub struct ComponentFuncType<'a> {
435 pub params: Box<[(&'a str, ComponentValType)]>,
437 pub results: ComponentFuncResult<'a>,
439}
440
441#[derive(Debug, Clone, PartialEq, Eq)]
443pub struct VariantCase<'a> {
444 pub name: &'a str,
446 pub ty: Option<ComponentValType>,
448 pub refines: Option<u32>,
450}
451
452impl<'a> FromReader<'a> for VariantCase<'a> {
453 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
454 Ok(VariantCase {
455 name: reader.read()?,
456 ty: reader.read()?,
457 refines: match reader.read_u8()? {
458 0x0 => None,
459 0x1 => Some(reader.read_var_u32()?),
460 x => return reader.invalid_leading_byte(x, "variant case refines"),
461 },
462 })
463 }
464}
465
466#[derive(Debug, Clone, PartialEq, Eq)]
468pub enum ComponentDefinedType<'a> {
469 Primitive(PrimitiveValType),
471 Record(Box<[(&'a str, ComponentValType)]>),
473 Variant(Box<[VariantCase<'a>]>),
475 List(ComponentValType),
477 Tuple(Box<[ComponentValType]>),
479 Flags(Box<[&'a str]>),
481 Enum(Box<[&'a str]>),
483 Option(ComponentValType),
485 Result {
487 ok: Option<ComponentValType>,
489 err: Option<ComponentValType>,
491 },
492 Own(u32),
494 Borrow(u32),
496}
497
498impl<'a> ComponentDefinedType<'a> {
499 fn read(reader: &mut BinaryReader<'a>, byte: u8) -> Result<ComponentDefinedType<'a>> {
500 Ok(match byte {
501 0x72 => ComponentDefinedType::Record(
502 reader
503 .read_iter(MAX_WASM_RECORD_FIELDS, "record field")?
504 .collect::<Result<_>>()?,
505 ),
506 0x71 => ComponentDefinedType::Variant(
507 reader
508 .read_iter(MAX_WASM_VARIANT_CASES, "variant cases")?
509 .collect::<Result<_>>()?,
510 ),
511 0x70 => ComponentDefinedType::List(reader.read()?),
512 0x6f => ComponentDefinedType::Tuple(
513 reader
514 .read_iter(MAX_WASM_TUPLE_TYPES, "tuple types")?
515 .collect::<Result<_>>()?,
516 ),
517 0x6e => ComponentDefinedType::Flags(
518 reader
519 .read_iter(MAX_WASM_FLAG_NAMES, "flag names")?
520 .collect::<Result<_>>()?,
521 ),
522 0x6d => ComponentDefinedType::Enum(
523 reader
524 .read_iter(MAX_WASM_ENUM_CASES, "enum cases")?
525 .collect::<Result<_>>()?,
526 ),
527 0x6b => ComponentDefinedType::Option(reader.read()?),
529 0x6a => ComponentDefinedType::Result {
530 ok: reader.read()?,
531 err: reader.read()?,
532 },
533 0x69 => ComponentDefinedType::Own(reader.read()?),
534 0x68 => ComponentDefinedType::Borrow(reader.read()?),
535 x => return reader.invalid_leading_byte(x, "component defined type"),
536 })
537 }
538}
539
540pub type ComponentTypeSectionReader<'a> = SectionLimited<'a, ComponentType<'a>>;