wasmparser/validator/
types.rs

1//! Types relating to type information provided by validation.
2
3use super::{component::ComponentState, core::Module};
4use crate::{
5    Export, ExternalKind, FuncType, GlobalType, Import, MemoryType, PrimitiveValType, RefType,
6    TableType, TypeRef, ValType,
7};
8use indexmap::{IndexMap, IndexSet};
9use std::collections::HashMap;
10use std::{
11    borrow::Borrow,
12    fmt,
13    hash::{Hash, Hasher},
14    mem,
15    ops::{Deref, DerefMut},
16    sync::Arc,
17};
18use url::Url;
19
20/// The maximum number of parameters in the canonical ABI that can be passed by value.
21///
22/// Functions that exceed this limit will instead pass parameters indirectly from
23/// linear memory via a single pointer parameter.
24const MAX_FLAT_FUNC_PARAMS: usize = 16;
25/// The maximum number of results in the canonical ABI that can be returned by a function.
26///
27/// Functions that exceed this limit have their results written to linear memory via an
28/// additional pointer parameter (imports) or return a single pointer value (exports).
29const MAX_FLAT_FUNC_RESULTS: usize = 1;
30
31/// The maximum lowered types, including a possible type for a return pointer parameter.
32const MAX_LOWERED_TYPES: usize = MAX_FLAT_FUNC_PARAMS + 1;
33
34/// Represents a kebab string slice used in validation.
35///
36/// This is a wrapper around `str` that ensures the slice is
37/// a valid kebab case string according to the component model
38/// specification.
39///
40/// It also provides an equality and hashing implementation
41/// that ignores ASCII case.
42#[derive(Debug, Eq)]
43#[repr(transparent)]
44pub struct KebabStr(str);
45
46impl KebabStr {
47    /// Creates a new kebab string slice.
48    ///
49    /// Returns `None` if the given string is not a valid kebab string.
50    pub fn new<'a>(s: impl AsRef<str> + 'a) -> Option<&'a Self> {
51        let s = Self::new_unchecked(s);
52        if s.is_kebab_case() {
53            Some(s)
54        } else {
55            None
56        }
57    }
58
59    pub(crate) fn new_unchecked<'a>(s: impl AsRef<str> + 'a) -> &'a Self {
60        // Safety: `KebabStr` is a transparent wrapper around `str`
61        // Therefore transmuting `&str` to `&KebabStr` is safe.
62        unsafe { std::mem::transmute::<_, &Self>(s.as_ref()) }
63    }
64
65    /// Gets the underlying string slice.
66    pub fn as_str(&self) -> &str {
67        &self.0
68    }
69
70    /// Converts the slice to an owned string.
71    pub fn to_kebab_string(&self) -> KebabString {
72        KebabString(self.to_string())
73    }
74
75    fn is_kebab_case(&self) -> bool {
76        let mut lower = false;
77        let mut upper = false;
78        for c in self.chars() {
79            match c {
80                'a'..='z' if !lower && !upper => lower = true,
81                'A'..='Z' if !lower && !upper => upper = true,
82                'a'..='z' if lower => {}
83                'A'..='Z' if upper => {}
84                '0'..='9' if lower || upper => {}
85                '-' if lower || upper => {
86                    lower = false;
87                    upper = false;
88                }
89                _ => return false,
90            }
91        }
92
93        !self.is_empty() && !self.ends_with('-')
94    }
95}
96
97impl Deref for KebabStr {
98    type Target = str;
99
100    fn deref(&self) -> &str {
101        self.as_str()
102    }
103}
104
105impl PartialEq for KebabStr {
106    fn eq(&self, other: &Self) -> bool {
107        if self.len() != other.len() {
108            return false;
109        }
110
111        self.chars()
112            .zip(other.chars())
113            .all(|(a, b)| a.to_ascii_lowercase() == b.to_ascii_lowercase())
114    }
115}
116
117impl PartialEq<KebabString> for KebabStr {
118    fn eq(&self, other: &KebabString) -> bool {
119        self.eq(other.as_kebab_str())
120    }
121}
122
123impl Hash for KebabStr {
124    fn hash<H: Hasher>(&self, state: &mut H) {
125        self.len().hash(state);
126
127        for b in self.chars() {
128            b.to_ascii_lowercase().hash(state);
129        }
130    }
131}
132
133impl fmt::Display for KebabStr {
134    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135        (self as &str).fmt(f)
136    }
137}
138
139impl ToOwned for KebabStr {
140    type Owned = KebabString;
141
142    fn to_owned(&self) -> Self::Owned {
143        self.to_kebab_string()
144    }
145}
146
147/// Represents an owned kebab string for validation.
148///
149/// This is a wrapper around `String` that ensures the string is
150/// a valid kebab case string according to the component model
151/// specification.
152///
153/// It also provides an equality and hashing implementation
154/// that ignores ASCII case.
155#[derive(Debug, Clone, Eq)]
156pub struct KebabString(String);
157
158impl KebabString {
159    /// Creates a new kebab string.
160    ///
161    /// Returns `None` if the given string is not a valid kebab string.
162    pub fn new(s: impl Into<String>) -> Option<Self> {
163        let s = s.into();
164        if KebabStr::new(&s).is_some() {
165            Some(Self(s))
166        } else {
167            None
168        }
169    }
170
171    /// Gets the underlying string.
172    pub fn as_str(&self) -> &str {
173        self.0.as_str()
174    }
175
176    /// Converts the kebab string to a kebab string slice.
177    pub fn as_kebab_str(&self) -> &KebabStr {
178        // Safety: internal string is always valid kebab-case
179        KebabStr::new_unchecked(self.as_str())
180    }
181}
182
183impl Deref for KebabString {
184    type Target = KebabStr;
185
186    fn deref(&self) -> &Self::Target {
187        self.as_kebab_str()
188    }
189}
190
191impl Borrow<KebabStr> for KebabString {
192    fn borrow(&self) -> &KebabStr {
193        self.as_kebab_str()
194    }
195}
196
197impl PartialEq for KebabString {
198    fn eq(&self, other: &Self) -> bool {
199        self.as_kebab_str().eq(other.as_kebab_str())
200    }
201}
202
203impl PartialEq<KebabStr> for KebabString {
204    fn eq(&self, other: &KebabStr) -> bool {
205        self.as_kebab_str().eq(other)
206    }
207}
208
209impl Hash for KebabString {
210    fn hash<H: Hasher>(&self, state: &mut H) {
211        self.as_kebab_str().hash(state)
212    }
213}
214
215impl fmt::Display for KebabString {
216    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217        self.as_kebab_str().fmt(f)
218    }
219}
220
221impl From<KebabString> for String {
222    fn from(s: KebabString) -> String {
223        s.0
224    }
225}
226
227/// A simple alloc-free list of types used for calculating lowered function signatures.
228pub(crate) struct LoweredTypes {
229    types: [ValType; MAX_LOWERED_TYPES],
230    len: usize,
231    max: usize,
232}
233
234impl LoweredTypes {
235    fn new(max: usize) -> Self {
236        assert!(max <= MAX_LOWERED_TYPES);
237        Self {
238            types: [ValType::I32; MAX_LOWERED_TYPES],
239            len: 0,
240            max,
241        }
242    }
243
244    fn len(&self) -> usize {
245        self.len
246    }
247
248    fn maxed(&self) -> bool {
249        self.len == self.max
250    }
251
252    fn get_mut(&mut self, index: usize) -> Option<&mut ValType> {
253        if index < self.len {
254            Some(&mut self.types[index])
255        } else {
256            None
257        }
258    }
259
260    fn push(&mut self, ty: ValType) -> bool {
261        if self.maxed() {
262            return false;
263        }
264
265        self.types[self.len] = ty;
266        self.len += 1;
267        true
268    }
269
270    fn clear(&mut self) {
271        self.len = 0;
272    }
273
274    pub fn as_slice(&self) -> &[ValType] {
275        &self.types[..self.len]
276    }
277
278    pub fn iter(&self) -> impl Iterator<Item = ValType> + '_ {
279        self.as_slice().iter().copied()
280    }
281}
282
283/// Represents information about a component function type lowering.
284pub(crate) struct LoweringInfo {
285    pub(crate) params: LoweredTypes,
286    pub(crate) results: LoweredTypes,
287    pub(crate) requires_memory: bool,
288    pub(crate) requires_realloc: bool,
289}
290
291impl LoweringInfo {
292    pub(crate) fn into_func_type(self) -> FuncType {
293        FuncType::new(
294            self.params.as_slice().iter().copied(),
295            self.results.as_slice().iter().copied(),
296        )
297    }
298}
299
300impl Default for LoweringInfo {
301    fn default() -> Self {
302        Self {
303            params: LoweredTypes::new(MAX_FLAT_FUNC_PARAMS),
304            results: LoweredTypes::new(MAX_FLAT_FUNC_RESULTS),
305            requires_memory: false,
306            requires_realloc: false,
307        }
308    }
309}
310
311fn push_primitive_wasm_types(ty: &PrimitiveValType, lowered_types: &mut LoweredTypes) -> bool {
312    match ty {
313        PrimitiveValType::Bool
314        | PrimitiveValType::S8
315        | PrimitiveValType::U8
316        | PrimitiveValType::S16
317        | PrimitiveValType::U16
318        | PrimitiveValType::S32
319        | PrimitiveValType::U32
320        | PrimitiveValType::Char => lowered_types.push(ValType::I32),
321        PrimitiveValType::S64 | PrimitiveValType::U64 => lowered_types.push(ValType::I64),
322        PrimitiveValType::Float32 => lowered_types.push(ValType::F32),
323        PrimitiveValType::Float64 => lowered_types.push(ValType::F64),
324        PrimitiveValType::String => {
325            lowered_types.push(ValType::I32) && lowered_types.push(ValType::I32)
326        }
327    }
328}
329
330/// Represents a unique identifier for a type known to a [`crate::Validator`].
331#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
332pub struct TypeId {
333    /// The index into the global list of types.
334    pub(crate) index: usize,
335    /// The effective type size for the type.
336    ///
337    /// This is stored as part of the ID to avoid having to recurse through
338    /// the global type list when calculating type sizes.
339    pub(crate) type_size: u32,
340    /// A unique integer assigned to this type.
341    ///
342    /// The purpose of this field is to ensure that two different `TypeId`
343    /// representations can be handed out for two different aliased types within
344    /// a component that actually point to the same underlying type (as pointed
345    /// to by the `index` field).
346    unique_id: u32,
347}
348
349// The size of `TypeId` was seen to have a large-ish impact in #844, so this
350// assert ensures that it stays relatively small.
351const _: () = {
352    assert!(std::mem::size_of::<TypeId>() <= 16);
353};
354
355/// A unified type definition for validating WebAssembly modules and components.
356#[derive(Debug)]
357pub enum Type {
358    /// The definition is for a core function type.
359    Func(FuncType),
360    /// The definition is for a core module type.
361    ///
362    /// This variant is only supported when parsing a component.
363    Module(ModuleType),
364    /// The definition is for a core module instance type.
365    ///
366    /// This variant is only supported when parsing a component.
367    Instance(InstanceType),
368    /// The definition is for a component type.
369    ///
370    /// This variant is only supported when parsing a component.
371    Component(ComponentType),
372    /// The definition is for a component instance type.
373    ///
374    /// This variant is only supported when parsing a component.
375    ComponentInstance(ComponentInstanceType),
376    /// The definition is for a component function type.
377    ///
378    /// This variant is only supported when parsing a component.
379    ComponentFunc(ComponentFuncType),
380    /// The definition is for a component defined type.
381    ///
382    /// This variant is only supported when parsing a component.
383    Defined(ComponentDefinedType),
384}
385
386impl Type {
387    /// Converts the type to a core function type.
388    pub fn as_func_type(&self) -> Option<&FuncType> {
389        match self {
390            Self::Func(ty) => Some(ty),
391            _ => None,
392        }
393    }
394
395    /// Converts the type to a core module type.
396    pub fn as_module_type(&self) -> Option<&ModuleType> {
397        match self {
398            Self::Module(ty) => Some(ty),
399            _ => None,
400        }
401    }
402
403    /// Converts the type to a core module instance type.
404    pub fn as_instance_type(&self) -> Option<&InstanceType> {
405        match self {
406            Self::Instance(ty) => Some(ty),
407            _ => None,
408        }
409    }
410
411    /// Converts the type to a component type.
412    pub fn as_component_type(&self) -> Option<&ComponentType> {
413        match self {
414            Self::Component(ty) => Some(ty),
415            _ => None,
416        }
417    }
418
419    /// Converts the type to a component instance type.
420    pub fn as_component_instance_type(&self) -> Option<&ComponentInstanceType> {
421        match self {
422            Self::ComponentInstance(ty) => Some(ty),
423            _ => None,
424        }
425    }
426
427    /// Converts the type to a component function type.
428    pub fn as_component_func_type(&self) -> Option<&ComponentFuncType> {
429        match self {
430            Self::ComponentFunc(ty) => Some(ty),
431            _ => None,
432        }
433    }
434
435    /// Converts the type to a component defined type.
436    pub fn as_defined_type(&self) -> Option<&ComponentDefinedType> {
437        match self {
438            Self::Defined(ty) => Some(ty),
439            _ => None,
440        }
441    }
442
443    pub(crate) fn type_size(&self) -> u32 {
444        match self {
445            Self::Func(ty) => 1 + (ty.params().len() + ty.results().len()) as u32,
446            Self::Module(ty) => ty.type_size,
447            Self::Instance(ty) => ty.type_size,
448            Self::Component(ty) => ty.type_size,
449            Self::ComponentInstance(ty) => ty.type_size,
450            Self::ComponentFunc(ty) => ty.type_size,
451            Self::Defined(ty) => ty.type_size(),
452        }
453    }
454}
455
456/// A component value type.
457#[derive(Debug, Clone, Copy)]
458pub enum ComponentValType {
459    /// The value type is one of the primitive types.
460    Primitive(PrimitiveValType),
461    /// The type is represented with the given type identifier.
462    Type(TypeId),
463}
464
465impl ComponentValType {
466    pub(crate) fn requires_realloc(&self, types: &TypeList) -> bool {
467        match self {
468            ComponentValType::Primitive(ty) => ty.requires_realloc(),
469            ComponentValType::Type(ty) => types[*ty]
470                .as_defined_type()
471                .unwrap()
472                .requires_realloc(types),
473        }
474    }
475
476    /// Determines if component value type `a` is a subtype of `b`.
477    pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
478        Self::internal_is_subtype_of(a, at.list, b, bt.list)
479    }
480
481    pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
482        match (a, b) {
483            (ComponentValType::Primitive(a), ComponentValType::Primitive(b)) => {
484                PrimitiveValType::is_subtype_of(*a, *b)
485            }
486            (ComponentValType::Type(a), ComponentValType::Type(b)) => {
487                ComponentDefinedType::internal_is_subtype_of(
488                    at[*a].as_defined_type().unwrap(),
489                    at,
490                    bt[*b].as_defined_type().unwrap(),
491                    bt,
492                )
493            }
494            (ComponentValType::Primitive(a), ComponentValType::Type(b)) => {
495                match bt[*b].as_defined_type().unwrap() {
496                    ComponentDefinedType::Primitive(b) => PrimitiveValType::is_subtype_of(*a, *b),
497                    _ => false,
498                }
499            }
500            (ComponentValType::Type(a), ComponentValType::Primitive(b)) => {
501                match at[*a].as_defined_type().unwrap() {
502                    ComponentDefinedType::Primitive(a) => PrimitiveValType::is_subtype_of(*a, *b),
503                    _ => false,
504                }
505            }
506        }
507    }
508
509    fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
510        match self {
511            Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
512            Self::Type(id) => types[*id]
513                .as_defined_type()
514                .unwrap()
515                .push_wasm_types(types, lowered_types),
516        }
517    }
518
519    pub(crate) fn type_size(&self) -> u32 {
520        match self {
521            Self::Primitive(_) => 1,
522            Self::Type(id) => id.type_size,
523        }
524    }
525}
526
527/// The entity type for imports and exports of a module.
528#[derive(Debug, Clone, Copy)]
529pub enum EntityType {
530    /// The entity is a function.
531    Func(TypeId),
532    /// The entity is a table.
533    Table(TableType),
534    /// The entity is a memory.
535    Memory(MemoryType),
536    /// The entity is a global.
537    Global(GlobalType),
538    /// The entity is a tag.
539    Tag(TypeId),
540}
541
542impl EntityType {
543    /// Determines if entity type `a` is a subtype of `b`.
544    pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
545        Self::internal_is_subtype_of(a, at.list, b, bt.list)
546    }
547
548    pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
549        macro_rules! limits_match {
550            ($a:expr, $b:expr) => {{
551                let a = $a;
552                let b = $b;
553                a.initial >= b.initial
554                    && match b.maximum {
555                        Some(b_max) => match a.maximum {
556                            Some(a_max) => a_max <= b_max,
557                            None => false,
558                        },
559                        None => true,
560                    }
561            }};
562        }
563
564        match (a, b) {
565            (EntityType::Func(a), EntityType::Func(b)) => {
566                at[*a].as_func_type().unwrap() == bt[*b].as_func_type().unwrap()
567            }
568            (EntityType::Table(a), EntityType::Table(b)) => {
569                a.element_type == b.element_type && limits_match!(a, b)
570            }
571            (EntityType::Memory(a), EntityType::Memory(b)) => {
572                a.shared == b.shared && a.memory64 == b.memory64 && limits_match!(a, b)
573            }
574            (EntityType::Global(a), EntityType::Global(b)) => a == b,
575            (EntityType::Tag(a), EntityType::Tag(b)) => {
576                at[*a].as_func_type().unwrap() == bt[*b].as_func_type().unwrap()
577            }
578            _ => false,
579        }
580    }
581
582    pub(crate) fn desc(&self) -> &'static str {
583        match self {
584            Self::Func(_) => "function",
585            Self::Table(_) => "table",
586            Self::Memory(_) => "memory",
587            Self::Global(_) => "global",
588            Self::Tag(_) => "tag",
589        }
590    }
591
592    pub(crate) fn type_size(&self) -> u32 {
593        match self {
594            Self::Func(id) | Self::Tag(id) => id.type_size,
595            Self::Table(_) | Self::Memory(_) | Self::Global(_) => 1,
596        }
597    }
598}
599
600trait ModuleImportKey {
601    fn module(&self) -> &str;
602    fn name(&self) -> &str;
603}
604
605impl<'a> Borrow<dyn ModuleImportKey + 'a> for (String, String) {
606    fn borrow(&self) -> &(dyn ModuleImportKey + 'a) {
607        self
608    }
609}
610
611impl Hash for (dyn ModuleImportKey + '_) {
612    fn hash<H: Hasher>(&self, state: &mut H) {
613        self.module().hash(state);
614        self.name().hash(state);
615    }
616}
617
618impl PartialEq for (dyn ModuleImportKey + '_) {
619    fn eq(&self, other: &Self) -> bool {
620        self.module() == other.module() && self.name() == other.name()
621    }
622}
623
624impl Eq for (dyn ModuleImportKey + '_) {}
625
626impl ModuleImportKey for (String, String) {
627    fn module(&self) -> &str {
628        &self.0
629    }
630
631    fn name(&self) -> &str {
632        &self.1
633    }
634}
635
636impl ModuleImportKey for (&str, &str) {
637    fn module(&self) -> &str {
638        self.0
639    }
640
641    fn name(&self) -> &str {
642        self.1
643    }
644}
645
646/// Represents a core module type.
647#[derive(Debug, Clone)]
648pub struct ModuleType {
649    /// The effective type size for the module type.
650    pub(crate) type_size: u32,
651    /// The imports of the module type.
652    pub imports: IndexMap<(String, String), EntityType>,
653    /// The exports of the module type.
654    pub exports: IndexMap<String, EntityType>,
655}
656
657impl ModuleType {
658    /// Looks up an import by its module and name.
659    ///
660    /// Returns `None` if the import was not found.
661    pub fn lookup_import(&self, module: &str, name: &str) -> Option<&EntityType> {
662        self.imports.get(&(module, name) as &dyn ModuleImportKey)
663    }
664
665    /// Determines if module type `a` is a subtype of `b`.
666    pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
667        Self::internal_is_subtype_of(a, at.list, b, bt.list)
668    }
669
670    pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
671        // For module type subtyping, all exports in the other module type
672        // must be present in this module type's exports (i.e. it can export
673        // *more* than what this module type needs).
674        // However, for imports, the check is reversed (i.e. it is okay
675        // to import *less* than what this module type needs).
676        a.imports.iter().all(|(k, a)| match b.imports.get(k) {
677            Some(b) => EntityType::internal_is_subtype_of(b, bt, a, at),
678            None => false,
679        }) && b.exports.iter().all(|(k, b)| match a.exports.get(k) {
680            Some(a) => EntityType::internal_is_subtype_of(a, at, b, bt),
681            None => false,
682        })
683    }
684}
685
686/// Represents the kind of module instance type.
687#[derive(Debug, Clone)]
688pub enum InstanceTypeKind {
689    /// The instance type is the result of instantiating a module type.
690    Instantiated(TypeId),
691    /// The instance type is the result of instantiating from exported items.
692    Exports(IndexMap<String, EntityType>),
693}
694
695/// Represents a module instance type.
696#[derive(Debug, Clone)]
697pub struct InstanceType {
698    /// The effective type size for the module instance type.
699    pub(crate) type_size: u32,
700    /// The kind of module instance type.
701    pub kind: InstanceTypeKind,
702}
703
704impl InstanceType {
705    /// Gets the exports of the instance type.
706    pub fn exports<'a>(&'a self, types: TypesRef<'a>) -> &'a IndexMap<String, EntityType> {
707        self.internal_exports(types.list)
708    }
709
710    pub(crate) fn internal_exports<'a>(
711        &'a self,
712        types: &'a TypeList,
713    ) -> &'a IndexMap<String, EntityType> {
714        match &self.kind {
715            InstanceTypeKind::Instantiated(id) => &types[*id].as_module_type().unwrap().exports,
716            InstanceTypeKind::Exports(exports) => exports,
717        }
718    }
719}
720
721/// The entity type for imports and exports of a component.
722#[derive(Debug, Clone, Copy)]
723pub enum ComponentEntityType {
724    /// The entity is a core module.
725    Module(TypeId),
726    /// The entity is a function.
727    Func(TypeId),
728    /// The entity is a value.
729    Value(ComponentValType),
730    /// The entity is a type.
731    Type {
732        /// This is the identifier of the type that was referenced when this
733        /// entity was created.
734        referenced: TypeId,
735        /// This is the identifier of the type that was created when this type
736        /// was imported or exported from the component.
737        ///
738        /// Note that the underlying type information for the `referenced`
739        /// field and for this `created` field is the same, but these two types
740        /// will hash to different values.
741        created: TypeId,
742    },
743    /// The entity is a component instance.
744    Instance(TypeId),
745    /// The entity is a component.
746    Component(TypeId),
747}
748
749impl ComponentEntityType {
750    /// Determines if component entity type `a` is a subtype of `b`.
751    pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
752        Self::internal_is_subtype_of(a, at.list, b, bt.list)
753    }
754
755    pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
756        match (a, b) {
757            (Self::Module(a), Self::Module(b)) => ModuleType::internal_is_subtype_of(
758                at[*a].as_module_type().unwrap(),
759                at,
760                bt[*b].as_module_type().unwrap(),
761                bt,
762            ),
763            (Self::Func(a), Self::Func(b)) => ComponentFuncType::internal_is_subtype_of(
764                at[*a].as_component_func_type().unwrap(),
765                at,
766                bt[*b].as_component_func_type().unwrap(),
767                bt,
768            ),
769            (Self::Value(a), Self::Value(b)) => {
770                ComponentValType::internal_is_subtype_of(a, at, b, bt)
771            }
772            (Self::Type { referenced: a, .. }, Self::Type { referenced: b, .. }) => {
773                ComponentDefinedType::internal_is_subtype_of(
774                    at[*a].as_defined_type().unwrap(),
775                    at,
776                    bt[*b].as_defined_type().unwrap(),
777                    bt,
778                )
779            }
780            (Self::Instance(a), Self::Instance(b)) => {
781                ComponentInstanceType::internal_is_subtype_of(
782                    at[*a].as_component_instance_type().unwrap(),
783                    at,
784                    bt[*b].as_component_instance_type().unwrap(),
785                    bt,
786                )
787            }
788            (Self::Component(a), Self::Component(b)) => ComponentType::internal_is_subtype_of(
789                at[*a].as_component_type().unwrap(),
790                at,
791                bt[*b].as_component_type().unwrap(),
792                bt,
793            ),
794            _ => false,
795        }
796    }
797
798    pub(crate) fn desc(&self) -> &'static str {
799        match self {
800            Self::Module(_) => "module",
801            Self::Func(_) => "function",
802            Self::Value(_) => "value",
803            Self::Type { .. } => "type",
804            Self::Instance(_) => "instance",
805            Self::Component(_) => "component",
806        }
807    }
808
809    pub(crate) fn type_size(&self) -> u32 {
810        match self {
811            Self::Module(ty)
812            | Self::Func(ty)
813            | Self::Type { referenced: ty, .. }
814            | Self::Instance(ty)
815            | Self::Component(ty) => ty.type_size,
816            Self::Value(ty) => ty.type_size(),
817        }
818    }
819}
820
821/// Represents a type of a component.
822#[derive(Debug, Clone)]
823pub struct ComponentType {
824    /// The effective type size for the component type.
825    pub(crate) type_size: u32,
826    /// The imports of the component type.
827    pub imports: IndexMap<KebabString, (Option<Url>, ComponentEntityType)>,
828    /// The exports of the component type.
829    pub exports: IndexMap<KebabString, (Option<Url>, ComponentEntityType)>,
830}
831
832impl ComponentType {
833    /// Determines if component type `a` is a subtype of `b`.
834    pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
835        Self::internal_is_subtype_of(a, at.list, b, bt.list)
836    }
837
838    pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
839        // For component type subtyping, all exports in the other component type
840        // must be present in this component type's exports (i.e. it can export
841        // *more* than what this component type needs).
842        // However, for imports, the check is reversed (i.e. it is okay
843        // to import *less* than what this component type needs).
844        a.imports.iter().all(|(k, (_, a))| match b.imports.get(k) {
845            Some((_, b)) => ComponentEntityType::internal_is_subtype_of(b, bt, a, at),
846            None => false,
847        }) && b.exports.iter().all(|(k, (_, b))| match a.exports.get(k) {
848            Some((_, a)) => ComponentEntityType::internal_is_subtype_of(a, at, b, bt),
849            None => false,
850        })
851    }
852}
853
854/// Represents the kind of a component instance.
855#[derive(Debug, Clone)]
856pub enum ComponentInstanceTypeKind {
857    /// The instance type is from a definition.
858    Defined(IndexMap<KebabString, (Option<Url>, ComponentEntityType)>),
859    /// The instance type is the result of instantiating a component type.
860    Instantiated(TypeId),
861    /// The instance type is the result of instantiating from exported items.
862    Exports(IndexMap<KebabString, (Option<Url>, ComponentEntityType)>),
863}
864
865/// Represents a type of a component instance.
866#[derive(Debug, Clone)]
867pub struct ComponentInstanceType {
868    /// The effective type size for the instance type.
869    pub(crate) type_size: u32,
870    /// The kind of instance type.
871    pub kind: ComponentInstanceTypeKind,
872}
873
874impl ComponentInstanceType {
875    /// Gets the exports of the instance type.
876    pub fn exports<'a>(
877        &'a self,
878        types: TypesRef<'a>,
879    ) -> impl ExactSizeIterator<Item = (&'a KebabStr, &'a Option<Url>, ComponentEntityType)> + Clone
880    {
881        self.internal_exports(types.list)
882            .iter()
883            .map(|(n, (u, t))| (n.as_kebab_str(), u, *t))
884    }
885
886    pub(crate) fn internal_exports<'a>(
887        &'a self,
888        types: &'a TypeList,
889    ) -> &'a IndexMap<KebabString, (Option<Url>, ComponentEntityType)> {
890        match &self.kind {
891            ComponentInstanceTypeKind::Defined(exports)
892            | ComponentInstanceTypeKind::Exports(exports) => exports,
893            ComponentInstanceTypeKind::Instantiated(id) => {
894                &types[*id].as_component_type().unwrap().exports
895            }
896        }
897    }
898
899    /// Determines if component instance type `a` is a subtype of `b`.
900    pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
901        Self::internal_is_subtype_of(a, at.list, b, bt.list)
902    }
903
904    pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
905        let exports = a.internal_exports(at);
906
907        // For instance type subtyping, all exports in the other instance type
908        // must be present in this instance type's exports (i.e. it can export
909        // *more* than what this instance type needs).
910        b.internal_exports(bt)
911            .iter()
912            .all(|(k, (_, b))| match exports.get(k) {
913                Some((_, a)) => ComponentEntityType::internal_is_subtype_of(a, at, b, bt),
914                None => false,
915            })
916    }
917}
918
919/// Represents a type of a component function.
920#[derive(Debug, Clone)]
921pub struct ComponentFuncType {
922    /// The effective type size for the component function type.
923    pub(crate) type_size: u32,
924    /// The function parameters.
925    pub params: Box<[(KebabString, ComponentValType)]>,
926    /// The function's results.
927    pub results: Box<[(Option<KebabString>, ComponentValType)]>,
928}
929
930impl ComponentFuncType {
931    /// Determines if component function type `a` is a subtype of `b`.
932    pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
933        Self::internal_is_subtype_of(a, at.list, b, bt.list)
934    }
935
936    pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
937        // Note that this intentionally diverges from the upstream specification
938        // in terms of subtyping. This is a full type-equality check which
939        // ensures that the structure of `a` exactly matches the structure of
940        // `b`. The rationale for this is:
941        //
942        // * Primarily in Wasmtime subtyping based on function types is not
943        //   implemented. This includes both subtyping a host import and
944        //   additionally handling subtyping as functions cross component
945        //   boundaries. The host import subtyping (or component export
946        //   subtyping) is not clear how to handle at all at this time. The
947        //   subtyping of functions between components can more easily be
948        //   handled by extending the `fact` compiler, but that hasn't been done
949        //   yet.
950        //
951        // * The upstream specification is currently pretty intentionally vague
952        //   precisely what subtyping is allowed. Implementing a strict check
953        //   here is intended to be a conservative starting point for the
954        //   component model which can be extended in the future if necessary.
955        //
956        // * The interaction with subtyping on bindings generation, for example,
957        //   is a tricky problem that doesn't have a clear answer at this time.
958        //   Effectively this is more rationale for being conservative in the
959        //   first pass of the component model.
960        //
961        // So, in conclusion, the test here (and other places that reference
962        // this comment) is for exact type equality with no differences.
963        a.params.len() == b.params.len()
964            && a.results.len() == b.results.len()
965            && a.params
966                .iter()
967                .zip(b.params.iter())
968                .all(|((an, a), (bn, b))| {
969                    an == bn && ComponentValType::internal_is_subtype_of(a, at, b, bt)
970                })
971            && a.results
972                .iter()
973                .zip(b.results.iter())
974                .all(|((an, a), (bn, b))| {
975                    an == bn && ComponentValType::internal_is_subtype_of(a, at, b, bt)
976                })
977    }
978
979    /// Lowers the component function type to core parameter and result types for the
980    /// canonical ABI.
981    pub(crate) fn lower(&self, types: &TypeList, import: bool) -> LoweringInfo {
982        let mut info = LoweringInfo::default();
983
984        for (_, ty) in self.params.iter() {
985            // When `import` is false, it means we're lifting a core function,
986            // check if the parameters needs realloc
987            if !import && !info.requires_realloc {
988                info.requires_realloc = ty.requires_realloc(types);
989            }
990
991            if !ty.push_wasm_types(types, &mut info.params) {
992                // Too many parameters to pass directly
993                // Function will have a single pointer parameter to pass the arguments
994                // via linear memory
995                info.params.clear();
996                assert!(info.params.push(ValType::I32));
997                info.requires_memory = true;
998
999                // We need realloc as well when lifting a function
1000                if !import {
1001                    info.requires_realloc = true;
1002                }
1003                break;
1004            }
1005        }
1006
1007        for (_, ty) in self.results.iter() {
1008            // When `import` is true, it means we're lowering a component function,
1009            // check if the result needs realloc
1010            if import && !info.requires_realloc {
1011                info.requires_realloc = ty.requires_realloc(types);
1012            }
1013
1014            if !ty.push_wasm_types(types, &mut info.results) {
1015                // Too many results to return directly, either a retptr parameter will be used (import)
1016                // or a single pointer will be returned (export)
1017                info.results.clear();
1018                if import {
1019                    info.params.max = MAX_LOWERED_TYPES;
1020                    assert!(info.params.push(ValType::I32));
1021                } else {
1022                    assert!(info.results.push(ValType::I32));
1023                }
1024                info.requires_memory = true;
1025                break;
1026            }
1027        }
1028
1029        // Memory is always required when realloc is required
1030        info.requires_memory |= info.requires_realloc;
1031
1032        info
1033    }
1034}
1035
1036/// Represents a variant case.
1037#[derive(Debug, Clone)]
1038pub struct VariantCase {
1039    /// The variant case type.
1040    pub ty: Option<ComponentValType>,
1041    /// The name of the variant case refined by this one.
1042    pub refines: Option<KebabString>,
1043}
1044
1045/// Represents a record type.
1046#[derive(Debug, Clone)]
1047pub struct RecordType {
1048    /// The effective type size for the record type.
1049    pub(crate) type_size: u32,
1050    /// The map of record fields.
1051    pub fields: IndexMap<KebabString, ComponentValType>,
1052}
1053
1054/// Represents a variant type.
1055#[derive(Debug, Clone)]
1056pub struct VariantType {
1057    /// The effective type size for the variant type.
1058    pub(crate) type_size: u32,
1059    /// The map of variant cases.
1060    pub cases: IndexMap<KebabString, VariantCase>,
1061}
1062
1063/// Represents a tuple type.
1064#[derive(Debug, Clone)]
1065pub struct TupleType {
1066    /// The effective type size for the tuple type.
1067    pub(crate) type_size: u32,
1068    /// The types of the tuple.
1069    pub types: Box<[ComponentValType]>,
1070}
1071
1072/// Represents a union type.
1073#[derive(Debug, Clone)]
1074pub struct UnionType {
1075    /// The inclusive type count for the union type.
1076    pub(crate) type_size: u32,
1077    /// The types of the union.
1078    pub types: Box<[ComponentValType]>,
1079}
1080
1081/// Represents a component defined type.
1082#[derive(Debug, Clone)]
1083pub enum ComponentDefinedType {
1084    /// The type is a primitive value type.
1085    Primitive(PrimitiveValType),
1086    /// The type is a record.
1087    Record(RecordType),
1088    /// The type is a variant.
1089    Variant(VariantType),
1090    /// The type is a list.
1091    List(ComponentValType),
1092    /// The type is a tuple.
1093    Tuple(TupleType),
1094    /// The type is a set of flags.
1095    Flags(IndexSet<KebabString>),
1096    /// The type is an enumeration.
1097    Enum(IndexSet<KebabString>),
1098    /// The type is a union.
1099    Union(UnionType),
1100    /// The type is an `option`.
1101    Option(ComponentValType),
1102    /// The type is a `result`.
1103    Result {
1104        /// The `ok` type.
1105        ok: Option<ComponentValType>,
1106        /// The `error` type.
1107        err: Option<ComponentValType>,
1108    },
1109}
1110
1111impl ComponentDefinedType {
1112    pub(crate) fn requires_realloc(&self, types: &TypeList) -> bool {
1113        match self {
1114            Self::Primitive(ty) => ty.requires_realloc(),
1115            Self::Record(r) => r.fields.values().any(|ty| ty.requires_realloc(types)),
1116            Self::Variant(v) => v.cases.values().any(|case| {
1117                case.ty
1118                    .map(|ty| ty.requires_realloc(types))
1119                    .unwrap_or(false)
1120            }),
1121            Self::List(_) => true,
1122            Self::Tuple(t) => t.types.iter().any(|ty| ty.requires_realloc(types)),
1123            Self::Union(u) => u.types.iter().any(|ty| ty.requires_realloc(types)),
1124            Self::Flags(_) | Self::Enum(_) => false,
1125            Self::Option(ty) => ty.requires_realloc(types),
1126            Self::Result { ok, err } => {
1127                ok.map(|ty| ty.requires_realloc(types)).unwrap_or(false)
1128                    || err.map(|ty| ty.requires_realloc(types)).unwrap_or(false)
1129            }
1130        }
1131    }
1132
1133    /// Determines if component defined type `a` is a subtype of `b`.
1134    pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
1135        Self::internal_is_subtype_of(a, at.list, b, bt.list)
1136    }
1137
1138    pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
1139        // Note that the implementation of subtyping here diverges from the
1140        // upstream specification intentionally, see the documentation on
1141        // function subtyping for more information.
1142        match (a, b) {
1143            (Self::Primitive(a), Self::Primitive(b)) => PrimitiveValType::is_subtype_of(*a, *b),
1144            (Self::Record(a), Self::Record(b)) => {
1145                a.fields.len() == b.fields.len()
1146                    && a.fields
1147                        .iter()
1148                        .zip(b.fields.iter())
1149                        .all(|((aname, a), (bname, b))| {
1150                            aname == bname && ComponentValType::internal_is_subtype_of(a, at, b, bt)
1151                        })
1152            }
1153            (Self::Variant(a), Self::Variant(b)) => {
1154                a.cases.len() == b.cases.len()
1155                    && a.cases
1156                        .iter()
1157                        .zip(b.cases.iter())
1158                        .all(|((aname, a), (bname, b))| {
1159                            aname == bname
1160                                && match (&a.ty, &b.ty) {
1161                                    (Some(a), Some(b)) => {
1162                                        ComponentValType::internal_is_subtype_of(a, at, b, bt)
1163                                    }
1164                                    (None, None) => true,
1165                                    _ => false,
1166                                }
1167                        })
1168            }
1169            (Self::List(a), Self::List(b)) | (Self::Option(a), Self::Option(b)) => {
1170                ComponentValType::internal_is_subtype_of(a, at, b, bt)
1171            }
1172            (Self::Tuple(a), Self::Tuple(b)) => {
1173                if a.types.len() != b.types.len() {
1174                    return false;
1175                }
1176                a.types
1177                    .iter()
1178                    .zip(b.types.iter())
1179                    .all(|(a, b)| ComponentValType::internal_is_subtype_of(a, at, b, bt))
1180            }
1181            (Self::Union(a), Self::Union(b)) => {
1182                if a.types.len() != b.types.len() {
1183                    return false;
1184                }
1185                a.types
1186                    .iter()
1187                    .zip(b.types.iter())
1188                    .all(|(a, b)| ComponentValType::internal_is_subtype_of(a, at, b, bt))
1189            }
1190            (Self::Flags(a), Self::Flags(b)) | (Self::Enum(a), Self::Enum(b)) => {
1191                a.len() == b.len() && a.iter().eq(b.iter())
1192            }
1193            (Self::Result { ok: ao, err: ae }, Self::Result { ok: bo, err: be }) => {
1194                Self::is_optional_subtype_of(*ao, at, *bo, bt)
1195                    && Self::is_optional_subtype_of(*ae, at, *be, bt)
1196            }
1197            _ => false,
1198        }
1199    }
1200
1201    pub(crate) fn type_size(&self) -> u32 {
1202        match self {
1203            Self::Primitive(_) => 1,
1204            Self::Flags(_) | Self::Enum(_) => 1,
1205            Self::Record(r) => r.type_size,
1206            Self::Variant(v) => v.type_size,
1207            Self::Tuple(t) => t.type_size,
1208            Self::Union(u) => u.type_size,
1209            Self::List(ty) | Self::Option(ty) => ty.type_size(),
1210            Self::Result { ok, err } => {
1211                ok.map(|ty| ty.type_size()).unwrap_or(1) + err.map(|ty| ty.type_size()).unwrap_or(1)
1212            }
1213        }
1214    }
1215
1216    fn is_optional_subtype_of(
1217        a: Option<ComponentValType>,
1218        at: &TypeList,
1219        b: Option<ComponentValType>,
1220        bt: &TypeList,
1221    ) -> bool {
1222        match (a, b) {
1223            (None, None) => true,
1224            (Some(a), Some(b)) => ComponentValType::internal_is_subtype_of(&a, at, &b, bt),
1225            _ => false,
1226        }
1227    }
1228    fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
1229        match self {
1230            Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
1231            Self::Record(r) => r
1232                .fields
1233                .iter()
1234                .all(|(_, ty)| ty.push_wasm_types(types, lowered_types)),
1235            Self::Variant(v) => Self::push_variant_wasm_types(
1236                v.cases.iter().filter_map(|(_, case)| case.ty.as_ref()),
1237                types,
1238                lowered_types,
1239            ),
1240            Self::List(_) => lowered_types.push(ValType::I32) && lowered_types.push(ValType::I32),
1241            Self::Tuple(t) => t
1242                .types
1243                .iter()
1244                .all(|ty| ty.push_wasm_types(types, lowered_types)),
1245            Self::Flags(names) => {
1246                (0..(names.len() + 31) / 32).all(|_| lowered_types.push(ValType::I32))
1247            }
1248            Self::Enum(_) => lowered_types.push(ValType::I32),
1249            Self::Union(u) => Self::push_variant_wasm_types(u.types.iter(), types, lowered_types),
1250            Self::Option(ty) => {
1251                Self::push_variant_wasm_types([ty].into_iter(), types, lowered_types)
1252            }
1253            Self::Result { ok, err } => {
1254                Self::push_variant_wasm_types(ok.iter().chain(err.iter()), types, lowered_types)
1255            }
1256        }
1257    }
1258
1259    fn push_variant_wasm_types<'a>(
1260        cases: impl Iterator<Item = &'a ComponentValType>,
1261        types: &TypeList,
1262        lowered_types: &mut LoweredTypes,
1263    ) -> bool {
1264        // Push the discriminant
1265        if !lowered_types.push(ValType::I32) {
1266            return false;
1267        }
1268
1269        let start = lowered_types.len();
1270
1271        for ty in cases {
1272            let mut temp = LoweredTypes::new(lowered_types.max);
1273
1274            if !ty.push_wasm_types(types, &mut temp) {
1275                return false;
1276            }
1277
1278            for (i, ty) in temp.iter().enumerate() {
1279                match lowered_types.get_mut(start + i) {
1280                    Some(prev) => *prev = Self::join_types(*prev, ty),
1281                    None => {
1282                        if !lowered_types.push(ty) {
1283                            return false;
1284                        }
1285                    }
1286                }
1287            }
1288        }
1289
1290        true
1291    }
1292
1293    fn join_types(a: ValType, b: ValType) -> ValType {
1294        use ValType::*;
1295
1296        match (a, b) {
1297            (I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => a,
1298            (I32, F32) | (F32, I32) => I32,
1299            (_, I64 | F64) | (I64 | F64, _) => I64,
1300            _ => panic!("unexpected wasm type for canonical ABI"),
1301        }
1302    }
1303}
1304
1305#[allow(clippy::large_enum_variant)]
1306enum TypesKind {
1307    Module(Arc<Module>),
1308    Component(ComponentState),
1309}
1310
1311/// Represents the types known to a [`crate::Validator`] once validation has completed.
1312///
1313/// The type information is returned via the [`crate::Validator::end`] method.
1314pub struct Types {
1315    list: TypeList,
1316    kind: TypesKind,
1317}
1318
1319#[derive(Clone, Copy)]
1320enum TypesRefKind<'a> {
1321    Module(&'a Module),
1322    Component(&'a ComponentState),
1323}
1324
1325/// Represents the types known to a [`crate::Validator`] during validation.
1326///
1327/// Retrieved via the [`crate::Validator::types`] method.
1328#[derive(Clone, Copy)]
1329pub struct TypesRef<'a> {
1330    list: &'a TypeList,
1331    kind: TypesRefKind<'a>,
1332}
1333
1334impl<'a> TypesRef<'a> {
1335    pub(crate) fn from_module(types: &'a TypeList, module: &'a Module) -> Self {
1336        Self {
1337            list: types,
1338            kind: TypesRefKind::Module(module),
1339        }
1340    }
1341
1342    pub(crate) fn from_component(types: &'a TypeList, component: &'a ComponentState) -> Self {
1343        Self {
1344            list: types,
1345            kind: TypesRefKind::Component(component),
1346        }
1347    }
1348
1349    fn types(&self, core: bool) -> Option<&'a [TypeId]> {
1350        Some(match &self.kind {
1351            TypesRefKind::Module(module) => {
1352                if core {
1353                    &module.types
1354                } else {
1355                    return None;
1356                }
1357            }
1358            TypesRefKind::Component(component) => {
1359                if core {
1360                    &component.core_types
1361                } else {
1362                    &component.types
1363                }
1364            }
1365        })
1366    }
1367
1368    /// Gets a type based on its type id.
1369    ///
1370    /// Returns `None` if the type id is unknown.
1371    pub fn type_from_id(&self, id: TypeId) -> Option<&'a Type> {
1372        self.list.get(id.index)
1373    }
1374
1375    /// Gets a type id from a type index.
1376    ///
1377    /// Returns `None` if the type index is out of bounds or the type has not
1378    /// been parsed yet.
1379    pub fn id_from_type_index(&self, index: u32, core: bool) -> Option<TypeId> {
1380        self.types(core)?.get(index as usize).copied()
1381    }
1382
1383    /// Gets a type at the given type index.
1384    ///
1385    /// Returns `None` if the type index is out of bounds or the type has not
1386    /// been parsed yet.
1387    pub fn type_at(&self, index: u32, core: bool) -> Option<&'a Type> {
1388        self.type_from_id(*self.types(core)?.get(index as usize)?)
1389    }
1390
1391    /// Gets a defined core function type at the given type index.
1392    ///
1393    /// Returns `None` if the type index is out of bounds or the type has not
1394    /// been parsed yet.
1395    pub fn func_type_at(&self, index: u32) -> Option<&'a FuncType> {
1396        match self.type_at(index, true)? {
1397            Type::Func(ty) => Some(ty),
1398            _ => None,
1399        }
1400    }
1401
1402    /// Gets the type of a table at the given table index.
1403    ///
1404    /// Returns `None` if the type index is out of bounds or the type has not
1405    /// been parsed yet.
1406    pub fn table_at(&self, index: u32) -> Option<TableType> {
1407        let tables = match &self.kind {
1408            TypesRefKind::Module(module) => &module.tables,
1409            TypesRefKind::Component(component) => &component.core_tables,
1410        };
1411
1412        tables.get(index as usize).copied()
1413    }
1414
1415    /// Gets the type of a memory at the given memory index.
1416    ///
1417    /// Returns `None` if the type index is out of bounds or the type has not
1418    /// been parsed yet.
1419    pub fn memory_at(&self, index: u32) -> Option<MemoryType> {
1420        let memories = match &self.kind {
1421            TypesRefKind::Module(module) => &module.memories,
1422            TypesRefKind::Component(component) => &component.core_memories,
1423        };
1424
1425        memories.get(index as usize).copied()
1426    }
1427
1428    /// Gets the type of a global at the given global index.
1429    ///
1430    /// Returns `None` if the type index is out of bounds or the type has not
1431    /// been parsed yet.
1432    pub fn global_at(&self, index: u32) -> Option<GlobalType> {
1433        let globals = match &self.kind {
1434            TypesRefKind::Module(module) => &module.globals,
1435            TypesRefKind::Component(component) => &component.core_globals,
1436        };
1437
1438        globals.get(index as usize).copied()
1439    }
1440
1441    /// Gets the type of a tag at the given tag index.
1442    ///
1443    /// Returns `None` if the type index is out of bounds or the type has not
1444    /// been parsed yet.
1445    pub fn tag_at(&self, index: u32) -> Option<&'a FuncType> {
1446        let tags = match &self.kind {
1447            TypesRefKind::Module(module) => &module.tags,
1448            TypesRefKind::Component(component) => &component.core_tags,
1449        };
1450
1451        Some(
1452            self.list[*tags.get(index as usize)?]
1453                .as_func_type()
1454                .unwrap(),
1455        )
1456    }
1457
1458    /// Gets the type of a core function at the given function index.
1459    ///
1460    /// Returns `None` if the type index is out of bounds or the type has not
1461    /// been parsed yet.
1462    pub fn function_at(&self, index: u32) -> Option<&'a FuncType> {
1463        let id = match &self.kind {
1464            TypesRefKind::Module(module) => {
1465                &module.types[*module.functions.get(index as usize)? as usize]
1466            }
1467            TypesRefKind::Component(component) => component.core_funcs.get(index as usize)?,
1468        };
1469
1470        match &self.list[*id] {
1471            Type::Func(ty) => Some(ty),
1472            _ => None,
1473        }
1474    }
1475
1476    /// Gets the type of an element segment at the given element segment index.
1477    ///
1478    /// Returns `None` if the type index is out of bounds or the type has not
1479    /// been parsed yet.
1480    pub fn element_at(&self, index: u32) -> Option<RefType> {
1481        match &self.kind {
1482            TypesRefKind::Module(module) => module.element_types.get(index as usize).copied(),
1483            TypesRefKind::Component(_) => None,
1484        }
1485    }
1486
1487    /// Gets the type of a component function at the given function index.
1488    ///
1489    /// Returns `None` if the type index is out of bounds or the type has not
1490    /// been parsed yet.
1491    pub fn component_function_at(&self, index: u32) -> Option<&'a ComponentFuncType> {
1492        match &self.kind {
1493            TypesRefKind::Module(_) => None,
1494            TypesRefKind::Component(component) => Some(
1495                self.list[*component.funcs.get(index as usize)?]
1496                    .as_component_func_type()
1497                    .unwrap(),
1498            ),
1499        }
1500    }
1501
1502    /// Gets the type of a module at the given module index.
1503    ///
1504    /// Returns `None` if the type index is out of bounds or the type has not
1505    /// been parsed yet.
1506    pub fn module_at(&self, index: u32) -> Option<&'a ModuleType> {
1507        match &self.kind {
1508            TypesRefKind::Module(_) => None,
1509            TypesRefKind::Component(component) => Some(
1510                self.list[*component.core_modules.get(index as usize)?]
1511                    .as_module_type()
1512                    .unwrap(),
1513            ),
1514        }
1515    }
1516
1517    /// Gets the type of a module instance at the given module instance index.
1518    ///
1519    /// Returns `None` if the type index is out of bounds or the type has not
1520    /// been parsed yet.
1521    pub fn instance_at(&self, index: u32) -> Option<&'a InstanceType> {
1522        match &self.kind {
1523            TypesRefKind::Module(_) => None,
1524            TypesRefKind::Component(component) => {
1525                let id = component.core_instances.get(index as usize)?;
1526                match &self.list[*id] {
1527                    Type::Instance(ty) => Some(ty),
1528                    _ => None,
1529                }
1530            }
1531        }
1532    }
1533
1534    /// Gets the type of a component at the given component index.
1535    ///
1536    /// Returns `None` if the type index is out of bounds or the type has not
1537    /// been parsed yet.
1538    pub fn component_at(&self, index: u32) -> Option<&'a ComponentType> {
1539        match &self.kind {
1540            TypesRefKind::Module(_) => None,
1541            TypesRefKind::Component(component) => Some(
1542                self.list[*component.components.get(index as usize)?]
1543                    .as_component_type()
1544                    .unwrap(),
1545            ),
1546        }
1547    }
1548
1549    /// Gets the type of an component instance at the given component instance index.
1550    ///
1551    /// Returns `None` if the type index is out of bounds or the type has not
1552    /// been parsed yet.
1553    pub fn component_instance_at(&self, index: u32) -> Option<&'a ComponentInstanceType> {
1554        match &self.kind {
1555            TypesRefKind::Module(_) => None,
1556            TypesRefKind::Component(component) => {
1557                let id = component.instances.get(index as usize)?;
1558                match &self.list[*id] {
1559                    Type::ComponentInstance(ty) => Some(ty),
1560                    _ => None,
1561                }
1562            }
1563        }
1564    }
1565
1566    /// Gets the type of a value at the given value index.
1567    ///
1568    /// Returns `None` if the type index is out of bounds or the type has not
1569    /// been parsed yet.
1570    pub fn value_at(&self, index: u32) -> Option<ComponentValType> {
1571        match &self.kind {
1572            TypesRefKind::Module(_) => None,
1573            TypesRefKind::Component(component) => {
1574                component.values.get(index as usize).map(|(r, _)| *r)
1575            }
1576        }
1577    }
1578
1579    /// Gets the entity type for the given import.
1580    pub fn entity_type_from_import(&self, import: &Import) -> Option<EntityType> {
1581        match &self.kind {
1582            TypesRefKind::Module(module) => Some(match import.ty {
1583                TypeRef::Func(idx) => EntityType::Func(*module.types.get(idx as usize)?),
1584                TypeRef::Table(ty) => EntityType::Table(ty),
1585                TypeRef::Memory(ty) => EntityType::Memory(ty),
1586                TypeRef::Global(ty) => EntityType::Global(ty),
1587                TypeRef::Tag(ty) => EntityType::Tag(*module.types.get(ty.func_type_idx as usize)?),
1588            }),
1589            TypesRefKind::Component(_) => None,
1590        }
1591    }
1592
1593    /// Gets the entity type from the given export.
1594    pub fn entity_type_from_export(&self, export: &Export) -> Option<EntityType> {
1595        match &self.kind {
1596            TypesRefKind::Module(module) => Some(match export.kind {
1597                ExternalKind::Func => EntityType::Func(
1598                    module.types[*module.functions.get(export.index as usize)? as usize],
1599                ),
1600                ExternalKind::Table => {
1601                    EntityType::Table(*module.tables.get(export.index as usize)?)
1602                }
1603                ExternalKind::Memory => {
1604                    EntityType::Memory(*module.memories.get(export.index as usize)?)
1605                }
1606                ExternalKind::Global => {
1607                    EntityType::Global(*module.globals.get(export.index as usize)?)
1608                }
1609                ExternalKind::Tag => EntityType::Tag(
1610                    module.types[*module.functions.get(export.index as usize)? as usize],
1611                ),
1612            }),
1613            TypesRefKind::Component(_) => None,
1614        }
1615    }
1616
1617    /// Gets the component entity type for the given component import.
1618    pub fn component_entity_type_of_extern(&self, name: &str) -> Option<ComponentEntityType> {
1619        match &self.kind {
1620            TypesRefKind::Module(_) => None,
1621            TypesRefKind::Component(component) => {
1622                let key = KebabStr::new(name)?;
1623                Some(component.externs.get(key)?.1)
1624            }
1625        }
1626    }
1627}
1628
1629impl Types {
1630    pub(crate) fn from_module(types: TypeList, module: Arc<Module>) -> Self {
1631        Self {
1632            list: types,
1633            kind: TypesKind::Module(module),
1634        }
1635    }
1636
1637    pub(crate) fn from_component(types: TypeList, component: ComponentState) -> Self {
1638        Self {
1639            list: types,
1640            kind: TypesKind::Component(component),
1641        }
1642    }
1643
1644    /// Gets a reference to this validation type information.
1645    pub fn as_ref(&self) -> TypesRef {
1646        TypesRef {
1647            list: &self.list,
1648            kind: match &self.kind {
1649                TypesKind::Module(module) => TypesRefKind::Module(module),
1650                TypesKind::Component(component) => TypesRefKind::Component(component),
1651            },
1652        }
1653    }
1654
1655    /// Gets a type based on its type id.
1656    ///
1657    /// Returns `None` if the type id is unknown.
1658    pub fn type_from_id(&self, id: TypeId) -> Option<&Type> {
1659        self.as_ref().type_from_id(id)
1660    }
1661
1662    /// Gets a type id from a type index.
1663    ///
1664    /// Returns `None` if the type index is out of bounds.
1665    pub fn id_from_type_index(&self, index: u32, core: bool) -> Option<TypeId> {
1666        self.as_ref().id_from_type_index(index, core)
1667    }
1668
1669    /// Gets a type at the given type index.
1670    ///
1671    /// Returns `None` if the index is out of bounds.
1672    pub fn type_at(&self, index: u32, core: bool) -> Option<&Type> {
1673        self.as_ref().type_at(index, core)
1674    }
1675
1676    /// Gets a defined core function type at the given type index.
1677    ///
1678    /// Returns `None` if the index is out of bounds.
1679    pub fn func_type_at(&self, index: u32) -> Option<&FuncType> {
1680        self.as_ref().func_type_at(index)
1681    }
1682
1683    /// Gets the count of core types.
1684    pub fn type_count(&self) -> usize {
1685        match &self.kind {
1686            TypesKind::Module(module) => module.types.len(),
1687            TypesKind::Component(component) => component.core_types.len(),
1688        }
1689    }
1690
1691    /// Gets the type of a table at the given table index.
1692    ///
1693    /// Returns `None` if the index is out of bounds.
1694    pub fn table_at(&self, index: u32) -> Option<TableType> {
1695        self.as_ref().table_at(index)
1696    }
1697
1698    /// Gets the count of imported and defined tables.
1699    pub fn table_count(&self) -> usize {
1700        match &self.kind {
1701            TypesKind::Module(module) => module.tables.len(),
1702            TypesKind::Component(component) => component.core_tables.len(),
1703        }
1704    }
1705
1706    /// Gets the type of a memory at the given memory index.
1707    ///
1708    /// Returns `None` if the index is out of bounds.
1709    pub fn memory_at(&self, index: u32) -> Option<MemoryType> {
1710        self.as_ref().memory_at(index)
1711    }
1712
1713    /// Gets the count of imported and defined memories.
1714    pub fn memory_count(&self) -> usize {
1715        match &self.kind {
1716            TypesKind::Module(module) => module.memories.len(),
1717            TypesKind::Component(component) => component.core_memories.len(),
1718        }
1719    }
1720
1721    /// Gets the type of a global at the given global index.
1722    ///
1723    /// Returns `None` if the index is out of bounds.
1724    pub fn global_at(&self, index: u32) -> Option<GlobalType> {
1725        self.as_ref().global_at(index)
1726    }
1727
1728    /// Gets the count of imported and defined globals.
1729    pub fn global_count(&self) -> usize {
1730        match &self.kind {
1731            TypesKind::Module(module) => module.globals.len(),
1732            TypesKind::Component(component) => component.core_globals.len(),
1733        }
1734    }
1735
1736    /// Gets the type of a tag at the given tag index.
1737    ///
1738    /// Returns `None` if the index is out of bounds.
1739    pub fn tag_at(&self, index: u32) -> Option<&FuncType> {
1740        self.as_ref().tag_at(index)
1741    }
1742
1743    /// Gets the count of imported and defined tags.
1744    pub fn tag_count(&self) -> usize {
1745        match &self.kind {
1746            TypesKind::Module(module) => module.tags.len(),
1747            TypesKind::Component(component) => component.core_tags.len(),
1748        }
1749    }
1750
1751    /// Gets the type of a core function at the given function index.
1752    ///
1753    /// Returns `None` if the index is out of bounds.
1754    pub fn function_at(&self, index: u32) -> Option<&FuncType> {
1755        self.as_ref().function_at(index)
1756    }
1757
1758    /// Gets the count of imported and defined core functions.
1759    ///
1760    /// The count also includes aliased core functions in components.
1761    pub fn function_count(&self) -> usize {
1762        match &self.kind {
1763            TypesKind::Module(module) => module.functions.len(),
1764            TypesKind::Component(component) => component.core_funcs.len(),
1765        }
1766    }
1767
1768    /// Gets the type of an element segment at the given element segment index.
1769    ///
1770    /// Returns `None` if the index is out of bounds.
1771    pub fn element_at(&self, index: u32) -> Option<RefType> {
1772        match &self.kind {
1773            TypesKind::Module(module) => module.element_types.get(index as usize).copied(),
1774            TypesKind::Component(_) => None,
1775        }
1776    }
1777
1778    /// Gets the count of element segments.
1779    pub fn element_count(&self) -> usize {
1780        match &self.kind {
1781            TypesKind::Module(module) => module.element_types.len(),
1782            TypesKind::Component(_) => 0,
1783        }
1784    }
1785
1786    /// Gets the type of a component function at the given function index.
1787    ///
1788    /// Returns `None` if the index is out of bounds.
1789    pub fn component_function_at(&self, index: u32) -> Option<&ComponentFuncType> {
1790        self.as_ref().component_function_at(index)
1791    }
1792
1793    /// Gets the count of imported, exported, or aliased component functions.
1794    pub fn component_function_count(&self) -> usize {
1795        match &self.kind {
1796            TypesKind::Module(_) => 0,
1797            TypesKind::Component(component) => component.funcs.len(),
1798        }
1799    }
1800
1801    /// Gets the type of a module at the given module index.
1802    ///
1803    /// Returns `None` if the index is out of bounds.
1804    pub fn module_at(&self, index: u32) -> Option<&ModuleType> {
1805        self.as_ref().module_at(index)
1806    }
1807
1808    /// Gets the count of imported, exported, or aliased modules.
1809    pub fn module_count(&self) -> usize {
1810        match &self.kind {
1811            TypesKind::Module(_) => 0,
1812            TypesKind::Component(component) => component.core_modules.len(),
1813        }
1814    }
1815
1816    /// Gets the type of a module instance at the given module instance index.
1817    ///
1818    /// Returns `None` if the index is out of bounds.
1819    pub fn instance_at(&self, index: u32) -> Option<&InstanceType> {
1820        self.as_ref().instance_at(index)
1821    }
1822
1823    /// Gets the count of imported, exported, or aliased core module instances.
1824    pub fn instance_count(&self) -> usize {
1825        match &self.kind {
1826            TypesKind::Module(_) => 0,
1827            TypesKind::Component(component) => component.core_instances.len(),
1828        }
1829    }
1830
1831    /// Gets the type of a component at the given component index.
1832    ///
1833    /// Returns `None` if the index is out of bounds.
1834    pub fn component_at(&self, index: u32) -> Option<&ComponentType> {
1835        self.as_ref().component_at(index)
1836    }
1837
1838    /// Gets the count of imported, exported, or aliased components.
1839    pub fn component_count(&self) -> usize {
1840        match &self.kind {
1841            TypesKind::Module(_) => 0,
1842            TypesKind::Component(component) => component.components.len(),
1843        }
1844    }
1845
1846    /// Gets the type of an component instance at the given component instance index.
1847    ///
1848    /// Returns `None` if the index is out of bounds.
1849    pub fn component_instance_at(&self, index: u32) -> Option<&ComponentInstanceType> {
1850        self.as_ref().component_instance_at(index)
1851    }
1852
1853    /// Gets the count of imported, exported, or aliased component instances.
1854    pub fn component_instance_count(&self) -> usize {
1855        match &self.kind {
1856            TypesKind::Module(_) => 0,
1857            TypesKind::Component(component) => component.instances.len(),
1858        }
1859    }
1860
1861    /// Gets the type of a value at the given value index.
1862    ///
1863    /// Returns `None` if the index is out of bounds.
1864    pub fn value_at(&self, index: u32) -> Option<ComponentValType> {
1865        self.as_ref().value_at(index)
1866    }
1867
1868    /// Gets the count of imported, exported, or aliased values.
1869    pub fn value_count(&self) -> usize {
1870        match &self.kind {
1871            TypesKind::Module(_) => 0,
1872            TypesKind::Component(component) => component.values.len(),
1873        }
1874    }
1875
1876    /// Gets the entity type from the given import.
1877    pub fn entity_type_from_import(&self, import: &Import) -> Option<EntityType> {
1878        self.as_ref().entity_type_from_import(import)
1879    }
1880
1881    /// Gets the entity type from the given export.
1882    pub fn entity_type_from_export(&self, export: &Export) -> Option<EntityType> {
1883        self.as_ref().entity_type_from_export(export)
1884    }
1885
1886    /// Gets the component entity type for the given component import or export
1887    /// name.
1888    pub fn component_entity_type_of_extern(&self, name: &str) -> Option<ComponentEntityType> {
1889        self.as_ref().component_entity_type_of_extern(name)
1890    }
1891
1892    /// Attempts to lookup the type id that `ty` is an alias of.
1893    ///
1894    /// Returns `None` if `ty` wasn't listed as aliasing a prior type.
1895    pub fn peel_alias(&self, ty: TypeId) -> Option<TypeId> {
1896        self.list.peel_alias(ty)
1897    }
1898}
1899
1900/// This is a type which mirrors a subset of the `Vec<T>` API, but is intended
1901/// to be able to be cheaply snapshotted and cloned.
1902///
1903/// When each module's code sections start we "commit" the current list of types
1904/// in the global list of types. This means that the temporary `cur` vec here is
1905/// pushed onto `snapshots` and wrapped up in an `Arc`. At that point we clone
1906/// this entire list (which is then O(modules), not O(types in all modules)) and
1907/// pass out as a context to each function validator.
1908///
1909/// Otherwise, though, this type behaves as if it were a large `Vec<T>`, but
1910/// it's represented by lists of contiguous chunks.
1911pub(crate) struct SnapshotList<T> {
1912    // All previous snapshots, the "head" of the list that this type represents.
1913    // The first entry in this pair is the starting index for all elements
1914    // contained in the list, and the second element is the list itself. Note
1915    // the `Arc` wrapper around sub-lists, which makes cloning time for this
1916    // `SnapshotList` O(snapshots) rather than O(snapshots_total), which for
1917    // us in this context means the number of modules, not types.
1918    //
1919    // Note that this list is sorted least-to-greatest in order of the index for
1920    // binary searching.
1921    snapshots: Vec<Arc<Snapshot<T>>>,
1922
1923    // This is the total length of all lists in the `snapshots` array.
1924    snapshots_total: usize,
1925
1926    // The current list of types for the current snapshot that are being built.
1927    cur: Vec<T>,
1928
1929    unique_mappings: HashMap<u32, u32>,
1930    unique_counter: u32,
1931}
1932
1933struct Snapshot<T> {
1934    prior_types: usize,
1935    unique_counter: u32,
1936    unique_mappings: HashMap<u32, u32>,
1937    items: Vec<T>,
1938}
1939
1940impl<T> SnapshotList<T> {
1941    /// Same as `<&[T]>::get`
1942    pub(crate) fn get(&self, index: usize) -> Option<&T> {
1943        // Check to see if this index falls on our local list
1944        if index >= self.snapshots_total {
1945            return self.cur.get(index - self.snapshots_total);
1946        }
1947        // ... and failing that we do a binary search to figure out which bucket
1948        // it's in. Note the `i-1` in the `Err` case because if we don't find an
1949        // exact match the type is located in the previous bucket.
1950        let i = match self
1951            .snapshots
1952            .binary_search_by_key(&index, |snapshot| snapshot.prior_types)
1953        {
1954            Ok(i) => i,
1955            Err(i) => i - 1,
1956        };
1957        let snapshot = &self.snapshots[i];
1958        Some(&snapshot.items[index - snapshot.prior_types])
1959    }
1960
1961    /// Same as `<&mut [T]>::get_mut`, except only works for indexes into the
1962    /// current snapshot being built.
1963    ///
1964    /// # Panics
1965    ///
1966    /// Panics if an index is passed in which falls within the
1967    /// previously-snapshotted list of types. This should never happen in our
1968    /// context and the panic is intended to weed out possible bugs in
1969    /// wasmparser.
1970    pub(crate) fn get_mut(&mut self, index: usize) -> Option<&mut T> {
1971        if index >= self.snapshots_total {
1972            return self.cur.get_mut(index - self.snapshots_total);
1973        }
1974        panic!("cannot get a mutable reference in snapshotted part of list")
1975    }
1976
1977    /// Same as `Vec::push`
1978    pub(crate) fn push(&mut self, val: T) {
1979        self.cur.push(val);
1980    }
1981
1982    /// Same as `<[T]>::len`
1983    pub(crate) fn len(&self) -> usize {
1984        self.cur.len() + self.snapshots_total
1985    }
1986
1987    /// Reserve space for an additional count of items.
1988    pub(crate) fn reserve(&mut self, additional: usize) {
1989        self.cur.reserve(additional);
1990    }
1991
1992    /// Commits previously pushed types into this snapshot vector, and returns a
1993    /// clone of this list.
1994    ///
1995    /// The returned `SnapshotList` can be used to access all the same types as
1996    /// this list itself. This list also is not changed (from an external
1997    /// perspective) and can continue to access all the same types.
1998    pub(crate) fn commit(&mut self) -> SnapshotList<T> {
1999        // If the current chunk has new elements, commit them in to an
2000        // `Arc`-wrapped vector in the snapshots list. Note the `shrink_to_fit`
2001        // ahead of time to hopefully keep memory usage lower than it would
2002        // otherwise be. Additionally note that the `unique_counter` is bumped
2003        // here to ensure that the previous value of the unique counter is
2004        // never used for an actual type so it's suitable for lookup via a
2005        // binary search.
2006        let len = self.cur.len();
2007        if len > 0 {
2008            self.unique_counter += 1;
2009            self.cur.shrink_to_fit();
2010            self.snapshots.push(Arc::new(Snapshot {
2011                prior_types: self.snapshots_total,
2012                unique_counter: self.unique_counter - 1,
2013                unique_mappings: mem::take(&mut self.unique_mappings),
2014                items: mem::take(&mut self.cur),
2015            }));
2016            self.snapshots_total += len;
2017        }
2018        SnapshotList {
2019            snapshots: self.snapshots.clone(),
2020            snapshots_total: self.snapshots_total,
2021            unique_mappings: HashMap::new(),
2022            unique_counter: self.unique_counter,
2023            cur: Vec::new(),
2024        }
2025    }
2026
2027    /// Modifies a `TypeId` to have the same contents but a fresh new unique id.
2028    ///
2029    /// This is used during aliasing with components to assign types a unique
2030    /// identifier that isn't equivalent to anything else but still
2031    /// points to the same underlying type.
2032    pub fn with_unique(&mut self, mut ty: TypeId) -> TypeId {
2033        self.unique_mappings
2034            .insert(self.unique_counter, ty.unique_id);
2035        ty.unique_id = self.unique_counter;
2036        self.unique_counter += 1;
2037        ty
2038    }
2039
2040    /// Attempts to lookup the type id that `ty` is an alias of.
2041    ///
2042    /// Returns `None` if `ty` wasn't listed as aliasing a prior type.
2043    pub fn peel_alias(&self, ty: TypeId) -> Option<TypeId> {
2044        // The unique counter in each snapshot is the unique counter at the
2045        // time of the snapshot so it's guaranteed to never be used, meaning
2046        // that `Ok` should never show up here. With an `Err` it's where the
2047        // index would be placed meaning that the index in question is the
2048        // smallest value over the unique id's value, meaning that slot has the
2049        // mapping we're interested in.
2050        let i = match self
2051            .snapshots
2052            .binary_search_by_key(&ty.unique_id, |snapshot| snapshot.unique_counter)
2053        {
2054            Ok(_) => unreachable!(),
2055            Err(i) => i,
2056        };
2057
2058        // If the `i` index is beyond the snapshot array then lookup in the
2059        // current mappings instead since it may refer to a type not snapshot
2060        // yet.
2061        let unique_id = match self.snapshots.get(i) {
2062            Some(snapshot) => *snapshot.unique_mappings.get(&ty.unique_id)?,
2063            None => *self.unique_mappings.get(&ty.unique_id)?,
2064        };
2065        Some(TypeId { unique_id, ..ty })
2066    }
2067}
2068
2069impl<T> std::ops::Index<usize> for SnapshotList<T> {
2070    type Output = T;
2071
2072    #[inline]
2073    fn index(&self, index: usize) -> &T {
2074        self.get(index).unwrap()
2075    }
2076}
2077
2078impl<T> std::ops::IndexMut<usize> for SnapshotList<T> {
2079    #[inline]
2080    fn index_mut(&mut self, index: usize) -> &mut T {
2081        self.get_mut(index).unwrap()
2082    }
2083}
2084
2085impl<T> std::ops::Index<TypeId> for SnapshotList<T> {
2086    type Output = T;
2087
2088    #[inline]
2089    fn index(&self, id: TypeId) -> &T {
2090        self.get(id.index).unwrap()
2091    }
2092}
2093
2094impl<T> std::ops::IndexMut<TypeId> for SnapshotList<T> {
2095    #[inline]
2096    fn index_mut(&mut self, id: TypeId) -> &mut T {
2097        self.get_mut(id.index).unwrap()
2098    }
2099}
2100
2101impl<T> Default for SnapshotList<T> {
2102    fn default() -> SnapshotList<T> {
2103        SnapshotList {
2104            snapshots: Vec::new(),
2105            snapshots_total: 0,
2106            cur: Vec::new(),
2107            unique_counter: 1,
2108            unique_mappings: HashMap::new(),
2109        }
2110    }
2111}
2112
2113/// A snapshot list of types.
2114pub(crate) type TypeList = SnapshotList<Type>;
2115
2116/// Thin wrapper around `TypeList` which provides an allocator of unique ids for
2117/// types contained within this list.
2118pub(crate) struct TypeAlloc {
2119    list: TypeList,
2120}
2121
2122impl Deref for TypeAlloc {
2123    type Target = TypeList;
2124    fn deref(&self) -> &TypeList {
2125        &self.list
2126    }
2127}
2128
2129impl DerefMut for TypeAlloc {
2130    fn deref_mut(&mut self) -> &mut TypeList {
2131        &mut self.list
2132    }
2133}
2134
2135impl TypeAlloc {
2136    /// Pushes a new anonymous type into this list which will have its
2137    /// `unique_id` field cleared.
2138    pub fn push_anon(&mut self, ty: Type) -> TypeId {
2139        let index = self.list.len();
2140        let type_size = ty.type_size();
2141        self.list.push(ty);
2142        TypeId {
2143            index,
2144            type_size,
2145            unique_id: 0,
2146        }
2147    }
2148
2149    /// Pushes a new defined type which has an index in core wasm onto this
2150    /// list.
2151    ///
2152    /// The returned `TypeId` is guaranteed to be unique and not hash-equivalent
2153    /// to any other prior ID in this list.
2154    pub fn push_defined(&mut self, ty: Type) -> TypeId {
2155        let id = self.push_anon(ty);
2156        self.with_unique(id)
2157    }
2158}
2159
2160impl Default for TypeAlloc {
2161    fn default() -> TypeAlloc {
2162        TypeAlloc {
2163            list: Default::default(),
2164        }
2165    }
2166}