radix_wasmi/module/
utils.rs

1use crate::{errors::ModuleError, FuncType, GlobalType, MemoryType, Mutability, TableType};
2use wasmi_core::ValueType;
3
4impl TryFrom<wasmparser::TableType> for TableType {
5    type Error = ModuleError;
6
7    fn try_from(table_type: wasmparser::TableType) -> Result<Self, Self::Error> {
8        if table_type.element_type != wasmparser::ValType::FuncRef {
9            return Err(ModuleError::unsupported(table_type));
10        }
11        let minimum = table_type.initial;
12        let maximum = table_type.maximum;
13        Ok(TableType::new(minimum, maximum))
14    }
15}
16
17impl TryFrom<wasmparser::MemoryType> for MemoryType {
18    type Error = ModuleError;
19
20    fn try_from(memory_type: wasmparser::MemoryType) -> Result<Self, Self::Error> {
21        let make_error = || ModuleError::unsupported(memory_type);
22        let into_error = |_error| make_error();
23        if memory_type.memory64 || memory_type.shared {
24            return Err(make_error());
25        }
26        let initial = memory_type.initial.try_into().map_err(into_error)?;
27        let maximum = memory_type
28            .maximum
29            .map(TryInto::try_into)
30            .transpose()
31            .map_err(into_error)?;
32        Ok(MemoryType::new(initial, maximum)
33            .expect("valid wasmparser MemoryType must be valid in wasmi")) // TODO: better return error
34    }
35}
36
37impl TryFrom<wasmparser::GlobalType> for GlobalType {
38    type Error = ModuleError;
39
40    fn try_from(global_type: wasmparser::GlobalType) -> Result<Self, Self::Error> {
41        let value_type = value_type_try_from_wasmparser(global_type.content_type)?;
42        let mutability = match global_type.mutable {
43            true => Mutability::Var,
44            false => Mutability::Const,
45        };
46        Ok(GlobalType::new(value_type, mutability))
47    }
48}
49
50impl TryFrom<wasmparser::FuncType> for FuncType {
51    type Error = ModuleError;
52
53    fn try_from(func_type: wasmparser::FuncType) -> Result<Self, Self::Error> {
54        /// Returns `true` if the given [`wasmparser::Type`] is supported by `wasmi`.
55        fn is_supported_value_type(value_type: &wasmparser::ValType) -> bool {
56            value_type_try_from_wasmparser(*value_type).is_ok()
57        }
58        /// Returns the [`ValueType`] from the given [`wasmparser::Type`].
59        ///
60        /// # Panics
61        ///
62        /// If the [`wasmparser::Type`] is not supported by `wasmi`.
63        fn extract_value_type(value_type: &wasmparser::ValType) -> ValueType {
64            value_type_from_wasmparser(*value_type)
65                .expect("encountered unexpected invalid value type")
66        }
67        if !func_type.params().iter().all(is_supported_value_type)
68            || !func_type.results().iter().all(is_supported_value_type)
69        {
70            // One of more function parameter or result types are not supported by `wasmi`.
71            return Err(ModuleError::unsupported(func_type));
72        }
73        let params = func_type.params().iter().map(extract_value_type);
74        let results = func_type.results().iter().map(extract_value_type);
75        let func_type = FuncType::new(params, results);
76        Ok(func_type)
77    }
78}
79
80/// Creates a [`ValueType`] from the given [`wasmparser::ValType`].
81///
82/// Returns `None` if the given [`wasmparser::ValType`] is not supported by `wasmi`.
83pub fn value_type_from_wasmparser(value_type: wasmparser::ValType) -> Option<ValueType> {
84    match value_type {
85        wasmparser::ValType::I32 => Some(ValueType::I32),
86        wasmparser::ValType::I64 => Some(ValueType::I64),
87        wasmparser::ValType::F32 => Some(ValueType::F32),
88        wasmparser::ValType::F64 => Some(ValueType::F64),
89        wasmparser::ValType::V128
90        | wasmparser::ValType::FuncRef
91        | wasmparser::ValType::ExternRef => None,
92    }
93}
94
95/// Creates a [`ValueType`] from the given [`wasmparser::ValType`].
96///
97/// # Errors
98///
99/// If the given [`wasmparser::ValType`] is not supported by `wasmi`.
100pub fn value_type_try_from_wasmparser(
101    value_type: wasmparser::ValType,
102) -> Result<ValueType, ModuleError> {
103    value_type_from_wasmparser(value_type).ok_or_else(|| ModuleError::unsupported(value_type))
104}