/src/wasm-tools/crates/wasmparser/src/module_resources.rs
Line | Count | Source (jump to first uncovered line) |
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 | | |
16 | | use crate::{FuncType, GlobalType, MemoryType, TableType, Type}; |
17 | | use std::ops::Range; |
18 | | |
19 | | /// Types that qualify as Wasm function types for validation purposes. |
20 | | pub 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<Type>; |
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<Type>; |
39 | | |
40 | | /// Returns the list of inputs as an iterator. |
41 | 2.00M | fn inputs(&self) -> WasmFuncTypeInputs<'_, Self> |
42 | 2.00M | where |
43 | 2.00M | Self: Sized, |
44 | 2.00M | { |
45 | 2.00M | WasmFuncTypeInputs { |
46 | 2.00M | func_type: self, |
47 | 2.00M | range: 0..self.len_inputs() as u32, |
48 | 2.00M | } |
49 | 2.00M | } |
50 | | |
51 | | /// Returns the list of outputs as an iterator. |
52 | 3.56M | fn outputs(&self) -> WasmFuncTypeOutputs<'_, Self> |
53 | 3.56M | where |
54 | 3.56M | Self: Sized, |
55 | 3.56M | { |
56 | 3.56M | WasmFuncTypeOutputs { |
57 | 3.56M | func_type: self, |
58 | 3.56M | range: 0..self.len_outputs() as u32, |
59 | 3.56M | } |
60 | 3.56M | } |
61 | | } |
62 | | |
63 | | impl<T> WasmFuncType for &'_ T |
64 | | where |
65 | | T: ?Sized + WasmFuncType, |
66 | | { |
67 | 0 | fn len_inputs(&self) -> usize { |
68 | 0 | T::len_inputs(self) |
69 | 0 | } |
70 | 0 | fn len_outputs(&self) -> usize { |
71 | 0 | T::len_outputs(self) |
72 | 0 | } |
73 | 0 | fn input_at(&self, at: u32) -> Option<Type> { |
74 | 0 | T::input_at(self, at) |
75 | 0 | } |
76 | 0 | fn output_at(&self, at: u32) -> Option<Type> { |
77 | 0 | T::output_at(self, at) |
78 | 0 | } |
79 | | } |
80 | | |
81 | | /// Iterator over the inputs of a Wasm function type. |
82 | | pub 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 | | |
89 | | impl<T> Iterator for WasmFuncTypeInputs<'_, T> |
90 | | where |
91 | | T: WasmFuncType, |
92 | | { |
93 | | type Item = crate::Type; |
94 | | |
95 | 8.86M | fn next(&mut self) -> Option<Self::Item> { |
96 | 8.86M | self.range |
97 | 8.86M | .next() |
98 | 8.86M | .map(|i| self.func_type.input_at(i).unwrap()) |
99 | 8.86M | } |
100 | | |
101 | 996k | fn size_hint(&self) -> (usize, Option<usize>) { |
102 | 996k | self.range.size_hint() |
103 | 996k | } |
104 | | } |
105 | | |
106 | | impl<T> DoubleEndedIterator for WasmFuncTypeInputs<'_, T> |
107 | | where |
108 | | T: WasmFuncType, |
109 | | { |
110 | 319k | fn next_back(&mut self) -> Option<Self::Item> { |
111 | 319k | self.range |
112 | 319k | .next_back() |
113 | 319k | .map(|i| self.func_type.input_at(i).unwrap()) |
114 | 319k | } |
115 | | } |
116 | | |
117 | | impl<T> ExactSizeIterator for WasmFuncTypeInputs<'_, T> |
118 | | where |
119 | | T: WasmFuncType, |
120 | | { |
121 | 0 | fn len(&self) -> usize { |
122 | 0 | self.range.len() |
123 | 0 | } |
124 | | } |
125 | | |
126 | | impl<'a, T> Clone for WasmFuncTypeInputs<'a, T> { |
127 | 0 | fn clone(&self) -> WasmFuncTypeInputs<'a, T> { |
128 | 0 | WasmFuncTypeInputs { |
129 | 0 | func_type: self.func_type, |
130 | 0 | range: self.range.clone(), |
131 | 0 | } |
132 | 0 | } |
133 | | } |
134 | | |
135 | | /// Iterator over the outputs of a Wasm function type. |
136 | | pub 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 | | |
143 | | impl<T> Iterator for WasmFuncTypeOutputs<'_, T> |
144 | | where |
145 | | T: WasmFuncType, |
146 | | { |
147 | | type Item = crate::Type; |
148 | | |
149 | 10.2M | fn next(&mut self) -> Option<Self::Item> { |
150 | 10.2M | self.range |
151 | 10.2M | .next() |
152 | 10.2M | .map(|i| self.func_type.output_at(i).unwrap()) |
153 | 10.2M | } |
154 | | |
155 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
156 | 0 | self.range.size_hint() |
157 | 0 | } |
158 | | } |
159 | | |
160 | | impl<T> DoubleEndedIterator for WasmFuncTypeOutputs<'_, T> |
161 | | where |
162 | | T: WasmFuncType, |
163 | | { |
164 | 8.49M | fn next_back(&mut self) -> Option<Self::Item> { |
165 | 8.49M | self.range |
166 | 8.49M | .next_back() |
167 | 8.49M | .map(|i| self.func_type.output_at(i).unwrap()) |
168 | 8.49M | } |
169 | | } |
170 | | |
171 | | impl<T> ExactSizeIterator for WasmFuncTypeOutputs<'_, T> |
172 | | where |
173 | | T: WasmFuncType, |
174 | | { |
175 | | fn len(&self) -> usize { |
176 | | self.range.len() |
177 | | } |
178 | | } |
179 | | |
180 | | impl<'a, T> Clone for WasmFuncTypeOutputs<'a, T> { |
181 | 0 | fn clone(&self) -> WasmFuncTypeOutputs<'a, T> { |
182 | 0 | WasmFuncTypeOutputs { |
183 | 0 | func_type: self.func_type, |
184 | 0 | range: self.range.clone(), |
185 | 0 | } |
186 | 0 | } |
187 | | } |
188 | | |
189 | | /// Types that qualify as Wasm valiation database. |
190 | | /// |
191 | | /// # Note |
192 | | /// |
193 | | /// The `wasmparser` 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. |
197 | | pub 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 event at given index. |
206 | | fn event_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<Type>; |
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) -> 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 | | |
225 | | impl<T> WasmModuleResources for &'_ T |
226 | | where |
227 | | T: ?Sized + WasmModuleResources, |
228 | | { |
229 | | type FuncType = T::FuncType; |
230 | | |
231 | 0 | fn table_at(&self, at: u32) -> Option<TableType> { |
232 | 0 | T::table_at(self, at) |
233 | 0 | } |
234 | 545k | fn memory_at(&self, at: u32) -> Option<MemoryType> { |
235 | 545k | T::memory_at(self, at) |
236 | 545k | } |
237 | 34 | fn event_at(&self, at: u32) -> Option<&Self::FuncType> { |
238 | 34 | T::event_at(self, at) |
239 | 34 | } |
240 | 0 | fn global_at(&self, at: u32) -> Option<GlobalType> { |
241 | 0 | T::global_at(self, at) |
242 | 0 | } |
243 | 128k | fn func_type_at(&self, at: u32) -> Option<&Self::FuncType> { |
244 | 128k | T::func_type_at(self, at) |
245 | 128k | } |
246 | 0 | fn type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType> { |
247 | 0 | T::type_of_function(self, func_idx) |
248 | 0 | } |
249 | 0 | fn element_type_at(&self, at: u32) -> Option<Type> { |
250 | 0 | T::element_type_at(self, at) |
251 | 0 | } |
252 | | |
253 | 0 | fn element_count(&self) -> u32 { |
254 | 0 | T::element_count(self) |
255 | 0 | } |
256 | 0 | fn data_count(&self) -> u32 { |
257 | 0 | T::data_count(self) |
258 | 0 | } |
259 | 0 | fn is_function_referenced(&self, idx: u32) -> bool { |
260 | 0 | T::is_function_referenced(self, idx) |
261 | 0 | } |
262 | | } |
263 | | |
264 | | impl WasmFuncType for FuncType { |
265 | 2.00M | fn len_inputs(&self) -> usize { |
266 | 2.00M | self.params.len() |
267 | 2.00M | } |
268 | | |
269 | 3.56M | fn len_outputs(&self) -> usize { |
270 | 3.56M | self.returns.len() |
271 | 3.56M | } |
272 | | |
273 | 7.18M | fn input_at(&self, at: u32) -> Option<Type> { |
274 | 7.18M | self.params.get(at as usize).copied() |
275 | 7.18M | } |
276 | | |
277 | 15.1M | fn output_at(&self, at: u32) -> Option<Type> { |
278 | 15.1M | self.returns.get(at as usize).copied() |
279 | 15.1M | } |
280 | | } |