1use crate::limits::*;
2use crate::prelude::*;
3use crate::RecGroup;
4use crate::{
5 BinaryReader, ComponentAlias, ComponentExportName, ComponentImport, ComponentTypeRef,
6 FromReader, Import, Result, SectionLimited, TypeRef, ValType,
7};
8use core::fmt;
9
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
12pub enum OuterAliasKind {
13 Type,
15}
16
17#[derive(Debug, Clone, Eq, PartialEq)]
19pub enum CoreType<'a> {
20 Rec(RecGroup),
22 Module(Box<[ModuleTypeDeclaration<'a>]>),
24}
25
26impl<'a> FromReader<'a> for CoreType<'a> {
27 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
28 Ok(match reader.peek()? {
37 0x00 => {
38 reader.read_u8()?;
39 let x = reader.peek()?;
40 if x != 0x50 {
41 return reader.invalid_leading_byte(x, "non-final sub type");
42 }
43 CoreType::Rec(reader.read()?)
44 }
45 0x50 => {
46 reader.read_u8()?;
47 CoreType::Module(
48 reader
49 .read_iter(MAX_WASM_MODULE_TYPE_DECLS, "module type declaration")?
50 .collect::<Result<_>>()?,
51 )
52 }
53 _ => CoreType::Rec(reader.read()?),
54 })
55 }
56}
57
58#[derive(Debug, Clone, Eq, PartialEq)]
60pub enum ModuleTypeDeclaration<'a> {
61 Type(RecGroup),
63 Export {
65 name: &'a str,
67 ty: TypeRef,
69 },
70 OuterAlias {
72 kind: OuterAliasKind,
74 count: u32,
76 index: u32,
78 },
79 Import(Import<'a>),
81}
82
83impl<'a> FromReader<'a> for ModuleTypeDeclaration<'a> {
84 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
85 Ok(match reader.read_u8()? {
86 0x00 => ModuleTypeDeclaration::Import(reader.read()?),
87 0x01 => ModuleTypeDeclaration::Type(reader.read()?),
88 0x02 => {
89 let kind = match reader.read_u8()? {
90 0x10 => OuterAliasKind::Type,
91 x => {
92 return reader.invalid_leading_byte(x, "outer alias kind");
93 }
94 };
95 match reader.read_u8()? {
96 0x01 => ModuleTypeDeclaration::OuterAlias {
97 kind,
98 count: reader.read()?,
99 index: reader.read()?,
100 },
101 x => {
102 return reader.invalid_leading_byte(x, "outer alias target");
103 }
104 }
105 }
106 0x03 => ModuleTypeDeclaration::Export {
107 name: reader.read()?,
108 ty: reader.read()?,
109 },
110 x => return reader.invalid_leading_byte(x, "type definition"),
111 })
112 }
113}
114
115pub type CoreTypeSectionReader<'a> = SectionLimited<'a, CoreType<'a>>;
128
129#[derive(Debug, Clone, Copy, PartialEq, Eq)]
131pub enum ComponentValType {
132 Primitive(PrimitiveValType),
134 Type(u32),
136}
137
138impl<'a> FromReader<'a> for ComponentValType {
139 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
140 if let Some(ty) = PrimitiveValType::from_byte(reader.peek()?) {
141 reader.read_u8()?;
142 return Ok(ComponentValType::Primitive(ty));
143 }
144
145 Ok(ComponentValType::Type(reader.read_var_s33()? as u32))
146 }
147}
148
149impl<'a> FromReader<'a> for Option<ComponentValType> {
150 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
151 match reader.read_u8()? {
152 0x0 => Ok(None),
153 0x1 => Ok(Some(reader.read()?)),
154 x => reader.invalid_leading_byte(x, "optional component value type"),
155 }
156 }
157}
158
159#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161pub enum PrimitiveValType {
162 Bool,
164 S8,
166 U8,
168 S16,
170 U16,
172 S32,
174 U32,
176 S64,
178 U64,
180 F32,
182 F64,
184 Char,
186 String,
188 ErrorContext,
191}
192
193impl PrimitiveValType {
194 fn from_byte(byte: u8) -> Option<PrimitiveValType> {
195 Some(match byte {
196 0x7f => PrimitiveValType::Bool,
197 0x7e => PrimitiveValType::S8,
198 0x7d => PrimitiveValType::U8,
199 0x7c => PrimitiveValType::S16,
200 0x7b => PrimitiveValType::U16,
201 0x7a => PrimitiveValType::S32,
202 0x79 => PrimitiveValType::U32,
203 0x78 => PrimitiveValType::S64,
204 0x77 => PrimitiveValType::U64,
205 0x76 => PrimitiveValType::F32,
206 0x75 => PrimitiveValType::F64,
207 0x74 => PrimitiveValType::Char,
208 0x73 => PrimitiveValType::String,
209 0x64 => PrimitiveValType::ErrorContext,
210 _ => return None,
211 })
212 }
213
214 #[cfg(feature = "validate")]
215 pub(crate) fn contains_ptr(&self) -> bool {
216 matches!(self, Self::String)
217 }
218
219 pub fn is_subtype_of(a: Self, b: Self) -> bool {
221 a == b
228 }
229}
230
231impl fmt::Display for PrimitiveValType {
232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233 use PrimitiveValType::*;
234 let s = match self {
235 Bool => "bool",
236 S8 => "s8",
237 U8 => "u8",
238 S16 => "s16",
239 U16 => "u16",
240 S32 => "s32",
241 U32 => "u32",
242 S64 => "s64",
243 U64 => "u64",
244 F32 => "f32",
245 F64 => "f64",
246 Char => "char",
247 String => "string",
248 ErrorContext => "error-context",
249 };
250 s.fmt(f)
251 }
252}
253
254#[derive(Debug, Clone, Eq, PartialEq)]
256pub enum ComponentType<'a> {
257 Defined(ComponentDefinedType<'a>),
259 Func(ComponentFuncType<'a>),
261 Component(Box<[ComponentTypeDeclaration<'a>]>),
263 Instance(Box<[InstanceTypeDeclaration<'a>]>),
265 Resource {
267 rep: ValType,
269 dtor: Option<u32>,
272 },
273}
274
275impl<'a> FromReader<'a> for ComponentType<'a> {
276 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
277 Ok(match reader.read_u8()? {
278 0x3f => ComponentType::Resource {
279 rep: reader.read()?,
280 dtor: match reader.read_u8()? {
281 0x00 => None,
282 0x01 => Some(reader.read()?),
283 b => return reader.invalid_leading_byte(b, "resource destructor"),
284 },
285 },
286 0x40 => {
287 let params = reader
288 .read_iter(MAX_WASM_FUNCTION_PARAMS, "component function parameters")?
289 .collect::<Result<_>>()?;
290 let result = read_resultlist(reader)?;
291 ComponentType::Func(ComponentFuncType { params, result })
292 }
293 0x41 => ComponentType::Component(
294 reader
295 .read_iter(MAX_WASM_COMPONENT_TYPE_DECLS, "component type declaration")?
296 .collect::<Result<_>>()?,
297 ),
298 0x42 => ComponentType::Instance(
299 reader
300 .read_iter(MAX_WASM_INSTANCE_TYPE_DECLS, "instance type declaration")?
301 .collect::<Result<_>>()?,
302 ),
303 x => {
304 if let Some(ty) = PrimitiveValType::from_byte(x) {
305 ComponentType::Defined(ComponentDefinedType::Primitive(ty))
306 } else {
307 ComponentType::Defined(ComponentDefinedType::read(reader, x)?)
308 }
309 }
310 })
311 }
312}
313
314#[derive(Debug, Clone, Eq, PartialEq)]
316pub enum ComponentTypeDeclaration<'a> {
317 CoreType(CoreType<'a>),
319 Type(ComponentType<'a>),
321 Alias(ComponentAlias<'a>),
323 Export {
325 name: ComponentExportName<'a>,
327 ty: ComponentTypeRef,
329 },
330 Import(ComponentImport<'a>),
332}
333
334impl<'a> FromReader<'a> for ComponentTypeDeclaration<'a> {
335 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
336 if reader.peek()? == 0x03 {
340 reader.read_u8()?;
341 return Ok(ComponentTypeDeclaration::Import(reader.read()?));
342 }
343
344 Ok(match reader.read()? {
345 InstanceTypeDeclaration::CoreType(t) => ComponentTypeDeclaration::CoreType(t),
346 InstanceTypeDeclaration::Type(t) => ComponentTypeDeclaration::Type(t),
347 InstanceTypeDeclaration::Alias(a) => ComponentTypeDeclaration::Alias(a),
348 InstanceTypeDeclaration::Export { name, ty } => {
349 ComponentTypeDeclaration::Export { name, ty }
350 }
351 })
352 }
353}
354
355#[derive(Debug, Clone, Eq, PartialEq)]
357pub enum InstanceTypeDeclaration<'a> {
358 CoreType(CoreType<'a>),
360 Type(ComponentType<'a>),
362 Alias(ComponentAlias<'a>),
364 Export {
366 name: ComponentExportName<'a>,
368 ty: ComponentTypeRef,
370 },
371}
372
373impl<'a> FromReader<'a> for InstanceTypeDeclaration<'a> {
374 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
375 Ok(match reader.read_u8()? {
376 0x00 => InstanceTypeDeclaration::CoreType(reader.read()?),
377 0x01 => InstanceTypeDeclaration::Type(reader.read()?),
378 0x02 => InstanceTypeDeclaration::Alias(reader.read()?),
379 0x04 => InstanceTypeDeclaration::Export {
380 name: reader.read()?,
381 ty: reader.read()?,
382 },
383 x => return reader.invalid_leading_byte(x, "component or instance type declaration"),
384 })
385 }
386}
387
388#[derive(Debug, Clone, Eq, PartialEq)]
390pub struct ComponentFuncType<'a> {
391 pub params: Box<[(&'a str, ComponentValType)]>,
393 pub result: Option<ComponentValType>,
395}
396
397pub(crate) fn read_resultlist(reader: &mut BinaryReader<'_>) -> Result<Option<ComponentValType>> {
398 match reader.read_u8()? {
399 0x00 => Ok(Some(reader.read()?)),
400 0x01 => match reader.read_u8()? {
401 0x00 => Ok(None),
402 x => return reader.invalid_leading_byte(x, "number of results"),
403 },
404 x => return reader.invalid_leading_byte(x, "component function results"),
405 }
406}
407
408#[derive(Debug, Clone, PartialEq, Eq)]
410pub struct VariantCase<'a> {
411 pub name: &'a str,
413 pub ty: Option<ComponentValType>,
415 pub refines: Option<u32>,
417}
418
419impl<'a> FromReader<'a> for VariantCase<'a> {
420 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
421 Ok(VariantCase {
422 name: reader.read()?,
423 ty: reader.read()?,
424 refines: match reader.read_u8()? {
425 0x0 => None,
426 0x1 => Some(reader.read_var_u32()?),
427 x => return reader.invalid_leading_byte(x, "variant case refines"),
428 },
429 })
430 }
431}
432
433#[derive(Debug, Clone, PartialEq, Eq)]
435pub enum ComponentDefinedType<'a> {
436 Primitive(PrimitiveValType),
438 Record(Box<[(&'a str, ComponentValType)]>),
440 Variant(Box<[VariantCase<'a>]>),
442 List(ComponentValType),
444 Tuple(Box<[ComponentValType]>),
446 Flags(Box<[&'a str]>),
448 Enum(Box<[&'a str]>),
450 Option(ComponentValType),
452 Result {
454 ok: Option<ComponentValType>,
456 err: Option<ComponentValType>,
458 },
459 Own(u32),
461 Borrow(u32),
463 Future(Option<ComponentValType>),
465 Stream(Option<ComponentValType>),
467}
468
469impl<'a> ComponentDefinedType<'a> {
470 fn read(reader: &mut BinaryReader<'a>, byte: u8) -> Result<ComponentDefinedType<'a>> {
471 Ok(match byte {
472 0x72 => ComponentDefinedType::Record(
473 reader
474 .read_iter(MAX_WASM_RECORD_FIELDS, "record field")?
475 .collect::<Result<_>>()?,
476 ),
477 0x71 => ComponentDefinedType::Variant(
478 reader
479 .read_iter(MAX_WASM_VARIANT_CASES, "variant cases")?
480 .collect::<Result<_>>()?,
481 ),
482 0x70 => ComponentDefinedType::List(reader.read()?),
483 0x6f => ComponentDefinedType::Tuple(
484 reader
485 .read_iter(MAX_WASM_TUPLE_TYPES, "tuple types")?
486 .collect::<Result<_>>()?,
487 ),
488 0x6e => ComponentDefinedType::Flags(
489 reader
490 .read_iter(MAX_WASM_FLAG_NAMES, "flag names")?
491 .collect::<Result<_>>()?,
492 ),
493 0x6d => ComponentDefinedType::Enum(
494 reader
495 .read_iter(MAX_WASM_ENUM_CASES, "enum cases")?
496 .collect::<Result<_>>()?,
497 ),
498 0x6b => ComponentDefinedType::Option(reader.read()?),
500 0x6a => ComponentDefinedType::Result {
501 ok: reader.read()?,
502 err: reader.read()?,
503 },
504 0x69 => ComponentDefinedType::Own(reader.read()?),
505 0x68 => ComponentDefinedType::Borrow(reader.read()?),
506 0x65 => ComponentDefinedType::Future(reader.read()?),
507 0x66 => ComponentDefinedType::Stream(reader.read()?),
508 x => return reader.invalid_leading_byte(x, "component defined type"),
509 })
510 }
511}
512
513pub type ComponentTypeSectionReader<'a> = SectionLimited<'a, ComponentType<'a>>;