xref: /wasmtime-44.0.1/crates/c-api/src/types/func.rs (revision 483eb432)
1 use crate::{CExternType, wasm_externtype_t, wasm_valtype_t, wasm_valtype_vec_t};
2 use std::cell::OnceCell;
3 use std::{
4     mem,
5     sync::{Arc, Mutex},
6 };
7 use wasmtime::{Engine, FuncType, ValType};
8 
9 #[repr(transparent)]
10 #[derive(Clone)]
11 pub struct wasm_functype_t {
12     ext: wasm_externtype_t,
13 }
14 
15 wasmtime_c_api_macros::declare_ty!(wasm_functype_t);
16 
17 #[derive(Clone)]
18 enum LazyFuncType {
19     Lazy {
20         params: Vec<ValType>,
21         results: Vec<ValType>,
22     },
23     FuncType(FuncType),
24 }
25 
26 impl LazyFuncType {
force(&mut self, engine: &Engine) -> FuncType27     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 
params(&self) -> impl ExactSizeIterator<Item = ValType> + '_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 
results(&self) -> impl ExactSizeIterator<Item = ValType> + '_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 
55 enum LazyFuncTypeIter<'a, T> {
56     Lazy(std::slice::Iter<'a, ValType>),
57     FuncType(T),
58 }
59 
60 impl<'a, T> Iterator for LazyFuncTypeIter<'a, T>
61 where
62     T: Iterator<Item = ValType>,
63 {
64     type Item = ValType;
65 
next(&mut self) -> Option<Self::Item>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 
size_hint(&self) -> (usize, Option<usize>)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 
81 impl<'a, T> ExactSizeIterator for LazyFuncTypeIter<'a, T> where T: ExactSizeIterator<Item = ValType> {}
82 
83 #[derive(Clone)]
84 pub(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 
90 impl wasm_functype_t {
new(ty: FuncType) -> wasm_functype_t91     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 
lazy(params: Vec<ValType>, results: Vec<ValType>) -> wasm_functype_t97     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 
from_cfunc(ty: CFuncType) -> wasm_functype_t105     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 
try_from(e: &wasm_externtype_t) -> Option<&wasm_functype_t>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 
ty(&self) -> &CFuncType118     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 
126 impl CFuncType {
new(ty: FuncType) -> CFuncType127     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 
lazy(params: Vec<ValType>, results: Vec<ValType>) -> CFuncType135     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 
ty(&self, engine: &Engine) -> FuncType143     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)]
wasm_functype_new( params: &mut wasm_valtype_vec_t, results: &mut wasm_valtype_vec_t, ) -> Box<wasm_functype_t>150 pub 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)]
wasm_functype_params(ft: &wasm_functype_t) -> &wasm_valtype_vec_t168 pub 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)]
wasm_functype_results(ft: &wasm_functype_t) -> &wasm_valtype_vec_t180 pub 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)]
wasm_functype_as_externtype(ty: &wasm_functype_t) -> &wasm_externtype_t192 pub extern "C" fn wasm_functype_as_externtype(ty: &wasm_functype_t) -> &wasm_externtype_t {
193     &ty.ext
194 }
195 
196 #[unsafe(no_mangle)]
wasm_functype_as_externtype_const(ty: &wasm_functype_t) -> &wasm_externtype_t197 pub extern "C" fn wasm_functype_as_externtype_const(ty: &wasm_functype_t) -> &wasm_externtype_t {
198     &ty.ext
199 }
200