wasmparser_nostd/
resources.rs

1/* Copyright 2019 Mozilla Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16use crate::{FuncType, GlobalType, MemoryType, TableType, ValType};
17use ::core::ops::Range;
18
19/// Types that qualify as Wasm function types for validation purposes.
20pub trait WasmFuncType {
21    /// Returns the number of input types.
22    fn len_inputs(&self) -> usize;
23    /// Returns the number of output types.
24    fn len_outputs(&self) -> usize;
25    /// Returns the type at given index if any.
26    ///
27    /// # Note
28    ///
29    /// The returned type may be wrapped by the user crate and thus
30    /// the actually returned type only has to be comparable to a Wasm type.
31    fn input_at(&self, at: u32) -> Option<ValType>;
32    /// Returns the type at given index if any.
33    ///
34    /// # Note
35    ///
36    /// The returned type may be wrapped by the user crate and thus
37    /// the actually returned type only has to be comparable to a Wasm type.
38    fn output_at(&self, at: u32) -> Option<ValType>;
39
40    /// Returns the list of inputs as an iterator.
41    fn inputs(&self) -> WasmFuncTypeInputs<'_, Self>
42    where
43        Self: Sized,
44    {
45        WasmFuncTypeInputs {
46            func_type: self,
47            range: 0..self.len_inputs() as u32,
48        }
49    }
50
51    /// Returns the list of outputs as an iterator.
52    fn outputs(&self) -> WasmFuncTypeOutputs<'_, Self>
53    where
54        Self: Sized,
55    {
56        WasmFuncTypeOutputs {
57            func_type: self,
58            range: 0..self.len_outputs() as u32,
59        }
60    }
61}
62
63impl<T> WasmFuncType for &'_ T
64where
65    T: ?Sized + WasmFuncType,
66{
67    fn len_inputs(&self) -> usize {
68        T::len_inputs(self)
69    }
70    fn len_outputs(&self) -> usize {
71        T::len_outputs(self)
72    }
73    fn input_at(&self, at: u32) -> Option<ValType> {
74        T::input_at(self, at)
75    }
76    fn output_at(&self, at: u32) -> Option<ValType> {
77        T::output_at(self, at)
78    }
79}
80
81/// Iterator over the inputs of a Wasm function type.
82pub struct WasmFuncTypeInputs<'a, T> {
83    /// The iterated-over function type.
84    func_type: &'a T,
85    /// The range we're iterating over.
86    range: Range<u32>,
87}
88
89impl<T> Iterator for WasmFuncTypeInputs<'_, T>
90where
91    T: WasmFuncType,
92{
93    type Item = crate::ValType;
94
95    fn next(&mut self) -> Option<Self::Item> {
96        self.range
97            .next()
98            .map(|i| self.func_type.input_at(i).unwrap())
99    }
100
101    fn size_hint(&self) -> (usize, Option<usize>) {
102        self.range.size_hint()
103    }
104}
105
106impl<T> DoubleEndedIterator for WasmFuncTypeInputs<'_, T>
107where
108    T: WasmFuncType,
109{
110    fn next_back(&mut self) -> Option<Self::Item> {
111        self.range
112            .next_back()
113            .map(|i| self.func_type.input_at(i).unwrap())
114    }
115}
116
117impl<T> ExactSizeIterator for WasmFuncTypeInputs<'_, T>
118where
119    T: WasmFuncType,
120{
121    fn len(&self) -> usize {
122        self.range.len()
123    }
124}
125
126impl<'a, T> Clone for WasmFuncTypeInputs<'a, T> {
127    fn clone(&self) -> WasmFuncTypeInputs<'a, T> {
128        WasmFuncTypeInputs {
129            func_type: self.func_type,
130            range: self.range.clone(),
131        }
132    }
133}
134
135/// Iterator over the outputs of a Wasm function type.
136pub struct WasmFuncTypeOutputs<'a, T> {
137    /// The iterated-over function type.
138    func_type: &'a T,
139    /// The range we're iterating over.
140    range: Range<u32>,
141}
142
143impl<T> Iterator for WasmFuncTypeOutputs<'_, T>
144where
145    T: WasmFuncType,
146{
147    type Item = crate::ValType;
148
149    fn next(&mut self) -> Option<Self::Item> {
150        self.range
151            .next()
152            .map(|i| self.func_type.output_at(i).unwrap())
153    }
154
155    fn size_hint(&self) -> (usize, Option<usize>) {
156        self.range.size_hint()
157    }
158}
159
160impl<T> DoubleEndedIterator for WasmFuncTypeOutputs<'_, T>
161where
162    T: WasmFuncType,
163{
164    fn next_back(&mut self) -> Option<Self::Item> {
165        self.range
166            .next_back()
167            .map(|i| self.func_type.output_at(i).unwrap())
168    }
169}
170
171impl<T> ExactSizeIterator for WasmFuncTypeOutputs<'_, T>
172where
173    T: WasmFuncType,
174{
175    fn len(&self) -> usize {
176        self.range.len()
177    }
178}
179
180impl<'a, T> Clone for WasmFuncTypeOutputs<'a, T> {
181    fn clone(&self) -> WasmFuncTypeOutputs<'a, T> {
182        WasmFuncTypeOutputs {
183            func_type: self.func_type,
184            range: self.range.clone(),
185        }
186    }
187}
188
189/// Types that qualify as Wasm validation database.
190///
191/// # Note
192///
193/// The `wasmparser_nostd` crate provides a builtin validation framework but allows
194/// users of this crate to also feed the parsed Wasm into their own data
195/// structure while parsing and also validate at the same time without
196/// the need of an additional parsing or validation step or copying data around.
197pub trait WasmModuleResources {
198    /// The function type used for validation.
199    type FuncType: WasmFuncType;
200
201    /// Returns the table at given index if any.
202    fn table_at(&self, at: u32) -> Option<TableType>;
203    /// Returns the linear memory at given index.
204    fn memory_at(&self, at: u32) -> Option<MemoryType>;
205    /// Returns the tag at given index.
206    fn tag_at(&self, at: u32) -> Option<&Self::FuncType>;
207    /// Returns the global variable at given index.
208    fn global_at(&self, at: u32) -> Option<GlobalType>;
209    /// Returns the `FuncType` associated with the given type index.
210    fn func_type_at(&self, type_idx: u32) -> Option<&Self::FuncType>;
211    /// Returns the `FuncType` associated with the given function index.
212    fn type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType>;
213    /// Returns the element type at the given index.
214    fn element_type_at(&self, at: u32) -> Option<ValType>;
215
216    /// Returns the number of elements.
217    fn element_count(&self) -> u32;
218    /// Returns the number of bytes in the Wasm data section.
219    fn data_count(&self) -> Option<u32>;
220    /// Returns whether the function index is referenced in the module anywhere
221    /// outside of the start/function sections.
222    fn is_function_referenced(&self, idx: u32) -> bool;
223}
224
225impl<T> WasmModuleResources for &'_ T
226where
227    T: ?Sized + WasmModuleResources,
228{
229    type FuncType = T::FuncType;
230
231    fn table_at(&self, at: u32) -> Option<TableType> {
232        T::table_at(self, at)
233    }
234    fn memory_at(&self, at: u32) -> Option<MemoryType> {
235        T::memory_at(self, at)
236    }
237    fn tag_at(&self, at: u32) -> Option<&Self::FuncType> {
238        T::tag_at(self, at)
239    }
240    fn global_at(&self, at: u32) -> Option<GlobalType> {
241        T::global_at(self, at)
242    }
243    fn func_type_at(&self, at: u32) -> Option<&Self::FuncType> {
244        T::func_type_at(self, at)
245    }
246    fn type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType> {
247        T::type_of_function(self, func_idx)
248    }
249    fn element_type_at(&self, at: u32) -> Option<ValType> {
250        T::element_type_at(self, at)
251    }
252
253    fn element_count(&self) -> u32 {
254        T::element_count(self)
255    }
256    fn data_count(&self) -> Option<u32> {
257        T::data_count(self)
258    }
259    fn is_function_referenced(&self, idx: u32) -> bool {
260        T::is_function_referenced(self, idx)
261    }
262}
263
264impl<T> WasmModuleResources for ::alloc::sync::Arc<T>
265where
266    T: WasmModuleResources,
267{
268    type FuncType = T::FuncType;
269
270    fn table_at(&self, at: u32) -> Option<TableType> {
271        T::table_at(self, at)
272    }
273
274    fn memory_at(&self, at: u32) -> Option<MemoryType> {
275        T::memory_at(self, at)
276    }
277
278    fn tag_at(&self, at: u32) -> Option<&Self::FuncType> {
279        T::tag_at(self, at)
280    }
281
282    fn global_at(&self, at: u32) -> Option<GlobalType> {
283        T::global_at(self, at)
284    }
285
286    fn func_type_at(&self, type_idx: u32) -> Option<&Self::FuncType> {
287        T::func_type_at(self, type_idx)
288    }
289
290    fn type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType> {
291        T::type_of_function(self, func_idx)
292    }
293
294    fn element_type_at(&self, at: u32) -> Option<ValType> {
295        T::element_type_at(self, at)
296    }
297
298    fn element_count(&self) -> u32 {
299        T::element_count(self)
300    }
301
302    fn data_count(&self) -> Option<u32> {
303        T::data_count(self)
304    }
305
306    fn is_function_referenced(&self, idx: u32) -> bool {
307        T::is_function_referenced(self, idx)
308    }
309}
310
311impl WasmFuncType for FuncType {
312    fn len_inputs(&self) -> usize {
313        self.params().len()
314    }
315
316    fn len_outputs(&self) -> usize {
317        self.results().len()
318    }
319
320    fn input_at(&self, at: u32) -> Option<ValType> {
321        self.params().get(at as usize).copied()
322    }
323
324    fn output_at(&self, at: u32) -> Option<ValType> {
325        self.results().get(at as usize).copied()
326    }
327}