wasmtime_c_api/types/
func.rs1use crate::{CExternType, wasm_externtype_t, wasm_valtype_t, wasm_valtype_vec_t};
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 from_cfunc(ty: CFuncType) -> wasm_functype_t {
106 wasm_functype_t {
107 ext: wasm_externtype_t::from_cextern_type(CExternType::Func(ty)),
108 }
109 }
110
111 pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasm_functype_t> {
112 match &e.which {
113 CExternType::Func(_) => Some(unsafe { &*(e as *const _ as *const _) }),
114 _ => None,
115 }
116 }
117
118 pub(crate) fn ty(&self) -> &CFuncType {
119 match &self.ext.which {
120 CExternType::Func(f) => &f,
121 _ => unsafe { std::hint::unreachable_unchecked() },
122 }
123 }
124}
125
126impl CFuncType {
127 pub(crate) fn new(ty: FuncType) -> CFuncType {
128 CFuncType {
129 ty: Arc::new(Mutex::new(LazyFuncType::FuncType(ty))),
130 params_cache: OnceCell::new(),
131 returns_cache: OnceCell::new(),
132 }
133 }
134
135 pub(crate) fn lazy(params: Vec<ValType>, results: Vec<ValType>) -> CFuncType {
136 CFuncType {
137 ty: Arc::new(Mutex::new(LazyFuncType::Lazy { params, results })),
138 params_cache: OnceCell::new(),
139 returns_cache: OnceCell::new(),
140 }
141 }
142
143 pub(crate) fn ty(&self, engine: &Engine) -> FuncType {
144 let mut ty = self.ty.lock().unwrap();
145 ty.force(engine)
146 }
147}
148
149#[unsafe(no_mangle)]
150pub extern "C" fn wasm_functype_new(
151 params: &mut wasm_valtype_vec_t,
152 results: &mut wasm_valtype_vec_t,
153) -> Box<wasm_functype_t> {
154 let params = params
155 .take()
156 .into_iter()
157 .map(|vt| vt.unwrap().ty.clone())
158 .collect();
159 let results = results
160 .take()
161 .into_iter()
162 .map(|vt| vt.unwrap().ty.clone())
163 .collect();
164 Box::new(wasm_functype_t::lazy(params, results))
165}
166
167#[unsafe(no_mangle)]
168pub extern "C" fn wasm_functype_params(ft: &wasm_functype_t) -> &wasm_valtype_vec_t {
169 let ft = ft.ty();
170 ft.params_cache.get_or_init(|| {
171 let ty = ft.ty.lock().unwrap();
172 ty.params()
173 .map(|p| Some(Box::new(wasm_valtype_t { ty: p.clone() })))
174 .collect::<Vec<_>>()
175 .into()
176 })
177}
178
179#[unsafe(no_mangle)]
180pub extern "C" fn wasm_functype_results(ft: &wasm_functype_t) -> &wasm_valtype_vec_t {
181 let ft = ft.ty();
182 ft.returns_cache.get_or_init(|| {
183 let ty = ft.ty.lock().unwrap();
184 ty.results()
185 .map(|p| Some(Box::new(wasm_valtype_t { ty: p.clone() })))
186 .collect::<Vec<_>>()
187 .into()
188 })
189}
190
191#[unsafe(no_mangle)]
192pub extern "C" fn wasm_functype_as_externtype(ty: &wasm_functype_t) -> &wasm_externtype_t {
193 &ty.ext
194}
195
196#[unsafe(no_mangle)]
197pub extern "C" fn wasm_functype_as_externtype_const(ty: &wasm_functype_t) -> &wasm_externtype_t {
198 &ty.ext
199}