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 0x40 => {
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 { params, result })
291 }
292 0x41 => ComponentType::Component(
293 reader
294 .read_iter(MAX_WASM_COMPONENT_TYPE_DECLS, "component type declaration")?
295 .collect::<Result<_>>()?,
296 ),
297 0x42 => ComponentType::Instance(
298 reader
299 .read_iter(MAX_WASM_INSTANCE_TYPE_DECLS, "instance type declaration")?
300 .collect::<Result<_>>()?,
301 ),
302 x => {
303 if let Some(ty) = PrimitiveValType::from_byte(x) {
304 ComponentType::Defined(ComponentDefinedType::Primitive(ty))
305 } else {
306 ComponentType::Defined(ComponentDefinedType::read(reader, x)?)
307 }
308 }
309 })
310 }
311}
312
313#[derive(Debug, Clone, Eq, PartialEq)]
315pub enum ComponentTypeDeclaration<'a> {
316 CoreType(CoreType<'a>),
318 Type(ComponentType<'a>),
320 Alias(ComponentAlias<'a>),
322 Export {
324 name: ComponentExportName<'a>,
326 ty: ComponentTypeRef,
328 },
329 Import(ComponentImport<'a>),
331}
332
333impl<'a> FromReader<'a> for ComponentTypeDeclaration<'a> {
334 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
335 if reader.peek()? == 0x03 {
339 reader.read_u8()?;
340 return Ok(ComponentTypeDeclaration::Import(reader.read()?));
341 }
342
343 Ok(match reader.read()? {
344 InstanceTypeDeclaration::CoreType(t) => ComponentTypeDeclaration::CoreType(t),
345 InstanceTypeDeclaration::Type(t) => ComponentTypeDeclaration::Type(t),
346 InstanceTypeDeclaration::Alias(a) => ComponentTypeDeclaration::Alias(a),
347 InstanceTypeDeclaration::Export { name, ty } => {
348 ComponentTypeDeclaration::Export { name, ty }
349 }
350 })
351 }
352}
353
354#[derive(Debug, Clone, Eq, PartialEq)]
356pub enum InstanceTypeDeclaration<'a> {
357 CoreType(CoreType<'a>),
359 Type(ComponentType<'a>),
361 Alias(ComponentAlias<'a>),
363 Export {
365 name: ComponentExportName<'a>,
367 ty: ComponentTypeRef,
369 },
370}
371
372impl<'a> FromReader<'a> for InstanceTypeDeclaration<'a> {
373 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
374 Ok(match reader.read_u8()? {
375 0x00 => InstanceTypeDeclaration::CoreType(reader.read()?),
376 0x01 => InstanceTypeDeclaration::Type(reader.read()?),
377 0x02 => InstanceTypeDeclaration::Alias(reader.read()?),
378 0x04 => InstanceTypeDeclaration::Export {
379 name: reader.read()?,
380 ty: reader.read()?,
381 },
382 x => return reader.invalid_leading_byte(x, "component or instance type declaration"),
383 })
384 }
385}
386
387#[derive(Debug, Clone, Eq, PartialEq)]
389pub struct ComponentFuncType<'a> {
390 pub params: Box<[(&'a str, ComponentValType)]>,
392 pub result: Option<ComponentValType>,
394}
395
396pub(crate) fn read_resultlist(reader: &mut BinaryReader<'_>) -> Result<Option<ComponentValType>> {
397 match reader.read_u8()? {
398 0x00 => Ok(Some(reader.read()?)),
399 0x01 => match reader.read_u8()? {
400 0x00 => Ok(None),
401 x => return reader.invalid_leading_byte(x, "number of results"),
402 },
403 x => return reader.invalid_leading_byte(x, "component function results"),
404 }
405}
406
407#[derive(Debug, Clone, PartialEq, Eq)]
409pub struct VariantCase<'a> {
410 pub name: &'a str,
412 pub ty: Option<ComponentValType>,
414 pub refines: Option<u32>,
416}
417
418impl<'a> FromReader<'a> for VariantCase<'a> {
419 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
420 Ok(VariantCase {
421 name: reader.read()?,
422 ty: reader.read()?,
423 refines: match reader.read_u8()? {
424 0x0 => None,
425 0x1 => Some(reader.read_var_u32()?),
426 x => return reader.invalid_leading_byte(x, "variant case refines"),
427 },
428 })
429 }
430}
431
432#[derive(Debug, Clone, PartialEq, Eq)]
434pub enum ComponentDefinedType<'a> {
435 Primitive(PrimitiveValType),
437 Record(Box<[(&'a str, ComponentValType)]>),
439 Variant(Box<[VariantCase<'a>]>),
441 List(ComponentValType),
443 FixedSizeList(ComponentValType, u32),
445 Tuple(Box<[ComponentValType]>),
447 Flags(Box<[&'a str]>),
449 Enum(Box<[&'a str]>),
451 Option(ComponentValType),
453 Result {
455 ok: Option<ComponentValType>,
457 err: Option<ComponentValType>,
459 },
460 Own(u32),
462 Borrow(u32),
464 Future(Option<ComponentValType>),
466 Stream(Option<ComponentValType>),
468}
469
470impl<'a> ComponentDefinedType<'a> {
471 fn read(reader: &mut BinaryReader<'a>, byte: u8) -> Result<ComponentDefinedType<'a>> {
472 Ok(match byte {
473 0x72 => ComponentDefinedType::Record(
474 reader
475 .read_iter(MAX_WASM_RECORD_FIELDS, "record field")?
476 .collect::<Result<_>>()?,
477 ),
478 0x71 => ComponentDefinedType::Variant(
479 reader
480 .read_iter(MAX_WASM_VARIANT_CASES, "variant cases")?
481 .collect::<Result<_>>()?,
482 ),
483 0x70 => ComponentDefinedType::List(reader.read()?),
484 0x6f => ComponentDefinedType::Tuple(
485 reader
486 .read_iter(MAX_WASM_TUPLE_TYPES, "tuple types")?
487 .collect::<Result<_>>()?,
488 ),
489 0x6e => ComponentDefinedType::Flags(
490 reader
491 .read_iter(MAX_WASM_FLAG_NAMES, "flag names")?
492 .collect::<Result<_>>()?,
493 ),
494 0x6d => ComponentDefinedType::Enum(
495 reader
496 .read_iter(MAX_WASM_ENUM_CASES, "enum cases")?
497 .collect::<Result<_>>()?,
498 ),
499 0x6b => ComponentDefinedType::Option(reader.read()?),
501 0x6a => ComponentDefinedType::Result {
502 ok: reader.read()?,
503 err: reader.read()?,
504 },
505 0x69 => ComponentDefinedType::Own(reader.read()?),
506 0x68 => ComponentDefinedType::Borrow(reader.read()?),
507 0x67 => ComponentDefinedType::FixedSizeList(reader.read()?, reader.read_var_u32()?),
508 0x66 => ComponentDefinedType::Stream(reader.read()?),
509 0x65 => ComponentDefinedType::Future(reader.read()?),
510 x => return reader.invalid_leading_byte(x, "component defined type"),
511 })
512 }
513}
514
515pub type ComponentTypeSectionReader<'a> = SectionLimited<'a, ComponentType<'a>>;