wasmtime_c_api/types/
func.rs1use crate::{wasm_externtype_t, wasm_valtype_t, wasm_valtype_vec_t, CExternType};
2use std::cell::OnceCell;
3use std::{
4 mem,
5 sync::{Arc, Mutex},
6};
7use wasmtime::{Engine, FuncType, ValType};
8
9#[repr(transparent)]
10#[derive(Clone)]
11pub struct wasm_functype_t {
12 ext: wasm_externtype_t,
13}
14
15wasmtime_c_api_macros::declare_ty!(wasm_functype_t);
16
17#[derive(Clone)]
18enum LazyFuncType {
19 Lazy {
20 params: Vec<ValType>,
21 results: Vec<ValType>,
22 },
23 FuncType(FuncType),
24}
25
26impl LazyFuncType {
27 pub(crate) fn force(&mut self, engine: &Engine) -> FuncType {
28 match self {
29 LazyFuncType::FuncType(ty) => ty.clone(),
30 LazyFuncType::Lazy { params, results } => {
31 let params = mem::take(params);
32 let results = mem::take(results);
33 let ty = FuncType::new(engine, params, results);
34 *self = LazyFuncType::FuncType(ty.clone());
35 ty
36 }
37 }
38 }
39
40 fn params(&self) -> impl ExactSizeIterator<Item = ValType> + '_ {
41 match self {
42 LazyFuncType::Lazy { params, .. } => LazyFuncTypeIter::Lazy(params.iter()),
43 LazyFuncType::FuncType(f) => LazyFuncTypeIter::FuncType(f.params()),
44 }
45 }
46
47 fn results(&self) -> impl ExactSizeIterator<Item = ValType> + '_ {
48 match self {
49 LazyFuncType::Lazy { results, .. } => LazyFuncTypeIter::Lazy(results.iter()),
50 LazyFuncType::FuncType(f) => LazyFuncTypeIter::FuncType(f.results()),
51 }
52 }
53}
54
55enum LazyFuncTypeIter<'a, T> {
56 Lazy(std::slice::Iter<'a, ValType>),
57 FuncType(T),
58}
59
60impl<'a, T> Iterator for LazyFuncTypeIter<'a, T>
61where
62 T: Iterator<Item = ValType>,
63{
64 type Item = ValType;
65
66 fn next(&mut self) -> Option<Self::Item> {
67 match self {
68 LazyFuncTypeIter::FuncType(i) => i.next(),
69 LazyFuncTypeIter::Lazy(i) => i.next().cloned(),
70 }
71 }
72
73 fn size_hint(&self) -> (usize, Option<usize>) {
74 match self {
75 LazyFuncTypeIter::FuncType(i) => i.size_hint(),
76 LazyFuncTypeIter::Lazy(i) => i.size_hint(),
77 }
78 }
79}
80
81impl<'a, T> ExactSizeIterator for LazyFuncTypeIter<'a, T> where T: ExactSizeIterator<Item = ValType> {}
82
83#[derive(Clone)]
84pub(crate) struct CFuncType {
85 ty: Arc<Mutex<LazyFuncType>>,
86 params_cache: OnceCell<wasm_valtype_vec_t>,
87 returns_cache: OnceCell<wasm_valtype_vec_t>,
88}
89
90impl wasm_functype_t {
91 pub(crate) fn new(ty: FuncType) -> wasm_functype_t {
92 wasm_functype_t {
93 ext: wasm_externtype_t::from_extern_type(ty.into()),
94 }
95 }
96
97 pub(crate) fn lazy(params: Vec<ValType>, results: Vec<ValType>) -> wasm_functype_t {
98 wasm_functype_t {
99 ext: wasm_externtype_t::from_cextern_type(CExternType::Func(CFuncType::lazy(
100 params, results,
101 ))),
102 }
103 }
104
105 pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasm_functype_t> {
106 match &e.which {
107 CExternType::Func(_) => Some(unsafe { &*(e as *const _ as *const _) }),
108 _ => None,
109 }
110 }
111
112 pub(crate) fn ty(&self) -> &CFuncType {
113 match &self.ext.which {
114 CExternType::Func(f) => &f,
115 _ => unsafe { std::hint::unreachable_unchecked() },
116 }
117 }
118}
119
120impl CFuncType {
121 pub(crate) fn new(ty: FuncType) -> CFuncType {
122 CFuncType {
123 ty: Arc::new(Mutex::new(LazyFuncType::FuncType(ty))),
124 params_cache: OnceCell::new(),
125 returns_cache: OnceCell::new(),
126 }
127 }
128
129 pub(crate) fn lazy(params: Vec<ValType>, results: Vec<ValType>) -> CFuncType {
130 CFuncType {
131 ty: Arc::new(Mutex::new(LazyFuncType::Lazy { params, results })),
132 params_cache: OnceCell::new(),
133 returns_cache: OnceCell::new(),
134 }
135 }
136
137 pub(crate) fn ty(&self, engine: &Engine) -> FuncType {
138 let mut ty = self.ty.lock().unwrap();
139 ty.force(engine)
140 }
141}
142
143#[unsafe(no_mangle)]
144pub extern "C" fn wasm_functype_new(
145 params: &mut wasm_valtype_vec_t,
146 results: &mut wasm_valtype_vec_t,
147) -> Box<wasm_functype_t> {
148 let params = params
149 .take()
150 .into_iter()
151 .map(|vt| vt.unwrap().ty.clone())
152 .collect();
153 let results = results
154 .take()
155 .into_iter()
156 .map(|vt| vt.unwrap().ty.clone())
157 .collect();
158 Box::new(wasm_functype_t::lazy(params, results))
159}
160
161#[unsafe(no_mangle)]
162pub extern "C" fn wasm_functype_params(ft: &wasm_functype_t) -> &wasm_valtype_vec_t {
163 let ft = ft.ty();
164 ft.params_cache.get_or_init(|| {
165 let ty = ft.ty.lock().unwrap();
166 ty.params()
167 .map(|p| Some(Box::new(wasm_valtype_t { ty: p.clone() })))
168 .collect::<Vec<_>>()
169 .into()
170 })
171}
172
173#[unsafe(no_mangle)]
174pub extern "C" fn wasm_functype_results(ft: &wasm_functype_t) -> &wasm_valtype_vec_t {
175 let ft = ft.ty();
176 ft.returns_cache.get_or_init(|| {
177 let ty = ft.ty.lock().unwrap();
178 ty.results()
179 .map(|p| Some(Box::new(wasm_valtype_t { ty: p.clone() })))
180 .collect::<Vec<_>>()
181 .into()
182 })
183}
184
185#[unsafe(no_mangle)]
186pub extern "C" fn wasm_functype_as_externtype(ty: &wasm_functype_t) -> &wasm_externtype_t {
187 &ty.ext
188}
189
190#[unsafe(no_mangle)]
191pub extern "C" fn wasm_functype_as_externtype_const(ty: &wasm_functype_t) -> &wasm_externtype_t {
192 &ty.ext
193}