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}