wasmer_types/features.rs
1use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
2#[cfg(feature = "enable-serde")]
3use serde::{Deserialize, Serialize};
4
5/// Controls which experimental features will be enabled.
6/// Features usually have a corresponding [WebAssembly proposal].
7///
8/// [WebAssembly proposal]: https://github.com/WebAssembly/proposals
9#[derive(Clone, Debug, Eq, PartialEq)]
10#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
11#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
12#[derive(RkyvSerialize, RkyvDeserialize, Archive)]
13#[rkyv(derive(Debug), compare(PartialEq))]
14pub struct Features {
15 /// Threads proposal should be enabled
16 pub threads: bool,
17 /// Reference Types proposal should be enabled
18 pub reference_types: bool,
19 /// SIMD proposal should be enabled
20 pub simd: bool,
21 /// Bulk Memory proposal should be enabled
22 pub bulk_memory: bool,
23 /// Multi Value proposal should be enabled
24 pub multi_value: bool,
25 /// Tail call proposal should be enabled
26 pub tail_call: bool,
27 /// Module Linking proposal should be enabled
28 pub module_linking: bool,
29 /// Multi Memory proposal should be enabled
30 pub multi_memory: bool,
31 /// 64-bit Memory proposal should be enabled
32 pub memory64: bool,
33 /// Wasm exceptions proposal should be enabled
34 pub exceptions: bool,
35 /// Relaxed SIMD proposal should be enabled
36 pub relaxed_simd: bool,
37 /// Extended constant expressions proposal should be enabled
38 pub extended_const: bool,
39}
40
41impl Features {
42 /// Create a new feature
43 pub fn new() -> Self {
44 Self {
45 threads: true,
46 // Reference types should be on by default
47 reference_types: true,
48 // SIMD should be on by default
49 simd: true,
50 // Bulk Memory should be on by default
51 bulk_memory: true,
52 // Multivalue should be on by default
53 multi_value: true,
54 tail_call: false,
55 module_linking: false,
56 multi_memory: false,
57 memory64: false,
58 exceptions: false,
59 relaxed_simd: false,
60 extended_const: false,
61 }
62 }
63
64 /// Configures whether the WebAssembly threads proposal will be enabled.
65 ///
66 /// The [WebAssembly threads proposal][threads] is not currently fully
67 /// standardized and is undergoing development. Support for this feature can
68 /// be enabled through this method for appropriate WebAssembly modules.
69 ///
70 /// This feature gates items such as shared memories and atomic
71 /// instructions.
72 ///
73 /// This is `false` by default.
74 ///
75 /// [threads]: https://github.com/webassembly/threads
76 pub fn threads(&mut self, enable: bool) -> &mut Self {
77 self.threads = enable;
78 self
79 }
80
81 /// Configures whether the WebAssembly reference types proposal will be
82 /// enabled.
83 ///
84 /// The [WebAssembly reference types proposal][proposal] is now
85 /// fully standardized and enabled by default.
86 ///
87 /// This feature gates items such as the `externref` type and multiple tables
88 /// being in a module. Note that enabling the reference types feature will
89 /// also enable the bulk memory feature.
90 ///
91 /// This is `true` by default.
92 ///
93 /// [proposal]: https://github.com/webassembly/reference-types
94 pub fn reference_types(&mut self, enable: bool) -> &mut Self {
95 self.reference_types = enable;
96 // The reference types proposal depends on the bulk memory proposal
97 if enable {
98 self.bulk_memory(true);
99 }
100 self
101 }
102
103 /// Configures whether the WebAssembly SIMD proposal will be
104 /// enabled.
105 ///
106 /// The [WebAssembly SIMD proposal][proposal] is not currently
107 /// fully standardized and is undergoing development. Support for this
108 /// feature can be enabled through this method for appropriate WebAssembly
109 /// modules.
110 ///
111 /// This feature gates items such as the `v128` type and all of its
112 /// operators being in a module.
113 ///
114 /// This is `false` by default.
115 ///
116 /// [proposal]: https://github.com/webassembly/simd
117 pub fn simd(&mut self, enable: bool) -> &mut Self {
118 self.simd = enable;
119 self
120 }
121
122 /// Configures whether the WebAssembly bulk memory operations proposal will
123 /// be enabled.
124 ///
125 /// The [WebAssembly bulk memory operations proposal][proposal] is now
126 /// fully standardized and enabled by default.
127 ///
128 /// This feature gates items such as the `memory.copy` instruction, passive
129 /// data/table segments, etc, being in a module.
130 ///
131 /// This is `true` by default.
132 ///
133 /// [proposal]: https://github.com/webassembly/bulk-memory-operations
134 pub fn bulk_memory(&mut self, enable: bool) -> &mut Self {
135 self.bulk_memory = enable;
136 // In case is false, we disable both threads and reference types
137 // since they both depend on bulk memory
138 if !enable {
139 self.reference_types(false);
140 }
141 self
142 }
143
144 /// Configures whether the WebAssembly multi-value proposal will
145 /// be enabled.
146 ///
147 /// The [WebAssembly multi-value proposal][proposal] is now fully
148 /// standardized and enabled by default, except with the singlepass
149 /// compiler which does not support it.
150 ///
151 /// This feature gates functions and blocks returning multiple values in a
152 /// module, for example.
153 ///
154 /// This is `true` by default.
155 ///
156 /// [proposal]: https://github.com/webassembly/multi-value
157 pub fn multi_value(&mut self, enable: bool) -> &mut Self {
158 self.multi_value = enable;
159 self
160 }
161
162 /// Configures whether the WebAssembly tail-call proposal will
163 /// be enabled.
164 ///
165 /// The [WebAssembly tail-call proposal][proposal] is not
166 /// currently fully standardized and is undergoing development.
167 /// Support for this feature can be enabled through this method for
168 /// appropriate WebAssembly modules.
169 ///
170 /// This feature gates tail-call functions in WebAssembly.
171 ///
172 /// This is `false` by default.
173 ///
174 /// [proposal]: https://github.com/webassembly/tail-call
175 pub fn tail_call(&mut self, enable: bool) -> &mut Self {
176 self.tail_call = enable;
177 self
178 }
179
180 /// Configures whether the WebAssembly module linking proposal will
181 /// be enabled.
182 ///
183 /// The [WebAssembly module linking proposal][proposal] is not
184 /// currently fully standardized and is undergoing development.
185 /// Support for this feature can be enabled through this method for
186 /// appropriate WebAssembly modules.
187 ///
188 /// This feature allows WebAssembly modules to define, import and
189 /// export modules and instances.
190 ///
191 /// This is `false` by default.
192 ///
193 /// [proposal]: https://github.com/webassembly/module-linking
194 pub fn module_linking(&mut self, enable: bool) -> &mut Self {
195 self.module_linking = enable;
196 self
197 }
198
199 /// Configures whether the WebAssembly multi-memory proposal will
200 /// be enabled.
201 ///
202 /// The [WebAssembly multi-memory proposal][proposal] is not
203 /// currently fully standardized and is undergoing development.
204 /// Support for this feature can be enabled through this method for
205 /// appropriate WebAssembly modules.
206 ///
207 /// This feature adds the ability to use multiple memories within a
208 /// single Wasm module.
209 ///
210 /// This is `false` by default.
211 ///
212 /// [proposal]: https://github.com/WebAssembly/multi-memory
213 pub fn multi_memory(&mut self, enable: bool) -> &mut Self {
214 self.multi_memory = enable;
215 self
216 }
217
218 /// Configures whether the WebAssembly 64-bit memory proposal will
219 /// be enabled.
220 ///
221 /// The [WebAssembly 64-bit memory proposal][proposal] is not
222 /// currently fully standardized and is undergoing development.
223 /// Support for this feature can be enabled through this method for
224 /// appropriate WebAssembly modules.
225 ///
226 /// This feature gates support for linear memory of sizes larger than
227 /// 2^32 bits.
228 ///
229 /// This is `false` by default.
230 ///
231 /// [proposal]: https://github.com/WebAssembly/memory64
232 pub fn memory64(&mut self, enable: bool) -> &mut Self {
233 self.memory64 = enable;
234 self
235 }
236
237 /// Configures whether the WebAssembly exception-handling proposal will be enabled.
238 ///
239 /// The [WebAssembly exception-handling proposal][eh] is not currently fully
240 /// standardized and is undergoing development. Support for this feature can
241 /// be enabled through this method for appropriate WebAssembly modules.
242 ///
243 /// This is `false` by default.
244 ///
245 /// [eh]: https://github.com/webassembly/exception-handling
246 pub fn exceptions(&mut self, enable: bool) -> &mut Self {
247 self.exceptions = enable;
248 self
249 }
250}
251
252impl Default for Features {
253 fn default() -> Self {
254 Self::new()
255 }
256}
257
258#[cfg(test)]
259mod test_features {
260 use super::*;
261 #[test]
262 fn default_features() {
263 let default = Features::default();
264 assert_eq!(
265 default,
266 Features {
267 threads: true,
268 reference_types: true,
269 simd: true,
270 bulk_memory: true,
271 multi_value: true,
272 tail_call: false,
273 module_linking: false,
274 multi_memory: false,
275 memory64: false,
276 exceptions: false,
277 relaxed_simd: false,
278 extended_const: false,
279 }
280 );
281 }
282
283 #[test]
284 fn enable_threads() {
285 let mut features = Features::new();
286 features.bulk_memory(false).threads(true);
287
288 assert!(features.threads);
289 }
290
291 #[test]
292 fn enable_reference_types() {
293 let mut features = Features::new();
294 features.bulk_memory(false).reference_types(true);
295 assert!(features.reference_types);
296 assert!(features.bulk_memory);
297 }
298
299 #[test]
300 fn enable_simd() {
301 let mut features = Features::new();
302 features.simd(true);
303 assert!(features.simd);
304 }
305
306 #[test]
307 fn enable_multi_value() {
308 let mut features = Features::new();
309 features.multi_value(true);
310 assert!(features.multi_value);
311 }
312
313 #[test]
314 fn enable_bulk_memory() {
315 let mut features = Features::new();
316 features.bulk_memory(true);
317 assert!(features.bulk_memory);
318 }
319
320 #[test]
321 fn disable_bulk_memory() {
322 let mut features = Features::new();
323 features
324 .threads(true)
325 .reference_types(true)
326 .bulk_memory(false);
327 assert!(!features.bulk_memory);
328 assert!(!features.reference_types);
329 }
330
331 #[test]
332 fn enable_tail_call() {
333 let mut features = Features::new();
334 features.tail_call(true);
335 assert!(features.tail_call);
336 }
337
338 #[test]
339 fn enable_module_linking() {
340 let mut features = Features::new();
341 features.module_linking(true);
342 assert!(features.module_linking);
343 }
344
345 #[test]
346 fn enable_multi_memory() {
347 let mut features = Features::new();
348 features.multi_memory(true);
349 assert!(features.multi_memory);
350 }
351
352 #[test]
353 fn enable_memory64() {
354 let mut features = Features::new();
355 features.memory64(true);
356 assert!(features.memory64);
357 }
358}