use crate::{IndexType, TableError};
#[cfg(doc)]
use crate::Table;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum RefType {
Func,
Extern,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct TableType {
element: RefType,
min: u64,
max: Option<u64>,
index_ty: IndexType,
}
impl TableType {
pub fn new(element: RefType, min: u32, max: Option<u32>) -> Self {
Self::new_impl(element, IndexType::I32, u64::from(min), max.map(u64::from))
}
pub fn new64(element: RefType, min: u64, max: Option<u64>) -> Self {
Self::new_impl(element, IndexType::I64, min, max)
}
pub(crate) fn new_impl(
element: RefType,
index_ty: IndexType,
min: u64,
max: Option<u64>,
) -> Self {
let absolute_max = index_ty.max_size();
assert!(u128::from(min) <= absolute_max);
max.inspect(|&max| {
assert!(min <= max && u128::from(max) <= absolute_max);
});
Self {
element,
min,
max,
index_ty,
}
}
pub fn is_64(&self) -> bool {
self.index_ty.is_64()
}
pub fn index_ty(&self) -> IndexType {
self.index_ty
}
pub fn element(&self) -> RefType {
self.element
}
pub fn minimum(&self) -> u64 {
self.min
}
pub fn maximum(&self) -> Option<u64> {
self.max
}
pub(crate) fn ensure_element_type_matches(&self, ty: RefType) -> Result<(), TableError> {
if self.element() != ty {
return Err(TableError::ElementTypeMismatch);
}
Ok(())
}
pub fn is_subtype_of(&self, other: &Self) -> bool {
if self.is_64() != other.is_64() {
return false;
}
if self.element() != other.element() {
return false;
}
if self.minimum() < other.minimum() {
return false;
}
match (self.maximum(), other.maximum()) {
(_, None) => true,
(Some(max), Some(other_max)) => max <= other_max,
_ => false,
}
}
}