1use crate::limits::*;
2use crate::prelude::*;
3use crate::{
4 BinaryReader, ComponentAlias, ComponentExportName, ComponentImport, ComponentTypeRef,
5 FromReader, Import, RecGroup, Result, SectionLimited, 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 Rec(RecGroup),
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()? {
36 0x00 => {
37 reader.read_u8()?;
38 let x = reader.peek()?;
39 if x != 0x50 {
40 return reader.invalid_leading_byte(x, "non-final sub type");
41 }
42 CoreType::Rec(reader.read()?)
43 }
44 0x50 => {
45 reader.read_u8()?;
46 CoreType::Module(
47 reader
48 .read_iter(MAX_WASM_MODULE_TYPE_DECLS, "module type declaration")?
49 .collect::<Result<_>>()?,
50 )
51 }
52 _ => CoreType::Rec(reader.read()?),
53 })
54 }
55}
56
57#[derive(Debug, Clone, Eq, PartialEq)]
59pub enum ModuleTypeDeclaration<'a> {
60 Type(RecGroup),
62 Export {
64 name: &'a str,
66 ty: TypeRef,
68 },
69 OuterAlias {
71 kind: OuterAliasKind,
73 count: u32,
75 index: u32,
77 },
78 Import(Import<'a>),
80}
81
82impl<'a> FromReader<'a> for ModuleTypeDeclaration<'a> {
83 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
84 Ok(match reader.read_u8()? {
85 0x00 => ModuleTypeDeclaration::Import(reader.read()?),
86 0x01 => ModuleTypeDeclaration::Type(reader.read()?),
87 0x02 => {
88 let kind = match reader.read_u8()? {
89 0x10 => OuterAliasKind::Type,
90 x => {
91 return reader.invalid_leading_byte(x, "outer alias kind");
92 }
93 };
94 match reader.read_u8()? {
95 0x01 => ModuleTypeDeclaration::OuterAlias {
96 kind,
97 count: reader.read()?,
98 index: reader.read()?,
99 },
100 x => {
101 return reader.invalid_leading_byte(x, "outer alias target");
102 }
103 }
104 }
105 0x03 => ModuleTypeDeclaration::Export {
106 name: reader.read()?,
107 ty: reader.read()?,
108 },
109 x => return reader.invalid_leading_byte(x, "type definition"),
110 })
111 }
112}
113
114pub type CoreTypeSectionReader<'a> = SectionLimited<'a, CoreType<'a>>;
127
128#[derive(Debug, Clone, Copy, PartialEq, Eq)]
130pub enum ComponentValType {
131 Primitive(PrimitiveValType),
133 Type(u32),
135}
136
137impl<'a> FromReader<'a> for ComponentValType {
138 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
139 if let Some(ty) = PrimitiveValType::from_byte(reader.peek()?) {
140 reader.read_u8()?;
141 return Ok(ComponentValType::Primitive(ty));
142 }
143
144 Ok(ComponentValType::Type(reader.read_var_s33()? as u32))
145 }
146}
147
148impl<'a> FromReader<'a> for Option<ComponentValType> {
149 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
150 match reader.read_u8()? {
151 0x0 => Ok(None),
152 0x1 => Ok(Some(reader.read()?)),
153 x => reader.invalid_leading_byte(x, "optional component value type"),
154 }
155 }
156}
157
158#[derive(Debug, Clone, Copy, PartialEq, Eq)]
160pub enum PrimitiveValType {
161 Bool,
163 S8,
165 U8,
167 S16,
169 U16,
171 S32,
173 U32,
175 S64,
177 U64,
179 F32,
181 F64,
183 Char,
185 String,
187 ErrorContext,
190}
191
192impl PrimitiveValType {
193 fn from_byte(byte: u8) -> Option<PrimitiveValType> {
194 Some(match byte {
195 0x7f => PrimitiveValType::Bool,
196 0x7e => PrimitiveValType::S8,
197 0x7d => PrimitiveValType::U8,
198 0x7c => PrimitiveValType::S16,
199 0x7b => PrimitiveValType::U16,
200 0x7a => PrimitiveValType::S32,
201 0x79 => PrimitiveValType::U32,
202 0x78 => PrimitiveValType::S64,
203 0x77 => PrimitiveValType::U64,
204 0x76 => PrimitiveValType::F32,
205 0x75 => PrimitiveValType::F64,
206 0x74 => PrimitiveValType::Char,
207 0x73 => PrimitiveValType::String,
208 0x64 => PrimitiveValType::ErrorContext,
209 _ => return None,
210 })
211 }
212
213 #[cfg(feature = "validate")]
214 pub(crate) fn contains_ptr(&self) -> bool {
215 matches!(self, Self::String)
216 }
217
218 pub fn is_subtype_of(a: Self, b: Self) -> bool {
220 a == b
227 }
228}
229
230impl fmt::Display for PrimitiveValType {
231 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232 use PrimitiveValType::*;
233 let s = match self {
234 Bool => "bool",
235 S8 => "s8",
236 U8 => "u8",
237 S16 => "s16",
238 U16 => "u16",
239 S32 => "s32",
240 U32 => "u32",
241 S64 => "s64",
242 U64 => "u64",
243 F32 => "f32",
244 F64 => "f64",
245 Char => "char",
246 String => "string",
247 ErrorContext => "error-context",
248 };
249 s.fmt(f)
250 }
251}
252
253#[derive(Debug, Clone, Eq, PartialEq)]
255pub enum ComponentType<'a> {
256 Defined(ComponentDefinedType<'a>),
258 Func(ComponentFuncType<'a>),
260 Component(Box<[ComponentTypeDeclaration<'a>]>),
262 Instance(Box<[InstanceTypeDeclaration<'a>]>),
264 Resource {
266 rep: ValType,
268 dtor: Option<u32>,
271 },
272}
273
274impl<'a> FromReader<'a> for ComponentType<'a> {
275 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
276 Ok(match reader.read_u8()? {
277 0x3f => ComponentType::Resource {
278 rep: reader.read()?,
279 dtor: match reader.read_u8()? {
280 0x00 => None,
281 0x01 => Some(reader.read()?),
282 b => return reader.invalid_leading_byte(b, "resource destructor"),
283 },
284 },
285 byte @ (0x40 | 0x43) => {
286 let params = reader
287 .read_iter(MAX_WASM_FUNCTION_PARAMS, "component function parameters")?
288 .collect::<Result<_>>()?;
289 let result = read_resultlist(reader)?;
290 ComponentType::Func(ComponentFuncType {
291 async_: byte == 0x43,
292 params,
293 result,
294 })
295 }
296 0x41 => ComponentType::Component(
297 reader
298 .read_iter(MAX_WASM_COMPONENT_TYPE_DECLS, "component type declaration")?
299 .collect::<Result<_>>()?,
300 ),
301 0x42 => ComponentType::Instance(
302 reader
303 .read_iter(MAX_WASM_INSTANCE_TYPE_DECLS, "instance type declaration")?
304 .collect::<Result<_>>()?,
305 ),
306 x => {
307 if let Some(ty) = PrimitiveValType::from_byte(x) {
308 ComponentType::Defined(ComponentDefinedType::Primitive(ty))
309 } else {
310 ComponentType::Defined(ComponentDefinedType::read(reader, x)?)
311 }
312 }
313 })
314 }
315}
316
317#[derive(Debug, Clone, Eq, PartialEq)]
319pub enum ComponentTypeDeclaration<'a> {
320 CoreType(CoreType<'a>),
322 Type(ComponentType<'a>),
324 Alias(ComponentAlias<'a>),
326 Export {
328 name: ComponentExportName<'a>,
330 ty: ComponentTypeRef,
332 },
333 Import(ComponentImport<'a>),
335}
336
337impl<'a> FromReader<'a> for ComponentTypeDeclaration<'a> {
338 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
339 if reader.peek()? == 0x03 {
343 reader.read_u8()?;
344 return Ok(ComponentTypeDeclaration::Import(reader.read()?));
345 }
346
347 Ok(match reader.read()? {
348 InstanceTypeDeclaration::CoreType(t) => ComponentTypeDeclaration::CoreType(t),
349 InstanceTypeDeclaration::Type(t) => ComponentTypeDeclaration::Type(t),
350 InstanceTypeDeclaration::Alias(a) => ComponentTypeDeclaration::Alias(a),
351 InstanceTypeDeclaration::Export { name, ty } => {
352 ComponentTypeDeclaration::Export { name, ty }
353 }
354 })
355 }
356}
357
358#[derive(Debug, Clone, Eq, PartialEq)]
360pub enum InstanceTypeDeclaration<'a> {
361 CoreType(CoreType<'a>),
363 Type(ComponentType<'a>),
365 Alias(ComponentAlias<'a>),
367 Export {
369 name: ComponentExportName<'a>,
371 ty: ComponentTypeRef,
373 },
374}
375
376impl<'a> FromReader<'a> for InstanceTypeDeclaration<'a> {
377 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
378 Ok(match reader.read_u8()? {
379 0x00 => InstanceTypeDeclaration::CoreType(reader.read()?),
380 0x01 => InstanceTypeDeclaration::Type(reader.read()?),
381 0x02 => InstanceTypeDeclaration::Alias(reader.read()?),
382 0x04 => InstanceTypeDeclaration::Export {
383 name: reader.read()?,
384 ty: reader.read()?,
385 },
386 x => return reader.invalid_leading_byte(x, "component or instance type declaration"),
387 })
388 }
389}
390
391#[derive(Debug, Clone, Eq, PartialEq)]
393pub struct ComponentFuncType<'a> {
394 pub async_: bool,
396 pub params: Box<[(&'a str, ComponentValType)]>,
398 pub result: Option<ComponentValType>,
400}
401
402pub(crate) fn read_resultlist(reader: &mut BinaryReader<'_>) -> Result<Option<ComponentValType>> {
403 match reader.read_u8()? {
404 0x00 => Ok(Some(reader.read()?)),
405 0x01 => match reader.read_u8()? {
406 0x00 => Ok(None),
407 x => return reader.invalid_leading_byte(x, "number of results"),
408 },
409 x => return reader.invalid_leading_byte(x, "component function results"),
410 }
411}
412
413#[derive(Debug, Clone, PartialEq, Eq)]
415pub struct VariantCase<'a> {
416 pub name: &'a str,
418 pub ty: Option<ComponentValType>,
420 pub refines: Option<u32>,
422}
423
424impl<'a> FromReader<'a> for VariantCase<'a> {
425 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
426 Ok(VariantCase {
427 name: reader.read()?,
428 ty: reader.read()?,
429 refines: match reader.read_u8()? {
430 0x0 => None,
431 0x1 => Some(reader.read_var_u32()?),
432 x => return reader.invalid_leading_byte(x, "variant case refines"),
433 },
434 })
435 }
436}
437
438#[derive(Debug, Clone, PartialEq, Eq)]
440pub enum ComponentDefinedType<'a> {
441 Primitive(PrimitiveValType),
443 Record(Box<[(&'a str, ComponentValType)]>),
445 Variant(Box<[VariantCase<'a>]>),
447 List(ComponentValType),
449 FixedSizeList(ComponentValType, u32),
451 Tuple(Box<[ComponentValType]>),
453 Flags(Box<[&'a str]>),
455 Enum(Box<[&'a str]>),
457 Option(ComponentValType),
459 Result {
461 ok: Option<ComponentValType>,
463 err: Option<ComponentValType>,
465 },
466 Own(u32),
468 Borrow(u32),
470 Future(Option<ComponentValType>),
472 Stream(Option<ComponentValType>),
474}
475
476impl<'a> ComponentDefinedType<'a> {
477 fn read(reader: &mut BinaryReader<'a>, byte: u8) -> Result<ComponentDefinedType<'a>> {
478 Ok(match byte {
479 0x72 => ComponentDefinedType::Record(
480 reader
481 .read_iter(MAX_WASM_RECORD_FIELDS, "record field")?
482 .collect::<Result<_>>()?,
483 ),
484 0x71 => ComponentDefinedType::Variant(
485 reader
486 .read_iter(MAX_WASM_VARIANT_CASES, "variant cases")?
487 .collect::<Result<_>>()?,
488 ),
489 0x70 => ComponentDefinedType::List(reader.read()?),
490 0x6f => ComponentDefinedType::Tuple(
491 reader
492 .read_iter(MAX_WASM_TUPLE_TYPES, "tuple types")?
493 .collect::<Result<_>>()?,
494 ),
495 0x6e => ComponentDefinedType::Flags(
496 reader
497 .read_iter(MAX_WASM_FLAG_NAMES, "flag names")?
498 .collect::<Result<_>>()?,
499 ),
500 0x6d => ComponentDefinedType::Enum(
501 reader
502 .read_iter(MAX_WASM_ENUM_CASES, "enum cases")?
503 .collect::<Result<_>>()?,
504 ),
505 0x6b => ComponentDefinedType::Option(reader.read()?),
507 0x6a => ComponentDefinedType::Result {
508 ok: reader.read()?,
509 err: reader.read()?,
510 },
511 0x69 => ComponentDefinedType::Own(reader.read()?),
512 0x68 => ComponentDefinedType::Borrow(reader.read()?),
513 0x67 => ComponentDefinedType::FixedSizeList(reader.read()?, reader.read_var_u32()?),
514 0x66 => ComponentDefinedType::Stream(reader.read()?),
515 0x65 => ComponentDefinedType::Future(reader.read()?),
516 x => return reader.invalid_leading_byte(x, "component defined type"),
517 })
518 }
519}
520
521pub type ComponentTypeSectionReader<'a> = SectionLimited<'a, ComponentType<'a>>;