1use alloc::{boxed::Box, string::String, vec::Vec};
2
3use crate::wasm::WasmFunc;
4
5use super::{Type, WasmValueError};
6
7#[derive(Clone, PartialEq)]
9pub struct FuncType {
10 params: Vec<(String, Type)>,
11 results: Vec<(String, Type)>,
12}
13
14impl FuncType {
15 pub fn new(
20 params: impl Into<Vec<(String, Type)>>,
21 results: impl Into<Vec<(String, Type)>>,
22 ) -> Result<Self, WasmValueError> {
23 let params = params.into();
24 if params.iter().any(|(name, _)| name.is_empty()) {
25 return Err(WasmValueError::Other("func params must be named".into()));
26 }
27 let results = results.into();
28 if results.len() > 1 && results.iter().any(|(name, _)| name.is_empty()) {
29 return Err(WasmValueError::Other(
30 "funcs with more than one result must have all results named".into(),
31 ));
32 }
33 Ok(Self { params, results })
34 }
35}
36
37impl WasmFunc for FuncType {
38 type Type = Type;
39
40 fn params(&self) -> Box<dyn Iterator<Item = Self::Type> + '_> {
41 Box::new(self.params.iter().map(|(_, ty)| ty.clone()))
42 }
43
44 fn param_names(&self) -> Box<dyn Iterator<Item = alloc::borrow::Cow<'_, str>> + '_> {
45 Box::new(self.params.iter().map(|(name, _)| name.into()))
46 }
47
48 fn results(&self) -> Box<dyn Iterator<Item = Self::Type> + '_> {
49 Box::new(self.results.iter().map(|(_, ty)| ty.clone()))
50 }
51
52 fn result_names(&self) -> Box<dyn Iterator<Item = alloc::borrow::Cow<'_, str>> + '_> {
53 Box::new(
54 self.results
55 .iter()
56 .flat_map(|(name, _)| (!name.is_empty()).then_some(name.into())),
57 )
58 }
59}
60
61impl core::fmt::Display for FuncType {
62 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
63 crate::wasm::DisplayFunc(self.clone()).fmt(f)
64 }
65}