1use crate::{
17 BinaryReaderError, FuncType, GlobalType, HeapType, MemoryType, RefType, TableType, ValType,
18 WasmFeatures,
19};
20use std::ops::Range;
21
22pub trait WasmFuncType {
24 fn len_inputs(&self) -> usize;
26 fn len_outputs(&self) -> usize;
28 fn input_at(&self, at: u32) -> Option<ValType>;
35 fn output_at(&self, at: u32) -> Option<ValType>;
42
43 fn inputs(&self) -> WasmFuncTypeInputs<'_, Self>
45 where
46 Self: Sized,
47 {
48 WasmFuncTypeInputs {
49 func_type: self,
50 range: 0..self.len_inputs() as u32,
51 }
52 }
53
54 fn outputs(&self) -> WasmFuncTypeOutputs<'_, Self>
56 where
57 Self: Sized,
58 {
59 WasmFuncTypeOutputs {
60 func_type: self,
61 range: 0..self.len_outputs() as u32,
62 }
63 }
64}
65
66impl<T> WasmFuncType for &'_ T
67where
68 T: ?Sized + WasmFuncType,
69{
70 fn len_inputs(&self) -> usize {
71 T::len_inputs(self)
72 }
73 fn len_outputs(&self) -> usize {
74 T::len_outputs(self)
75 }
76 fn input_at(&self, at: u32) -> Option<ValType> {
77 T::input_at(self, at)
78 }
79 fn output_at(&self, at: u32) -> Option<ValType> {
80 T::output_at(self, at)
81 }
82}
83
84pub struct WasmFuncTypeInputs<'a, T> {
86 func_type: &'a T,
88 range: Range<u32>,
90}
91
92impl<T> Iterator for WasmFuncTypeInputs<'_, T>
93where
94 T: WasmFuncType,
95{
96 type Item = crate::ValType;
97
98 fn next(&mut self) -> Option<Self::Item> {
99 self.range
100 .next()
101 .map(|i| self.func_type.input_at(i).unwrap())
102 }
103
104 fn size_hint(&self) -> (usize, Option<usize>) {
105 self.range.size_hint()
106 }
107}
108
109impl<T> DoubleEndedIterator for WasmFuncTypeInputs<'_, T>
110where
111 T: WasmFuncType,
112{
113 fn next_back(&mut self) -> Option<Self::Item> {
114 self.range
115 .next_back()
116 .map(|i| self.func_type.input_at(i).unwrap())
117 }
118}
119
120impl<T> ExactSizeIterator for WasmFuncTypeInputs<'_, T>
121where
122 T: WasmFuncType,
123{
124 fn len(&self) -> usize {
125 self.range.len()
126 }
127}
128
129impl<'a, T> Clone for WasmFuncTypeInputs<'a, T> {
130 fn clone(&self) -> WasmFuncTypeInputs<'a, T> {
131 WasmFuncTypeInputs {
132 func_type: self.func_type,
133 range: self.range.clone(),
134 }
135 }
136}
137
138pub struct WasmFuncTypeOutputs<'a, T> {
140 func_type: &'a T,
142 range: Range<u32>,
144}
145
146impl<T> Iterator for WasmFuncTypeOutputs<'_, T>
147where
148 T: WasmFuncType,
149{
150 type Item = crate::ValType;
151
152 fn next(&mut self) -> Option<Self::Item> {
153 self.range
154 .next()
155 .map(|i| self.func_type.output_at(i).unwrap())
156 }
157
158 fn size_hint(&self) -> (usize, Option<usize>) {
159 self.range.size_hint()
160 }
161}
162
163impl<T> DoubleEndedIterator for WasmFuncTypeOutputs<'_, T>
164where
165 T: WasmFuncType,
166{
167 fn next_back(&mut self) -> Option<Self::Item> {
168 self.range
169 .next_back()
170 .map(|i| self.func_type.output_at(i).unwrap())
171 }
172}
173
174impl<T> ExactSizeIterator for WasmFuncTypeOutputs<'_, T>
175where
176 T: WasmFuncType,
177{
178 fn len(&self) -> usize {
179 self.range.len()
180 }
181}
182
183impl<'a, T> Clone for WasmFuncTypeOutputs<'a, T> {
184 fn clone(&self) -> WasmFuncTypeOutputs<'a, T> {
185 WasmFuncTypeOutputs {
186 func_type: self.func_type,
187 range: self.range.clone(),
188 }
189 }
190}
191
192pub trait WasmModuleResources {
201 type FuncType: WasmFuncType;
203
204 fn table_at(&self, at: u32) -> Option<TableType>;
206 fn memory_at(&self, at: u32) -> Option<MemoryType>;
208 fn tag_at(&self, at: u32) -> Option<&Self::FuncType>;
210 fn global_at(&self, at: u32) -> Option<GlobalType>;
212 fn func_type_at(&self, type_idx: u32) -> Option<&Self::FuncType>;
214 fn type_index_of_function(&self, func_idx: u32) -> Option<u32>;
217 fn type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType>;
219 fn element_type_at(&self, at: u32) -> Option<RefType>;
221 fn matches(&self, t1: ValType, t2: ValType) -> bool;
224 fn check_value_type(
226 &self,
227 t: ValType,
228 features: &WasmFeatures,
229 offset: usize,
230 ) -> Result<(), BinaryReaderError>;
231
232 fn check_heap_type(
235 &self,
236 heap_type: HeapType,
237 features: &WasmFeatures,
238 offset: usize,
239 ) -> Result<(), BinaryReaderError> {
240 self.check_value_type(
243 RefType {
244 nullable: true,
245 heap_type,
246 }
247 .into(),
248 features,
249 offset,
250 )
251 }
252
253 fn element_count(&self) -> u32;
255 fn data_count(&self) -> Option<u32>;
257 fn is_function_referenced(&self, idx: u32) -> bool;
260}
261
262impl<T> WasmModuleResources for &'_ T
263where
264 T: ?Sized + WasmModuleResources,
265{
266 type FuncType = T::FuncType;
267
268 fn table_at(&self, at: u32) -> Option<TableType> {
269 T::table_at(self, at)
270 }
271 fn memory_at(&self, at: u32) -> Option<MemoryType> {
272 T::memory_at(self, at)
273 }
274 fn tag_at(&self, at: u32) -> Option<&Self::FuncType> {
275 T::tag_at(self, at)
276 }
277 fn global_at(&self, at: u32) -> Option<GlobalType> {
278 T::global_at(self, at)
279 }
280 fn func_type_at(&self, at: u32) -> Option<&Self::FuncType> {
281 T::func_type_at(self, at)
282 }
283 fn type_index_of_function(&self, func_idx: u32) -> Option<u32> {
284 T::type_index_of_function(self, func_idx)
285 }
286 fn type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType> {
287 T::type_of_function(self, func_idx)
288 }
289 fn check_value_type(
290 &self,
291 t: ValType,
292 features: &WasmFeatures,
293 offset: usize,
294 ) -> Result<(), BinaryReaderError> {
295 T::check_value_type(self, t, features, offset)
296 }
297 fn element_type_at(&self, at: u32) -> Option<RefType> {
298 T::element_type_at(self, at)
299 }
300 fn matches(&self, t1: ValType, t2: ValType) -> bool {
301 T::matches(self, t1, t2)
302 }
303
304 fn element_count(&self) -> u32 {
305 T::element_count(self)
306 }
307 fn data_count(&self) -> Option<u32> {
308 T::data_count(self)
309 }
310 fn is_function_referenced(&self, idx: u32) -> bool {
311 T::is_function_referenced(self, idx)
312 }
313}
314
315impl<T> WasmModuleResources for std::sync::Arc<T>
316where
317 T: WasmModuleResources,
318{
319 type FuncType = T::FuncType;
320
321 fn table_at(&self, at: u32) -> Option<TableType> {
322 T::table_at(self, at)
323 }
324
325 fn memory_at(&self, at: u32) -> Option<MemoryType> {
326 T::memory_at(self, at)
327 }
328
329 fn tag_at(&self, at: u32) -> Option<&Self::FuncType> {
330 T::tag_at(self, at)
331 }
332
333 fn global_at(&self, at: u32) -> Option<GlobalType> {
334 T::global_at(self, at)
335 }
336
337 fn func_type_at(&self, type_idx: u32) -> Option<&Self::FuncType> {
338 T::func_type_at(self, type_idx)
339 }
340
341 fn type_index_of_function(&self, func_idx: u32) -> Option<u32> {
342 T::type_index_of_function(self, func_idx)
343 }
344
345 fn type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType> {
346 T::type_of_function(self, func_idx)
347 }
348
349 fn check_value_type(
350 &self,
351 t: ValType,
352 features: &WasmFeatures,
353 offset: usize,
354 ) -> Result<(), BinaryReaderError> {
355 T::check_value_type(self, t, features, offset)
356 }
357
358 fn element_type_at(&self, at: u32) -> Option<RefType> {
359 T::element_type_at(self, at)
360 }
361
362 fn matches(&self, t1: ValType, t2: ValType) -> bool {
363 T::matches(self, t1, t2)
364 }
365
366 fn element_count(&self) -> u32 {
367 T::element_count(self)
368 }
369
370 fn data_count(&self) -> Option<u32> {
371 T::data_count(self)
372 }
373
374 fn is_function_referenced(&self, idx: u32) -> bool {
375 T::is_function_referenced(self, idx)
376 }
377}
378
379impl WasmFuncType for FuncType {
380 fn len_inputs(&self) -> usize {
381 self.params().len()
382 }
383
384 fn len_outputs(&self) -> usize {
385 self.results().len()
386 }
387
388 fn input_at(&self, at: u32) -> Option<ValType> {
389 self.params().get(at as usize).copied()
390 }
391
392 fn output_at(&self, at: u32) -> Option<ValType> {
393 self.results().get(at as usize).copied()
394 }
395}