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