use crate::error::{Error, Result};
use fizzyx_sys as sys;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ValType {
I32,
I64,
F32,
F64,
}
impl ValType {
pub(crate) fn from_sys(raw: sys::FizzyValueType) -> Result<Self> {
match raw {
sys::FizzyValueTypeI32 => Ok(Self::I32),
sys::FizzyValueTypeI64 => Ok(Self::I64),
sys::FizzyValueTypeF32 => Ok(Self::F32),
sys::FizzyValueTypeF64 => Ok(Self::F64),
_ => Err(Error::UnsupportedType),
}
}
pub fn name(self) -> &'static str {
match self {
Self::I32 => "i32",
Self::I64 => "i64",
Self::F32 => "f32",
Self::F64 => "f64",
}
}
pub(crate) fn to_sys(self) -> sys::FizzyValueType {
match self {
Self::I32 => sys::FizzyValueTypeI32,
Self::I64 => sys::FizzyValueTypeI64,
Self::F32 => sys::FizzyValueTypeF32,
Self::F64 => sys::FizzyValueTypeF64,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Val {
I32(i32),
I64(i64),
F32(f32),
F64(f64),
}
impl Val {
pub fn ty(&self) -> ValType {
match self {
Self::I32(_) => ValType::I32,
Self::I64(_) => ValType::I64,
Self::F32(_) => ValType::F32,
Self::F64(_) => ValType::F64,
}
}
pub fn default_for_ty(ty: ValType) -> Self {
match ty {
ValType::I32 => Self::I32(0),
ValType::I64 => Self::I64(0),
ValType::F32 => Self::F32(0.0),
ValType::F64 => Self::F64(0.0),
}
}
pub fn i32(&self) -> Option<i32> {
match self {
Self::I32(value) => Some(*value),
_ => None,
}
}
pub fn i64(&self) -> Option<i64> {
match self {
Self::I64(value) => Some(*value),
_ => None,
}
}
pub fn f32(&self) -> Option<f32> {
match self {
Self::F32(value) => Some(*value),
_ => None,
}
}
pub fn f64(&self) -> Option<f64> {
match self {
Self::F64(value) => Some(*value),
_ => None,
}
}
pub(crate) fn to_sys(self) -> sys::FizzyValue {
match self {
Self::I32(value) => sys::FizzyValue { i32_: value as u32 },
Self::I64(value) => sys::FizzyValue { i64_: value as u64 },
Self::F32(value) => sys::FizzyValue { f32_: value },
Self::F64(value) => sys::FizzyValue { f64_: value },
}
}
pub(crate) fn from_sys(raw: sys::FizzyValue, ty: ValType) -> Self {
unsafe {
match ty {
ValType::I32 => Self::I32(raw.i32_ as i32),
ValType::I64 => Self::I64(raw.i64_ as i64),
ValType::F32 => Self::F32(raw.f32_),
ValType::F64 => Self::F64(raw.f64_),
}
}
}
}
impl From<i32> for Val {
fn from(value: i32) -> Self {
Self::I32(value)
}
}
impl From<i64> for Val {
fn from(value: i64) -> Self {
Self::I64(value)
}
}
impl From<f32> for Val {
fn from(value: f32) -> Self {
Self::F32(value)
}
}
impl From<f64> for Val {
fn from(value: f64) -> Self {
Self::F64(value)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Mutability {
Const,
Mutable,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct GlobalType {
content: ValType,
mutability: Mutability,
}
impl GlobalType {
pub fn new(content: ValType, mutability: Mutability) -> Self {
Self {
content,
mutability,
}
}
pub fn content(&self) -> ValType {
self.content
}
pub fn mutability(&self) -> Mutability {
self.mutability
}
pub(crate) fn from_sys(raw: sys::FizzyGlobalType) -> Result<Self> {
let content = ValType::from_sys(raw.value_type)?;
let mutability = if raw.is_mutable {
Mutability::Mutable
} else {
Mutability::Const
};
Ok(Self::new(content, mutability))
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct MemoryType {
minimum: u32,
maximum: Option<u32>,
}
impl MemoryType {
pub fn new(minimum: u32, maximum: Option<u32>) -> Self {
Self { minimum, maximum }
}
pub fn minimum(&self) -> u32 {
self.minimum
}
pub fn maximum(&self) -> Option<u32> {
self.maximum
}
pub(crate) fn from_sys(raw: sys::FizzyLimits) -> Self {
Self::new(raw.min, raw.has_max.then_some(raw.max))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FuncType {
params: Box<[ValType]>,
results: Box<[ValType]>,
}
impl FuncType {
pub fn new<P, R>(params: P, results: R) -> Self
where
P: IntoIterator<Item = ValType>,
R: IntoIterator<Item = ValType>,
{
Self {
params: params.into_iter().collect(),
results: results.into_iter().collect(),
}
}
pub fn params(&self) -> &[ValType] {
&self.params
}
pub fn results(&self) -> &[ValType] {
&self.results
}
pub(crate) fn from_sys(raw: &sys::FizzyFunctionType) -> Result<Self> {
let params = if raw.inputs_size == 0 {
Vec::new()
} else {
let inputs = unsafe { core::slice::from_raw_parts(raw.inputs, raw.inputs_size) };
inputs
.iter()
.map(|&ty| ValType::from_sys(ty))
.collect::<Result<Vec<_>>>()?
};
let results = if raw.output == sys::FizzyValueTypeVoid {
Vec::new()
} else {
vec![ValType::from_sys(raw.output)?]
};
Ok(Self::new(params, results))
}
pub(crate) fn to_sys_parts(&self) -> (Vec<sys::FizzyValueType>, sys::FizzyValueType) {
let inputs = self.params.iter().map(|ty| ty.to_sys()).collect();
let output = self
.results
.first()
.map(|ty| ty.to_sys())
.unwrap_or(sys::FizzyValueTypeVoid);
(inputs, output)
}
}