use crate::core::ValueType;
use alloc::{sync::Arc, vec::Vec};
use core::fmt::{self, Display};
#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
pub struct FuncType {
len_params: usize,
params_results: Arc<[ValueType]>,
}
impl Display for FuncType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "fn(")?;
let (params, results) = self.params_results();
if let Some((first, rest)) = params.split_first() {
write!(f, "{}", first)?;
for param in rest {
write!(f, ", {}", param)?;
}
}
write!(f, ")")?;
if let Some((first, rest)) = results.split_first() {
write!(f, " -> ")?;
if !rest.is_empty() {
write!(f, "(")?;
}
write!(f, "{}", first)?;
for result in rest {
write!(f, ", {}", result)?;
}
if !rest.is_empty() {
write!(f, ")")?;
}
}
Ok(())
}
}
impl FuncType {
pub fn new<I, O>(inputs: I, outputs: O) -> Self
where
I: IntoIterator<Item = ValueType>,
O: IntoIterator<Item = ValueType>,
{
let mut inputs_outputs = inputs.into_iter().collect::<Vec<_>>();
let len_inputs = inputs_outputs.len();
inputs_outputs.extend(outputs);
Self {
params_results: inputs_outputs.into(),
len_params: len_inputs,
}
}
pub fn params(&self) -> &[ValueType] {
&self.params_results[..self.len_params]
}
pub fn results(&self) -> &[ValueType] {
&self.params_results[self.len_params..]
}
pub(crate) fn params_results(&self) -> (&[ValueType], &[ValueType]) {
self.params_results.split_at(self.len_params)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display_0in_0out() {
let func_type = FuncType::new([], []);
assert_eq!(format!("{}", func_type), String::from("fn()"),);
}
#[test]
fn display_1in_1out() {
let func_type = FuncType::new([ValueType::I32], [ValueType::I32]);
assert_eq!(format!("{}", func_type), String::from("fn(i32) -> i32"),);
}
#[test]
fn display_4in_0out() {
let func_type = FuncType::new(
[
ValueType::I32,
ValueType::I64,
ValueType::F32,
ValueType::F64,
],
[],
);
assert_eq!(
format!("{}", func_type),
String::from("fn(i32, i64, f32, f64)"),
);
}
#[test]
fn display_0in_4out() {
let func_type = FuncType::new(
[],
[
ValueType::I32,
ValueType::I64,
ValueType::F32,
ValueType::F64,
],
);
assert_eq!(
format!("{}", func_type),
String::from("fn() -> (i32, i64, f32, f64)"),
);
}
#[test]
fn display_4in_4out() {
let func_type = FuncType::new(
[
ValueType::I32,
ValueType::I64,
ValueType::F32,
ValueType::F64,
],
[
ValueType::I32,
ValueType::I64,
ValueType::F32,
ValueType::F64,
],
);
assert_eq!(
format!("{}", func_type),
String::from("fn(i32, i64, f32, f64) -> (i32, i64, f32, f64)"),
);
}
}