wasmparser_nostd/validator/
types.rs

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