Skip to main content

submilli_wasm/value/
type_access.rs

1//! wasmtime-compatible accessors on `ExternType` and `HeapType`: the `func()`/`global()`/… (and
2//! panicking `unwrap_*`) projections, and `as_concrete_struct()`/`…_array`/`…_func` for recovering
3//! a concrete GC/func type from a `HeapType`. Split from `types` to keep that file under the cap.
4
5use super::gc_type::{ArrayType, StructType};
6use super::tag_type::TagType;
7use super::types::{
8    ExternType, FuncType, GlobalType, HeapType, MemoryType, RefType, TableType, ValType,
9};
10
11impl ValType {
12    /// Whether this is a reference type.
13    pub fn is_ref(&self) -> bool {
14        matches!(self, ValType::Ref(_))
15    }
16
17    /// The underlying [`RefType`] if this is a reference type, else `None`.
18    // Inherent `as_ref` matches `wasmtime::ValType::as_ref` (not the `AsRef` trait).
19    #[allow(clippy::should_implement_trait)]
20    pub fn as_ref(&self) -> Option<&RefType> {
21        match self {
22            ValType::Ref(r) => Some(r),
23            _ => None,
24        }
25    }
26
27    /// The underlying [`RefType`], panicking if this is not a reference type.
28    pub fn unwrap_ref(&self) -> &RefType {
29        self.as_ref().expect("expected a reference type")
30    }
31}
32
33macro_rules! extern_type_accessors {
34    ($(($variant:ident($ty:ty) $get:ident $unwrap:ident))*) => ($(
35        /// The underlying type if this `ExternType` is that variant, else `None`.
36        pub fn $get(&self) -> Option<&$ty> {
37            if let ExternType::$variant(e) = self {
38                Some(e)
39            } else {
40                None
41            }
42        }
43
44        /// The underlying type, panicking if this `ExternType` is a different variant.
45        pub fn $unwrap(&self) -> &$ty {
46            self.$get().expect(concat!("expected ", stringify!($ty)))
47        }
48    )*)
49}
50
51impl ExternType {
52    extern_type_accessors! {
53        (Func(FuncType) func unwrap_func)
54        (Global(GlobalType) global unwrap_global)
55        (Table(TableType) table unwrap_table)
56        (Memory(MemoryType) memory unwrap_memory)
57        (Tag(TagType) tag unwrap_tag)
58    }
59}
60
61impl HeapType {
62    /// The concrete struct type if this is a `ConcreteStruct` heap type, else `None`.
63    pub fn as_concrete_struct(&self) -> Option<&StructType> {
64        match self {
65            HeapType::ConcreteStruct(t) => Some(t),
66            _ => None,
67        }
68    }
69
70    /// The concrete struct type, panicking if this is not a concrete struct heap type.
71    pub fn unwrap_concrete_struct(&self) -> &StructType {
72        self.as_concrete_struct()
73            .expect("expected a concrete struct heap type")
74    }
75
76    /// The concrete array type if this is a `ConcreteArray` heap type, else `None`.
77    pub fn as_concrete_array(&self) -> Option<&ArrayType> {
78        match self {
79            HeapType::ConcreteArray(t) => Some(t),
80            _ => None,
81        }
82    }
83
84    /// The concrete array type, panicking if this is not a concrete array heap type.
85    pub fn unwrap_concrete_array(&self) -> &ArrayType {
86        self.as_concrete_array()
87            .expect("expected a concrete array heap type")
88    }
89
90    /// The concrete function type if this is a `ConcreteFunc` heap type, else `None`.
91    pub fn as_concrete_func(&self) -> Option<&FuncType> {
92        match self {
93            HeapType::ConcreteFunc(t) => Some(t),
94            _ => None,
95        }
96    }
97
98    /// The concrete function type, panicking if this is not a concrete func heap type.
99    pub fn unwrap_concrete_func(&self) -> &FuncType {
100        self.as_concrete_func()
101            .expect("expected a concrete func heap type")
102    }
103}