wasmer 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/documentation.yml +50 -0
  3. data/.github/workflows/test.yml +34 -61
  4. data/CHANGELOG.md +89 -29
  5. data/Cargo.lock +812 -380
  6. data/Cargo.toml +7 -20
  7. data/Gemfile +2 -3
  8. data/README.md +1 -0
  9. data/Rakefile +4 -3
  10. data/crates/rutie-derive-macros/Cargo.toml +19 -0
  11. data/crates/rutie-derive-macros/README.md +4 -0
  12. data/crates/rutie-derive-macros/src/class.rs +156 -0
  13. data/crates/rutie-derive-macros/src/function.rs +178 -0
  14. data/crates/rutie-derive-macros/src/lib.rs +27 -0
  15. data/crates/rutie-derive-macros/src/methods.rs +282 -0
  16. data/crates/rutie-derive/Cargo.toml +14 -0
  17. data/crates/rutie-derive/README.md +97 -0
  18. data/crates/rutie-derive/src/lib.rs +4 -0
  19. data/crates/rutie-derive/src/upcast.rs +47 -0
  20. data/crates/rutie-test/Cargo.toml +10 -0
  21. data/crates/rutie-test/src/lib.rs +38 -0
  22. data/crates/wasmer/Cargo.toml +27 -0
  23. data/crates/wasmer/README.md +228 -0
  24. data/crates/wasmer/src/doc.rs +1512 -0
  25. data/crates/wasmer/src/error.rs +55 -0
  26. data/crates/wasmer/src/exports.rs +107 -0
  27. data/crates/wasmer/src/externals/function.rs +159 -0
  28. data/crates/wasmer/src/externals/global.rs +62 -0
  29. data/crates/wasmer/src/externals/memory.rs +117 -0
  30. data/crates/wasmer/src/externals/mod.rs +9 -0
  31. data/crates/wasmer/src/externals/table.rs +41 -0
  32. data/crates/wasmer/src/import_object.rs +78 -0
  33. data/crates/wasmer/src/instance.rs +45 -0
  34. data/crates/wasmer/src/lib.rs +307 -0
  35. data/crates/wasmer/src/memory/mod.rs +1 -0
  36. data/crates/wasmer/src/memory/views.rs +112 -0
  37. data/crates/wasmer/src/module.rs +106 -0
  38. data/crates/wasmer/src/prelude.rs +3 -0
  39. data/crates/wasmer/src/store.rs +22 -0
  40. data/crates/wasmer/src/types.rs +390 -0
  41. data/crates/wasmer/src/values.rs +84 -0
  42. data/crates/wasmer/src/wasi.rs +226 -0
  43. data/crates/wasmer/src/wat.rs +20 -0
  44. data/justfile +7 -1
  45. data/lib/wasmer.rb +29 -3
  46. data/wasmer.gemspec +6 -10
  47. metadata +45 -47
  48. data/README.md +0 -332
  49. data/lib/wasmer/version.rb +0 -3
  50. data/src/error.rs +0 -16
  51. data/src/instance/exports.rs +0 -215
  52. data/src/instance/globals.rs +0 -234
  53. data/src/instance/mod.rs +0 -141
  54. data/src/lib.rs +0 -162
  55. data/src/memory/mod.rs +0 -158
  56. data/src/memory/view.rs +0 -145
  57. data/src/module.rs +0 -28
@@ -0,0 +1,10 @@
1
+ [package]
2
+ name = "rutie-test"
3
+ version = "0.1.0"
4
+ authors = ["Wasmer Engineering Team <engineering@wasmer.io>"]
5
+ edition = "2018"
6
+ description = "Helpers to test code written with `rutie`."
7
+ readme = "README.md"
8
+ repository = "https://github.com/wasmerio/wasmer-ruby"
9
+ keywords = ["ruby", "extension"]
10
+ publish = false
@@ -0,0 +1,38 @@
1
+ #[macro_export]
2
+ macro_rules! test_ruby {
3
+ ($code:expr) => {
4
+ use rutie::VM;
5
+
6
+ let code = format!(
7
+ r#"
8
+ root = File.expand_path("../..", ENV["CARGO_MANIFEST_DIR"])
9
+
10
+ Dir.chdir(root)
11
+
12
+ $LOAD_PATH.unshift(File.expand_path("lib", root))
13
+
14
+ require "wasmer"
15
+
16
+ class AssertionError < RuntimeError
17
+ end
18
+
19
+ def assert &block
20
+ raise AssertionError unless yield
21
+ end
22
+
23
+ {code}
24
+ "#,
25
+ code = $code
26
+ );
27
+
28
+ VM::init();
29
+ VM::init_loadpath();
30
+
31
+ match VM::eval(&code) {
32
+ Ok(value) => assert!(true),
33
+ Err(err) => panic!("{:?}", err),
34
+ }
35
+ };
36
+ }
37
+
38
+ pub fn foo() {}
@@ -0,0 +1,27 @@
1
+ [package]
2
+ name = "wasmer"
3
+ version = "0.5.0"
4
+ authors = ["Wasmer Engineering Team <engineering@wasmer.io>"]
5
+ edition = "2018"
6
+ description = "Ruby extension to run WebAssembly binaries"
7
+ readme = "README.md"
8
+ repository = "https://github.com/wasmerio/wasmer-ruby"
9
+ keywords = ["ruby", "extension", "webassembly"]
10
+ categories = ["wasm"]
11
+ publish = false
12
+
13
+ [lib]
14
+ name = "wasmer_ruby"
15
+ crate-type = ["dylib", "rlib"]
16
+
17
+ [dependencies]
18
+ wasmer = "1.0"
19
+ wasmer-wasi = "1.0"
20
+ rutie = "0.8"
21
+ rutie-derive = { path = "../rutie-derive", version = "0.1.0" }
22
+ lazy_static = "1.4"
23
+ wat = "1.0"
24
+ wasmprinter = "0.2"
25
+
26
+ [dev-dependencies]
27
+ rutie-test = { path = "../rutie-test", version = "0.1.0" }
@@ -0,0 +1,228 @@
1
+ <div align="center">
2
+ <a href="https://wasmer.io" target="_blank" rel="noopener noreferrer">
3
+ <img width="300" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/assets/logo.png" alt="Wasmer logo">
4
+ </a>
5
+
6
+ <h1>Wasmer Ruby</h1>
7
+
8
+ <p>
9
+ <a href="https://github.com/wasmerio/wasmer-ruby/actions?query=workflow%3A%22Build+and+Test%22">
10
+ <img src="https://github.com/wasmerio/wasmer-ruby/workflows/Build%20and%20Test/badge.svg" alt="Build Status">
11
+ </a>
12
+ <a href="https://github.com/wasmerio/wasmer-ruby/blob/master/LICENSE">
13
+ <img src="https://img.shields.io/github/license/wasmerio/wasmer-ruby.svg" alt="License">
14
+ </a>
15
+ <a href="https://rubygems.org/gems/wasmer">
16
+ <img src="https://img.shields.io/gem/v/wasmer.svg" alt="Wasmer on RubyGem">
17
+ </a>
18
+ <a href="https://rubygems.org/gems/wasmer">
19
+ <img src="https://img.shields.io/gem/dt/wasmer.svg" alt="Number of downloads">
20
+ </a>
21
+ <a href="https://wasmerio.github.io/wasmer-ruby/wasmer_ruby/index.html">
22
+ <img src="https://img.shields.io/badge/documentation-API-f06" alt="API Documentation">
23
+ </a>
24
+ </p>
25
+
26
+ <h3>
27
+ <a href="https://wasmer.io/">Website</a>
28
+ <span> • </span>
29
+ <a href="https://docs.wasmer.io">Docs</a>
30
+ <span> • </span>
31
+ <a href="https://slack.wasmer.io/">Slack Channel</a>
32
+ </h3>
33
+ </div>
34
+
35
+ <hr/>
36
+
37
+ A complete and mature WebAssembly runtime for Ruby based on
38
+ [Wasmer](https://github.com/wasmerio/wasmer).
39
+
40
+ Features
41
+
42
+ * **Easy to use**: The `wasmer` API mimics the standard WebAssembly API,
43
+ * **Fast**: `wasmer` executes the WebAssembly modules as fast as
44
+ possible, close to **native speed**,
45
+ * **Safe**: All calls to WebAssembly will be fast, but more
46
+ importantly, completely safe and sandboxed.
47
+
48
+ **Documentation**: [browse the detailed API
49
+ documentation](https://wasmerio.github.io/wasmer-ruby/wasmer_ruby/index.html)
50
+ full of examples.
51
+
52
+ **Examples** as tutorials: [browser the `examples/`
53
+ directory](https://github.com/wasmerio/wasmer-ruby/tree/master/examples),
54
+ it's the best place for a complete introduction!
55
+
56
+ # Quick Introduction
57
+
58
+ The `wasmer` package brings the required API to execute WebAssembly
59
+ modules. In a nutshell, `wasmer` compiles the WebAssembly module into
60
+ compiled code, and then executes it. `wasmer` is designed to work in
61
+ various environments and platforms. To achieve this, Wasmer (the
62
+ original runtime) provides multiple engines and multiple
63
+ compilers.
64
+
65
+ Succinctly, an _engine_ is responsible to drive the _compilation_ (by
66
+ using a _compiler_) and the _execution_ of a WebAssembly
67
+ module. Wasmer comes with many engines and compilers, but for the Ruby
68
+ extension, it only provides the JIT engine with the Cranelift
69
+ compiler. It is subject to change in the future where the user will
70
+ have the choice to select its own engine and compiler.
71
+
72
+ ## Install
73
+
74
+ To install the `wasmer` Ruby gem, just run this command in your shell:
75
+
76
+ ```sh
77
+ $ gem install wasmer
78
+ ```
79
+
80
+ And you're ready to get fun!
81
+
82
+ [View the `wasmer` gem on RubyGems][wasmer-gem].
83
+
84
+ > Note: [Rust][rust] is required to install the Ruby library (Cargo
85
+ —the build tool for Rust— is used to compile the extension). See [how
86
+ to install Rust][install-rust].
87
+
88
+ ## Example
89
+
90
+ We highly recommend to read the
91
+ [`examples/`](https://github.com/wasmerio/wasmer-ruby/tree/master/examples)
92
+ directory, which contains a sequence of examples/tutorials. It's the
93
+ best place to learn by reading examples.
94
+
95
+ But for the most eager of you, and we know you're numerous you
96
+ mischievous, there is a quick toy program in
97
+ `examples/appendices/simple.rs`, written in Rust:
98
+
99
+ ```rust
100
+ #[no_mangle]
101
+ pub extern fn sum(x: i32, y: i32) -> i32 {
102
+ x + y
103
+ }
104
+ ```
105
+
106
+ After compilation to WebAssembly, the
107
+ [`examples/appendices/simple.wasm`](https://github.com/wasmerio/wasmer-ruby/blob/master/examples/appendices/simple.wasm)
108
+ binary file is generated.
109
+
110
+ Then, we can execute it in Ruby:
111
+
112
+ ```ruby
113
+ require "wasmer"
114
+
115
+ # Let's define the store, that holds the engine, that holds the compiler.
116
+ store = Wasmer::Store.new
117
+
118
+ # Let's compile the module to be able to execute it!
119
+ module_ = Wasmer::Module.new store, IO.read("simple.wasm", mode: "rb")
120
+
121
+ # Now the module is compiled, we can instantiate it.
122
+ instance = Wasmer::Instance.new module_, nil
123
+
124
+ # Call the exported `sum` function.
125
+ result = instance.exports.sum.(5, 37)
126
+
127
+ puts result # 42!
128
+ ```
129
+
130
+ And then, finally, enjoy by running:
131
+
132
+ ```sh
133
+ $ ruby examples/appendices/simple.rb
134
+ ```
135
+
136
+ ## Development
137
+
138
+ The Ruby extension is written in [Rust][rust], with [`rutie`][rutie].
139
+
140
+ First, you need to install Rust and Ruby. We will not make you the
141
+ affront to explain to you how to install Ruby (if you really need,
142
+ check [`rbenv`][rbenv]). For Rust though, we advice to use
143
+ [`rustup`][rustup], then:
144
+
145
+ ```sh
146
+ $ rustup install stable
147
+ ```
148
+
149
+ Then, after installing [`just`][just], you can simply run:
150
+
151
+ ```sh
152
+ $ just build
153
+ ```
154
+
155
+ The supported Ruby versions are:
156
+
157
+ * Ruby 2.6,
158
+ * Ruby 2.7,
159
+ * Ruby 3.0.
160
+
161
+ ### Extensions to `rutie`
162
+
163
+ This project provides extensions to `rutie`, through the
164
+ `rutie-derive` and `rutie-derive-macros` crates (see the `crates/`
165
+ directory). Those crates aim at enhancing `rutie` by providing a
166
+ better “Domain Specific Language” (DSL for short) to declare Ruby
167
+ modules, classes, methods and functions. It's not perfect but it does
168
+ a good job for the moment. Contributions on that front are welcomed
169
+ too!
170
+
171
+ ### Testing
172
+
173
+ Running the `test` recipe will automatically build and run all the
174
+ tests. It includes library tests, along with documentation tests.
175
+
176
+ ```sh
177
+ $ just test
178
+ ```
179
+
180
+ ### Documentation
181
+
182
+ To generate the documentation, run the following command:
183
+
184
+ ```sh
185
+ $ just doc
186
+ ```
187
+
188
+ All the examples in the documentation are automatically run as tests,
189
+ called doctests. To run the doctests, run `just test`.
190
+
191
+ ## What is WebAssembly?
192
+
193
+ Quoting [the WebAssembly site][wasm]:
194
+
195
+ > WebAssembly (abbreviated Wasm) is a binary instruction format for a
196
+ > stack-based virtual machine. Wasm is designed as a portable target
197
+ > for compilation of high-level languages like C/C++/Rust, enabling
198
+ > deployment on the web for client and server applications.
199
+
200
+ About speed:
201
+
202
+ > WebAssembly aims to execute at native speed by taking advantage of
203
+ > [common hardware
204
+ > capabilities](https://webassembly.org/docs/portability/#assumptions-for-efficient-execution)
205
+ > available on a wide range of platforms.
206
+
207
+ About safety:
208
+
209
+ > WebAssembly describes a memory-safe, sandboxed [execution
210
+ > environment](https://webassembly.org/docs/semantics/#linear-memory) […].
211
+
212
+ [wasm]: https://webassembly.org/
213
+
214
+ ## License
215
+
216
+ The entire project is under the MIT License. Please read [the
217
+ `LICENSE` file][license].
218
+
219
+ [license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE
220
+
221
+ [Wasmer]: https://github.com/wasmerio/wasmer
222
+ [rust]: https://www.rust-lang.org/
223
+ [install-rust]: https://www.rust-lang.org/tools/install
224
+ [wasmer-gem]: https://rubygems.org/gems/wasmer
225
+ [rutie]: https://github.com/danielpclark/rutie
226
+ [rbenv]: https://github.com/rbenv/rbenv
227
+ [rustup]: https://rustup.rs/
228
+ [just]: https://github.com/casey/just/
@@ -0,0 +1,1512 @@
1
+ macro_rules! x {
2
+ () => {
3
+ unimplemented!("This code exists only for documentation purposes");
4
+ };
5
+ }
6
+
7
+ /// Declare Ruby native types. It's only for documentation purposes.
8
+ pub mod Ruby {
9
+ /// A native Ruby boolean.
10
+ ///
11
+ /// # Example
12
+ ///
13
+ /// ```rust
14
+ /// # fn main() { rutie_test::test_ruby!(r#"
15
+ /// true
16
+ /// # "#); }
17
+ /// ```
18
+ pub struct Boolean;
19
+
20
+ /// A native Ruby integer.
21
+ ///
22
+ /// # Example
23
+ ///
24
+ /// ```rust
25
+ /// # fn main() { rutie_test::test_ruby!(r#"
26
+ /// 42
27
+ /// # "#); }
28
+ /// ```
29
+ pub struct Integer;
30
+
31
+ /// A native Ruby float.
32
+ ///
33
+ /// # Example
34
+ ///
35
+ /// ```rust
36
+ /// # fn main() { rutie_test::test_ruby!(r#"
37
+ /// 4.2
38
+ /// # "#); }
39
+ /// ```
40
+ pub struct Float;
41
+
42
+ /// A native Ruby string.
43
+ ///
44
+ /// # Example
45
+ ///
46
+ /// ```rust
47
+ /// # fn main() { rutie_test::test_ruby!(r#"
48
+ /// "hello"
49
+ /// # "#); }
50
+ /// ```
51
+ pub struct String;
52
+
53
+ /// A native Ruby array.
54
+ ///
55
+ /// # Example
56
+ ///
57
+ /// ```rust
58
+ /// # fn main() { rutie_test::test_ruby!(r#"
59
+ /// [1, "two", 3.0]
60
+ /// # "#); }
61
+ /// ```
62
+ pub struct Array<T>;
63
+
64
+ /// A native Ruby hash.
65
+ ///
66
+ /// # Example
67
+ ///
68
+ /// ```rust
69
+ /// # fn main() { rutie_test::test_ruby!(r#"
70
+ /// {"foo": 42, "bar": 153}
71
+ /// # "#); }
72
+ /// ```
73
+ pub struct Hash<K, V>;
74
+
75
+ /// Represents any kind of object.
76
+ pub struct Any;
77
+ }
78
+
79
+ /// The `Wasmer` module provides the entire Wasmer API to manipulate
80
+ /// the WebAssembly runtime.
81
+ pub mod Wasmer {
82
+ use crate::doc::Ruby::*;
83
+
84
+ /// A WebAssembly type.
85
+ ///
86
+ /// # Example
87
+ ///
88
+ /// ```rust
89
+ /// # fn main() { rutie_test::test_ruby!(r#"
90
+ /// Wasmer::Type::I32
91
+ /// # "#); }
92
+ /// ```
93
+ #[allow(non_camel_case_types)]
94
+ pub enum Type {
95
+ I32,
96
+ I64,
97
+ F32,
98
+ F64,
99
+ V128,
100
+ EXTERN_REF,
101
+ FUNC_REF,
102
+ }
103
+
104
+ /// Represents the signature of a function that is either
105
+ /// implemented in WebAssembly module or exposed to WebAssembly by
106
+ /// the host.
107
+ ///
108
+ /// WebAssembly functions can have 0 or more parameters and results.
109
+ pub struct FunctionType;
110
+
111
+ impl FunctionType {
112
+ /// Creates a new `FunctionType`.
113
+ ///
114
+ /// # Example
115
+ ///
116
+ /// ```rust
117
+ /// # fn main() { rutie_test::test_ruby!(r#"
118
+ /// function_type = Wasmer::FunctionType.new(
119
+ /// [Wasmer::Type::I32, Wasmer::Type::I64],
120
+ /// [Wasmer::Type::I32]
121
+ /// )
122
+ /// # "#); }
123
+ /// ```
124
+ pub fn new(params: Array<Type>, results: Array<Type>) -> Self {
125
+ x!()
126
+ }
127
+
128
+ /// Returns the parameters.
129
+ ///
130
+ /// # Example
131
+ ///
132
+ /// ```rust
133
+ /// # fn main() { rutie_test::test_ruby!(r#"
134
+ /// function_type = Wasmer::FunctionType.new(
135
+ /// [Wasmer::Type::I32, Wasmer::Type::I64],
136
+ /// [Wasmer::Type::I32]
137
+ /// )
138
+ ///
139
+ /// assert { function_type.params == [Wasmer::Type::I32, Wasmer::Type::I64] }
140
+ /// # "#); }
141
+ /// ```
142
+ pub fn params(&self) -> Array<Type> {
143
+ x!()
144
+ }
145
+
146
+ /// Returns the results.
147
+ ///
148
+ /// # Example
149
+ ///
150
+ /// ```rust
151
+ /// # fn main() { rutie_test::test_ruby!(r#"
152
+ /// function_type = Wasmer::FunctionType.new(
153
+ /// [Wasmer::Type::I32, Wasmer::Type::I64],
154
+ /// [Wasmer::Type::I32]
155
+ /// )
156
+ ///
157
+ /// assert { function_type.results == [Wasmer::Type::I32] }
158
+ /// # "#); }
159
+ /// ```
160
+ pub fn results(&self) -> Array<Type> {
161
+ x!()
162
+ }
163
+ }
164
+
165
+ /// A descriptor for a WebAssembly memory type.
166
+ ///
167
+ /// Memories are described in units of pages (64Kb) and represent
168
+ /// contiguous chunks of addressable memory.
169
+ pub struct MemoryType;
170
+
171
+ impl MemoryType {
172
+ /// Creates a new `MemoryType`.
173
+ ///
174
+ /// # Example
175
+ ///
176
+ /// ```rust
177
+ /// # fn main() { rutie_test::test_ruby!(r#"
178
+ /// memory_type = Wasmer::MemoryType.new 1, 3, true
179
+ /// # "#); }
180
+ /// ```
181
+ pub fn new(minimum: Integer, maximum: Option<Integer>, shared: Boolean) -> Self {
182
+ x!()
183
+ }
184
+
185
+ /// Returns the minimum size of the memory.
186
+ ///
187
+ /// # Example
188
+ ///
189
+ /// ```rust
190
+ /// # fn main() { rutie_test::test_ruby!(r#"
191
+ /// memory_type = Wasmer::MemoryType.new 1, 3, true
192
+ ///
193
+ /// assert { memory_type.minimum == 1 }
194
+ /// # "#); }
195
+ /// ```
196
+ pub fn minimum(&self) -> Integer {
197
+ x!()
198
+ }
199
+
200
+ /// Returns the maximum size of the memory of any.
201
+ ///
202
+ /// # Example
203
+ ///
204
+ /// ```rust
205
+ /// # fn main() { rutie_test::test_ruby!(r#"
206
+ /// memory_type = Wasmer::MemoryType.new 1, 3, true
207
+ ///
208
+ /// assert { memory_type.maximum == 3 }
209
+ /// # "#); }
210
+ /// ```
211
+ pub fn maximum(&self) -> Option<Integer> {
212
+ x!()
213
+ }
214
+
215
+ /// Returns whether the memory is shared or not.
216
+ ///
217
+ /// # Example
218
+ ///
219
+ /// ```rust
220
+ /// # fn main() { rutie_test::test_ruby!(r#"
221
+ /// memory_type = Wasmer::MemoryType.new 1, 3, true
222
+ ///
223
+ /// assert { memory_type.shared? }
224
+ /// # "#); }
225
+ /// ```
226
+ pub fn shared(&self) -> Integer {
227
+ x!()
228
+ }
229
+ }
230
+
231
+ /// A descriptor for a WebAssembly global.
232
+ pub struct GlobalType;
233
+
234
+ impl GlobalType {
235
+ /// Creates a new `GlobalType`.
236
+ ///
237
+ /// # Example
238
+ ///
239
+ /// ```rust
240
+ /// # fn main() { rutie_test::test_ruby!(r#"
241
+ /// global_type = Wasmer::GlobalType.new Wasmer::Type::I32, true
242
+ /// # "#); }
243
+ /// ```
244
+ pub fn new(r#type: Type, mutable: Boolean) -> Self {
245
+ x!()
246
+ }
247
+
248
+ /// Returns the type of the global.
249
+ ///
250
+ /// # Example
251
+ ///
252
+ /// ```rust
253
+ /// # fn main() { rutie_test::test_ruby!(r#"
254
+ /// global_type = Wasmer::GlobalType.new Wasmer::Type::I32, true
255
+ ///
256
+ /// assert { global_type.type == Wasmer::Type::I32 }
257
+ /// # "#); }
258
+ /// ```
259
+ pub fn r#type(&self) -> Type {
260
+ x!()
261
+ }
262
+
263
+ /// Returns whether the global is mutable.
264
+ ///
265
+ /// # Example
266
+ ///
267
+ /// ```rust
268
+ /// # fn main() { rutie_test::test_ruby!(r#"
269
+ /// global_type = Wasmer::GlobalType.new Wasmer::Type::I32, true
270
+ ///
271
+ /// assert { global_type.mutable? }
272
+ /// # "#); }
273
+ /// ```
274
+ pub fn mutable(&self) -> Boolean {
275
+ x!()
276
+ }
277
+ }
278
+
279
+ /// A descriptor for a table in a WebAssembly module.
280
+ ///
281
+ /// Tables are contiguous chunks of a specific element, typically
282
+ /// a funcref or externref. The most common use for tables is a
283
+ /// function table through which call_indirect can invoke other
284
+ /// functions.
285
+ pub struct TableType;
286
+
287
+ impl TableType {
288
+ /// Creates a new `TableType`.
289
+ ///
290
+ /// # Example
291
+ ///
292
+ /// ```rust
293
+ /// # fn main() { rutie_test::test_ruby!(r#"
294
+ /// table_type = Wasmer::TableType.new Wasmer::Type::I32, 7, 42
295
+ /// # "#); }
296
+ /// ```
297
+ pub fn new(r#type: Type, minimum: Integer, maximum: Option<Integer>) -> Self {
298
+ x!()
299
+ }
300
+
301
+ /// Returns the type of table.
302
+ ///
303
+ /// # Example
304
+ ///
305
+ /// ```rust
306
+ /// # fn main() { rutie_test::test_ruby!(r#"
307
+ /// table_type = Wasmer::TableType.new Wasmer::Type::I32, 7, 42
308
+ ///
309
+ /// assert { table_type.type == Wasmer::Type::I32 }
310
+ /// # "#); }
311
+ /// ```
312
+ pub fn r#type(&self) -> Type {
313
+ x!()
314
+ }
315
+
316
+ /// Returns the minimum size of the table.
317
+ ///
318
+ /// # Example
319
+ ///
320
+ /// ```rust
321
+ /// # fn main() { rutie_test::test_ruby!(r#"
322
+ /// table_type = Wasmer::TableType.new Wasmer::Type::I32, 7, 42
323
+ ///
324
+ /// assert { table_type.minimum == 7 }
325
+ /// # "#); }
326
+ /// ```
327
+ pub fn minimum(&self) -> Integer {
328
+ x!()
329
+ }
330
+
331
+ /// Returns the maximum size of the table if any.
332
+ ///
333
+ /// # Example
334
+ ///
335
+ /// ```rust
336
+ /// # fn main() { rutie_test::test_ruby!(r#"
337
+ /// table_type = Wasmer::TableType.new Wasmer::Type::I32, 7, 42
338
+ ///
339
+ /// assert { table_type.maximum == 42 }
340
+ /// # "#); }
341
+ /// ```
342
+ pub fn maximum(&self) -> Option<Integer> {
343
+ x!()
344
+ }
345
+ }
346
+
347
+ /// Represents the type of a module's export (not to be confused
348
+ /// with an export of an instance). It is usually built from the
349
+ /// [`Module::exports`] getter.
350
+ pub struct ExportType;
351
+
352
+ impl ExportType {
353
+ /// Creates a new `ExportType`.
354
+ ///
355
+ /// `type` must be of type [`FunctionType`], [`MemoryType`],
356
+ /// [`GlobalType`] or [`TableType`].
357
+ ///
358
+ /// # Example
359
+ ///
360
+ /// ```rust,ignore
361
+ /// # fn main() { rutie_test::test_ruby!(r#"
362
+ /// export_type = Wasmer::ExportType.new "foo", Wasmer::Function.new([Wasmer::Type::I32], [])
363
+ /// # "#); }
364
+ /// ```
365
+ pub fn new(name: String, r#type: Any) -> Self {
366
+ x!()
367
+ }
368
+
369
+ /// Returns the name of the export.
370
+ ///
371
+ /// # Example
372
+ ///
373
+ /// ```rust,ignore
374
+ /// # fn main() { rutie_test::test_ruby!(r#"
375
+ /// export_type = Wasmer::ExportType.new "foo", Wasmer::Function.new([Wasmer::Type::I32], [])
376
+ ///
377
+ /// assert { export_type.name == "foo" }
378
+ /// # "#); }
379
+ /// ```
380
+ pub fn name(&self) -> String {
381
+ x!()
382
+ }
383
+
384
+ /// Returns the type of the export.
385
+ ///
386
+ /// # Example
387
+ ///
388
+ /// ```rust,ignore
389
+ /// # fn main() { rutie_test::test_ruby!(r#"
390
+ /// export_type = Wasmer::ExportType.new "foo", Wasmer::Function.new([Wasmer::Type::I32], [])
391
+ ///
392
+ /// assert { export_type.type == Wasmer::Type::I32 }
393
+ /// # "#); }
394
+ /// ```
395
+ pub fn r#type(&self) -> Type {
396
+ x!()
397
+ }
398
+ }
399
+
400
+ /// Represents the type of a module's import. It is usually built
401
+ /// from the [`Module::imports`] getter.
402
+ pub struct ImportType;
403
+
404
+ impl ImportType {
405
+ /// Creates a new `ImportType`.
406
+ ///
407
+ /// `type` must be of type [`FunctionType`], [`MemoryType`],
408
+ /// [`GlobalType`] or [`TableType`].
409
+ ///
410
+ /// # Example
411
+ ///
412
+ /// ```rust,ignore
413
+ /// # fn main() { rutie_test::test_ruby!(r#"
414
+ /// import_type = Wasmer::ImportType.new "foo", "bar", Wasmer::Function.new([Wasmer::Type::I32], [])
415
+ /// # "#); }
416
+ /// ```
417
+ pub fn new(module: String, name: String, r#type: Any) -> Self {
418
+ x!()
419
+ }
420
+
421
+ /// Returns the module's name of the import.
422
+ ///
423
+ /// # Example
424
+ ///
425
+ /// ```rust,ignore
426
+ /// # fn main() { rutie_test::test_ruby!(r#"
427
+ /// import_type = Wasmer::ImportType.new "foo", "bar", Wasmer::Function.new([Wasmer::Type::I32], [])
428
+ /// # "#); }
429
+ ///
430
+ /// assert { import_type.module == "foo" }
431
+ /// ```
432
+ pub fn module(&self) -> String {
433
+ x!()
434
+ }
435
+
436
+ /// Returns the name of the import.
437
+ ///
438
+ /// # Example
439
+ ///
440
+ /// ```rust,ignore
441
+ /// # fn main() { rutie_test::test_ruby!(r#"
442
+ /// import_type = Wasmer::ImportType.new "foo", "bar", Wasmer::Function.new([Wasmer::Type::I32], [])
443
+ /// # "#); }
444
+ ///
445
+ /// assert { import_type.name == "bar" }
446
+ /// ```
447
+ pub fn name(&self) -> String {
448
+ x!()
449
+ }
450
+
451
+ /// Returns the type of the import.
452
+ ///
453
+ /// # Example
454
+ ///
455
+ /// ```rust,ignore
456
+ /// # fn main() { rutie_test::test_ruby!(r#"
457
+ /// import_type = Wasmer::ImportType.new "foo", "bar", Wasmer::Function.new([Wasmer::Type::I32], [])
458
+ /// # "#); }
459
+ ///
460
+ /// assert { import_type.type == Wasmer::Type::I32 }
461
+ /// ```
462
+ pub fn r#type(&self) -> Type {
463
+ x!()
464
+ }
465
+ }
466
+
467
+ /// The store represents all global state that can be manipulated
468
+ /// by WebAssembly programs. It consists of the runtime
469
+ /// representation of all instances of functions, tables,
470
+ /// memories, and globals that have been allocated during the
471
+ /// lifetime of the abstract machine.
472
+ ///
473
+ /// The `Store` holds the engine (that is —amongst many things— used
474
+ /// to compile the WebAssembly bytes into a valid module
475
+ /// artifact), in addition to the Tunables (that are used to
476
+ /// create the memories, tables and globals). For the moment, it's
477
+ /// not possible to tweak the engines and the compilers.
478
+ ///
479
+ /// Specification: <https://webassembly.github.io/spec/core/exec/runtime.html#store>
480
+ ///
481
+ /// # Example
482
+ ///
483
+ /// Use the store with the default engine and the default compiler:
484
+ ///
485
+ /// ```rust
486
+ /// # fn main() { rutie_test::test_ruby!(r#"
487
+ /// store = Wasmer::Store.new
488
+ /// # "#); }
489
+ /// ```
490
+ pub struct Store;
491
+
492
+ impl Store {
493
+ /// Creates a new `Store`.
494
+ pub fn new() -> Self {
495
+ x!()
496
+ }
497
+ }
498
+
499
+ /// A WebAssembly module contains stateless WebAssembly code that has
500
+ /// already been compiled and can be instantiated multiple times.
501
+ ///
502
+ /// Creates a new WebAssembly `Module` given the configuration in the
503
+ /// store.
504
+ ///
505
+ /// If the provided bytes are not WebAssembly-like (start with
506
+ /// b"\0asm"), this function will try to to convert the bytes assuming
507
+ /// they correspond to the WebAssembly text format.
508
+ ///
509
+ /// # Security
510
+ ///
511
+ /// Before the code is compiled, it will be validated using the store
512
+ /// features.
513
+ ///
514
+ /// # Example
515
+ ///
516
+ /// ```rust
517
+ /// # fn main() { rutie_test::test_ruby!(r#"
518
+ /// store = Wasmer::Store.new
519
+ ///
520
+ /// ## Let's compile WebAssembly from bytes.
521
+ /// wasm_bytes = "\x00asm\x01\x00\x00\x00";
522
+ /// module_ = Wasmer::Module.new store, wasm_bytes
523
+ ///
524
+ /// ## Let's compile WebAssembly from WAT.
525
+ /// module_ = Wasmer::Module.new store, "(module)"
526
+ /// # "#); }
527
+ /// ```
528
+ pub struct Module;
529
+
530
+ impl Module {
531
+ /// Validates a new WebAssembly Module given the configuration
532
+ /// in the [`Store`].
533
+ ///
534
+ /// This validation is normally pretty fast and checks the
535
+ /// enabled WebAssembly features in the Store engine to assure
536
+ /// deterministic validation of the `Module`.
537
+ ///
538
+ /// # Example
539
+ ///
540
+ /// ```rust
541
+ /// # fn main() { rutie_test::test_ruby!(r#"
542
+ /// wasm_bytes = "\x00asm\x01\x00\x00\x00";
543
+ /// Wasmer::Module.validate Wasmer::Store.new, wasm_bytes
544
+ /// # "#); }
545
+ /// ```
546
+ pub fn validate(store: Store, bytes: String) -> Boolean {
547
+ x!()
548
+ }
549
+
550
+ /// Creates a new [`Module`].
551
+ pub fn new(store: Store, bytes: String) -> Self {
552
+ x!()
553
+ }
554
+
555
+ /// Get or set the current name of the module.
556
+ ///
557
+ /// This name is normally set in the WebAssembly bytecode by
558
+ /// some compilers, but can be also overwritten.
559
+ ///
560
+ /// Not all modules have a name.
561
+ ///
562
+ /// # Example
563
+ ///
564
+ /// ```rust
565
+ /// # fn main() { rutie_test::test_ruby!(r#"
566
+ /// store = Wasmer::Store.new
567
+ ///
568
+ /// ## Module with an existing name.
569
+ /// assert { Wasmer::Module.new(store, "(module $moduleName)").name == "moduleName" }
570
+ ///
571
+ /// ## Module with no name.
572
+ /// assert { Wasmer::Module.new(store, "(module)").name.nil? }
573
+ ///
574
+ /// ## Change the module's name.
575
+ /// module_ = Wasmer::Module.new store, "(module $moduleName)"
576
+ /// module_.name = "hello"
577
+ ///
578
+ /// assert { module_.name == "hello" }
579
+ /// # "#); }
580
+ /// ```
581
+ pub fn name(&self, name: String) {
582
+ x!()
583
+ }
584
+
585
+ /// Returns a list of [`ExportType`] objects, which represents
586
+ /// all the exports of this module.
587
+ ///
588
+ /// The order of the exports is guaranteed to be the same as
589
+ /// in the WebAssembly bytecode.
590
+ ///
591
+ /// # Example
592
+ ///
593
+ /// See the [`ExportType`] class to learn more.
594
+ pub fn exports(&self) -> Array<ExportType> {
595
+ x!()
596
+ }
597
+
598
+ /// Returns a list of [`ImportType`] objects, which represents
599
+ /// all the imports of this module.
600
+ ///
601
+ /// The order of the imports is guaranteed to be the same as
602
+ /// in the WebAssembly bytecode.
603
+ ///
604
+ /// # Example
605
+ ///
606
+ /// See the [`ImportType`] class to learn more.
607
+ pub fn imports(&self) -> Array<ImportType> {
608
+ x!()
609
+ }
610
+
611
+ /// Get the custom sections of the module given a `name`.
612
+ ///
613
+ /// # Important
614
+ ///
615
+ /// Following the WebAssembly specification, one name can have
616
+ /// multiple custom sections. That's why a list of bytes is
617
+ /// returned rather than bytes.
618
+ ///
619
+ /// Consequently, the empty list represents the absence of a
620
+ /// custom section for the given name.
621
+ ///
622
+ /// # Example
623
+ ///
624
+ /// ```rust,ignore
625
+ /// # fn main() { rutie_test::test_ruby!(r#"
626
+ /// bytes = IO.read "custom_sections.wasm", mode: "rb"
627
+ /// module_ = Wasmer::Module.new Wasmer::Store.new, bytes
628
+ ///
629
+ /// assert { module_.custom_sections("easter_egg") == ["Wasmer"] }
630
+ /// assert { module_.custom_sections("hello") == ["World!"] }
631
+ /// assert { module_.custom_sections("foo") == [] }
632
+ /// # "#); }
633
+ /// ```
634
+ pub fn custom_sections(&self, name: String) -> Array<String> {
635
+ x!()
636
+ }
637
+
638
+ /// Serializes a module into a binary representation that the
639
+ /// engine can later process via [`Module::deserialize`].
640
+ ///
641
+ /// # Example
642
+ ///
643
+ /// ```rust
644
+ /// # fn main() { rutie_test::test_ruby!(r#"
645
+ /// module_ = Wasmer::Module.new Wasmer::Store.new, "(module)"
646
+ /// assert { module_.serialize.is_a?(String) }
647
+ /// # "#); }
648
+ /// ```
649
+ pub fn serialize(&self) -> String {
650
+ x!()
651
+ }
652
+
653
+ /// Deserializes a serialized module binary into a Module.
654
+ ///
655
+ /// **Note**: the module has to be serialized before with the
656
+ /// serialize method.
657
+ ///
658
+ /// # Safety
659
+ ///
660
+ /// This function is inherently unsafe as the provided bytes:
661
+ ///
662
+ /// 1. Are going to be deserialized directly into Rust objects.
663
+ /// 2. Contains the function assembly bodies and, if
664
+ /// intercepted, a malicious actor could inject code into
665
+ /// executable memory.
666
+ ///
667
+ /// And as such, the deserialize method is unsafe.
668
+ ///
669
+ /// # Example
670
+ ///
671
+ /// ```rust
672
+ /// # fn main() { rutie_test::test_ruby!(r#"
673
+ /// store = Wasmer::Store.new
674
+ ///
675
+ /// serialized_module = Wasmer::Module.new(
676
+ /// store,
677
+ /// (<<~WAST)
678
+ /// (module
679
+ /// (func (export "function") (param i32 i64)))
680
+ /// WAST
681
+ /// ).serialize
682
+ ///
683
+ /// module_ = Wasmer::Module.deserialize store, serialized_module
684
+ /// serialized_module = nil
685
+ ///
686
+ /// exports = module_.exports
687
+ ///
688
+ /// assert { exports.length() == 1 }
689
+ /// assert { exports[0].name == "function" }
690
+ /// assert { exports[0].type.is_a?(Wasmer::FunctionType) }
691
+ /// assert { exports[0].type.params == [Wasmer::Type::I32, Wasmer::Type::I64] }
692
+ /// assert { exports[0].type.results == [] }
693
+ /// # "#); }
694
+ /// ```
695
+ pub fn deserialize(bytes: String) -> Self {
696
+ x!()
697
+ }
698
+ }
699
+
700
+ /// A WebAssembly instance is a stateful, executable instance of a
701
+ /// WebAssembly [`Module`].
702
+ ///
703
+ /// Instance objects contain all the exported WebAssembly
704
+ /// functions, memories, tables and globals that allow interacting
705
+ /// with WebAssembly.
706
+ ///
707
+ /// Specification:
708
+ /// <https://webassembly.github.io/spec/core/exec/runtime.html#module-instances>
709
+ ///
710
+ /// # Examples
711
+ ///
712
+ /// Example without an import object. The following creates a
713
+ /// module with a sum exported function that sum two integers.
714
+ ///
715
+ /// ```rust
716
+ /// # fn main() { rutie_test::test_ruby!(r#"
717
+ /// module_ = Wasmer::Module.new(
718
+ /// Wasmer::Store.new,
719
+ /// (<<~WAST)
720
+ /// (module
721
+ /// (type (func (param i32 i32) (result i32)))
722
+ /// (func (type 0)
723
+ /// local.get 0
724
+ /// local.get 1
725
+ /// i32.add)
726
+ /// (export "sum" (func 0)))
727
+ /// WAST
728
+ /// )
729
+ /// instance = Wasmer::Instance.new module_, nil
730
+ ///
731
+ /// assert { instance.exports.sum.(1, 2) == 3 }
732
+ /// # "#); }
733
+ /// ```
734
+ ///
735
+ /// Example with an import object. The following creates a module
736
+ /// that (i) imports a sum function from the `math` namespace, and
737
+ /// (ii) exports an `add_one` function that adds 1 to any given
738
+ /// integer (by using the `math.sum` function).
739
+ ///
740
+ /// ```rust
741
+ /// # fn main() { rutie_test::test_ruby!(r#"
742
+ /// def sum(x, y)
743
+ /// x + y
744
+ /// end
745
+ ///
746
+ /// store = Wasmer::Store.new
747
+ /// module_ = Wasmer::Module.new(
748
+ /// store,
749
+ /// (<<~WAST)
750
+ /// (module
751
+ /// (import "math" "sum" (func $sum (param i32 i32) (result i32)))
752
+ /// (func (export "add_one") (param i32) (result i32)
753
+ /// local.get 0
754
+ /// i32.const 1
755
+ /// call $sum))
756
+ /// WAST
757
+ /// )
758
+ ///
759
+ /// import_object = Wasmer::ImportObject.new
760
+ /// import_object.register(
761
+ /// "math",
762
+ /// {
763
+ /// :sum => Wasmer::Function.new(
764
+ /// store,
765
+ /// method(:sum),
766
+ /// Wasmer::FunctionType.new([Wasmer::Type::I32, Wasmer::Type::I32], [Wasmer::Type::I32])
767
+ /// )
768
+ /// }
769
+ /// )
770
+ ///
771
+ /// instance = Wasmer::Instance.new module_, import_object
772
+ ///
773
+ /// assert { instance.exports.add_one.(1) == 2 }
774
+ /// # "#); }
775
+ /// ```
776
+ pub struct Instance;
777
+
778
+ impl Instance {
779
+ /// Creates a new `Instance`.
780
+ pub fn new(module: Module, import_object: ImportObject) -> Self {
781
+ x!()
782
+ }
783
+
784
+ /// Returns all the exported entities.
785
+ pub fn exports(&self) -> Exports {
786
+ x!()
787
+ }
788
+ }
789
+
790
+ /// Represents all the exports of an instance. It is built by [`Instance::exports`].
791
+ ///
792
+ /// Exports can be of kind [`Function`], [`Global`], [`Table`], or [`Memory`].
793
+ pub struct Exports;
794
+
795
+ impl Exports {
796
+ /// Returns the number of exports.
797
+ pub fn length(&self) -> Integer {
798
+ x!()
799
+ }
800
+
801
+ /// Returns either a [`Function`], a [`Memory`], a [`Global`],
802
+ /// or a [`Table`] if the name for the export exists.
803
+ ///
804
+ /// # Example
805
+ ///
806
+ /// ```rust
807
+ /// # fn main() { rutie_test::test_ruby!(r#"
808
+ /// module_ = Wasmer::Module.new(
809
+ /// Wasmer::Store.new,
810
+ /// (<<~WAST)
811
+ /// (module
812
+ /// (func (export "func") (param i32 i64))
813
+ /// (global (export "glob") i32 (i32.const 7))
814
+ /// (table (export "tab") 0 funcref)
815
+ /// (memory (export "mem") 1))
816
+ /// WAST
817
+ /// )
818
+ /// instance = Wasmer::Instance.new module_, nil
819
+ /// exports = instance.exports
820
+ ///
821
+ /// assert { exports.respond_to? :func }
822
+ /// assert { exports.respond_to? :glob }
823
+ /// assert { exports.respond_to? :tab }
824
+ /// assert { exports.respond_to? :mem }
825
+ /// assert { not(exports.respond_to? :foo) }
826
+ ///
827
+ /// assert { exports.func.is_a?(Wasmer::Function) }
828
+ /// assert { exports.mem.is_a?(Wasmer::Memory) }
829
+ /// assert { exports.glob.is_a?(Wasmer::Global) }
830
+ /// assert { exports.tab.is_a?(Wasmer::Table) }
831
+ /// # "#); }
832
+ /// ```
833
+ pub fn method_missing(name: String) -> Any {
834
+ x!()
835
+ }
836
+ }
837
+
838
+ /// An `ImportObject` represents all of the import data used when
839
+ /// instantiating a WebAssembly module.
840
+ ///
841
+ /// # Example
842
+ ///
843
+ /// Importing a function, `math.sum`, and call it through the
844
+ /// exported `add_one` function:
845
+ ///
846
+ /// ```rust
847
+ /// # fn main() { rutie_test::test_ruby!(r#"
848
+ /// def sum(x, y)
849
+ /// x + y
850
+ /// end
851
+ ///
852
+ /// store = Wasmer::Store.new
853
+ /// module_ = Wasmer::Module.new(
854
+ /// store,
855
+ /// (<<~WAST)
856
+ /// (module
857
+ /// (import "math" "sum" (func $sum (param i32 i32) (result i32)))
858
+ /// (func (export "add_one") (param i32) (result i32)
859
+ /// local.get 0
860
+ /// i32.const 1
861
+ /// call $sum))
862
+ /// WAST
863
+ /// )
864
+ ///
865
+ /// import_object = Wasmer::ImportObject.new
866
+ /// import_object.register(
867
+ /// "math",
868
+ /// {
869
+ /// :sum => Wasmer::Function.new(
870
+ /// store,
871
+ /// method(:sum),
872
+ /// Wasmer::FunctionType.new([Wasmer::Type::I32, Wasmer::Type::I32], [Wasmer::Type::I32])
873
+ /// )
874
+ /// }
875
+ /// )
876
+ ///
877
+ /// instance = Wasmer::Instance.new module_, import_object
878
+ ///
879
+ /// assert { instance.exports.add_one.(1) == 2 }
880
+ /// # "#); }
881
+ /// ```
882
+ ///
883
+ /// Importing a memory:
884
+ ///
885
+ /// ```rust
886
+ /// # fn main() { rutie_test::test_ruby!(r#"
887
+ /// store = Wasmer::Store.new
888
+ /// module_ = Wasmer::Module.new(
889
+ /// store,
890
+ /// (<<~WAST)
891
+ /// (module
892
+ /// (import "env" "memory" (memory $memory 1))
893
+ /// (func (export "increment")
894
+ /// i32.const 0
895
+ /// i32.const 0
896
+ /// i32.load ;; load 0
897
+ /// i32.const 1
898
+ /// i32.add ;; add 1
899
+ /// i32.store ;; store at 0
900
+ /// ))
901
+ /// WAST
902
+ /// )
903
+ ///
904
+ /// memory = Wasmer::Memory.new store, Wasmer::MemoryType.new(1, nil, false)
905
+ /// view = memory.uint8_view(0)
906
+ ///
907
+ /// import_object = Wasmer::ImportObject.new
908
+ /// import_object.register(
909
+ /// "env",
910
+ /// {
911
+ /// :memory => memory,
912
+ /// }
913
+ /// )
914
+ ///
915
+ /// instance = Wasmer::Instance.new module_, import_object
916
+ ///
917
+ /// assert { view[0] == 0 }
918
+ ///
919
+ /// instance.exports.increment.()
920
+ /// assert { view[0] == 1 }
921
+ ///
922
+ /// instance.exports.increment.()
923
+ /// assert { view[0] == 2 }
924
+ /// # "#); }
925
+ /// ```
926
+ ///
927
+ /// Importing a global:
928
+ ///
929
+ /// ```rust
930
+ /// # fn main() { rutie_test::test_ruby!(r#"
931
+ /// store = Wasmer::Store.new
932
+ /// module_ = Wasmer::Module.new(
933
+ /// store,
934
+ /// (<<~WAST)
935
+ /// (module
936
+ /// (import "env" "global" (global $global (mut i32)))
937
+ /// (func (export "read_g") (result i32)
938
+ /// global.get $global)
939
+ /// (func (export "write_g") (param i32)
940
+ /// local.get 0
941
+ /// global.set $global))
942
+ /// WAST
943
+ /// )
944
+ ///
945
+ /// global = Wasmer::Global.new store, Wasmer::Value.i32(7), true
946
+ ///
947
+ /// import_object = Wasmer::ImportObject.new
948
+ /// import_object.register(
949
+ /// "env",
950
+ /// {
951
+ /// :global => global
952
+ /// }
953
+ /// )
954
+ ///
955
+ /// instance = Wasmer::Instance.new module_, import_object
956
+ ///
957
+ /// assert { instance.exports.read_g.() == 7 }
958
+ ///
959
+ /// global.value = 153
960
+ /// assert { instance.exports.read_g.() == 153 }
961
+ ///
962
+ /// instance.exports.write_g.(11)
963
+ /// assert { global.value == 11 }
964
+ /// # "#); }
965
+ /// ```
966
+ ///
967
+ /// etc.
968
+ pub struct ImportObject;
969
+
970
+ impl ImportObject {
971
+ /// Creates a new `ImportObject`.
972
+ pub fn new() -> Self {
973
+ x!()
974
+ }
975
+
976
+ /// Checks whether the import object contains a specific
977
+ /// namespace.
978
+ pub fn contains_namespace(&self, namespace_name: String) -> Boolean {
979
+ x!()
980
+ }
981
+
982
+ /// Registers a set of [`Function`], [`Memory`], [`Global`] or
983
+ /// [`Table`] to a particular namespace.
984
+ ///
985
+ /// See the [`ImportObject`]'s documentation to see more
986
+ /// examples.
987
+ pub fn register(&self, namespace_name: String, namespace: Hash<String, Any>) {
988
+ x!()
989
+ }
990
+ }
991
+
992
+ /// Represents a WebAssembly function instance.
993
+ ///
994
+ /// A function instance is the runtime representation of a
995
+ /// function. It effectively is a closure of the original function
996
+ /// (defined in either the host or the WebAssembly module) over
997
+ /// the runtime [`Instance`] of its originating [`Module`].
998
+ ///
999
+ /// The module instance is used to resolve references to other
1000
+ /// definitions during executing of the function.
1001
+ ///
1002
+ /// Specification:
1003
+ /// <https://webassembly.github.io/spec/core/exec/runtime.html#function-instances>
1004
+ ///
1005
+ /// Note that the function can be invoked/called by the host only
1006
+ /// when it is an exported function (see [`Exports`] to see an
1007
+ /// example).
1008
+ ///
1009
+ /// # Example
1010
+ ///
1011
+ /// To build a `Function`, we need its type. `Function`
1012
+ /// understands `Symbol`, `Proc`, and `Lambda`.
1013
+ ///
1014
+ /// First, a function through a symbol:
1015
+ ///
1016
+ /// ```rust
1017
+ /// # fn main() { rutie_test::test_ruby!(r#"
1018
+ /// def foo(x)
1019
+ /// x + 1
1020
+ /// end
1021
+ ///
1022
+ /// function = Wasmer::Function.new(
1023
+ /// Wasmer::Store.new,
1024
+ /// ## A symbol.
1025
+ /// method(:foo),
1026
+ /// Wasmer::FunctionType.new([Wasmer::Type::I32], [])
1027
+ /// )
1028
+ /// # "#); }
1029
+ /// ```
1030
+ ///
1031
+ /// Second, a function through a proc as a lambda:
1032
+ ///
1033
+ /// ```rust
1034
+ /// # fn main() { rutie_test::test_ruby!(r#"
1035
+ /// function = Wasmer::Function.new(
1036
+ /// Wasmer::Store.new,
1037
+ /// ## A lambda.
1038
+ /// -> (x) { x + 1 },
1039
+ /// Wasmer::FunctionType.new([Wasmer::Type::I32], [])
1040
+ /// )
1041
+ /// # "#); }
1042
+ /// ```
1043
+ ///
1044
+ /// Third, a function through a proc:
1045
+ ///
1046
+ /// ```rust
1047
+ /// # fn main() { rutie_test::test_ruby!(r#"
1048
+ /// function = Wasmer::Function.new(
1049
+ /// Wasmer::Store.new,
1050
+ /// ## A proc.
1051
+ /// Proc.new { |x| x + 1 },
1052
+ /// Wasmer::FunctionType.new([Wasmer::Type::I32], [])
1053
+ /// )
1054
+ /// # "#); }
1055
+ /// ```
1056
+ pub struct Function;
1057
+
1058
+ impl Function {
1059
+ /// Creates a new `Function`. The `function` can be of kind
1060
+ /// `Symbol`, `Proc` or `Lambda`.
1061
+ pub fn new(store: Store, function: Any, function_type: FunctionType) -> Self {
1062
+ x!()
1063
+ }
1064
+
1065
+ /// Calls the function with arguments. It returns zero or more results.
1066
+ pub fn call(x0: Any, x1: Any, x2: Any, etc: Any) -> Any {
1067
+ x!()
1068
+ }
1069
+
1070
+ /// Returns the function type.
1071
+ pub fn r#type(&self) -> FunctionType {
1072
+ x!()
1073
+ }
1074
+ }
1075
+
1076
+ /// A WebAssembly memory instance.
1077
+ ///
1078
+ /// A memory instance is the runtime representation of a linear
1079
+ /// memory. It consists of a vector of bytes and an optional
1080
+ /// maximum size.
1081
+ ///
1082
+ /// The length of the vector always is a multiple of the
1083
+ /// WebAssembly page size, which is defined to be the constant
1084
+ /// 65536 – abbreviated 64Ki. Like in a memory type, the maximum
1085
+ /// size in a memory instance is given in units of this page size.
1086
+ ///
1087
+ /// A memory created by the host or in WebAssembly code will be
1088
+ /// accessible and mutable from both host and WebAssembly.
1089
+ ///
1090
+ /// Specification: <https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances>
1091
+ ///
1092
+ /// # Example
1093
+ ///
1094
+ /// Creates a [`Memory`] from scratch:
1095
+ ///
1096
+ /// ```rust
1097
+ /// # fn main() { rutie_test::test_ruby!(r#"
1098
+ /// store = Wasmer::Store.new
1099
+ /// memory_type = Wasmer::MemoryType.new 3, 10, true
1100
+ /// memory = Wasmer::Memory.new store, memory_type
1101
+ ///
1102
+ /// assert { memory.size == 3 }
1103
+ /// # "#); }
1104
+ /// ```
1105
+ ///
1106
+ /// Gets a memory from the exports of an instance:
1107
+ ///
1108
+ /// ```rust,ignore
1109
+ /// # fn main() { rutie_test::test_ruby!(r#"
1110
+ /// module_ = Wasmer::Module.new Wasmer::Store.new, wasm_bytes
1111
+ /// instance = Wasmer::Instance.new module, nil
1112
+ ///
1113
+ /// memory = instance.exports.memory
1114
+ /// # "#); }
1115
+ /// ```
1116
+ pub struct Memory;
1117
+
1118
+ impl Memory {
1119
+ /// Creates a new `Memory`.
1120
+ pub fn new(store: Store, memory_type: MemoryType) -> Self {
1121
+ x!()
1122
+ }
1123
+
1124
+ /// Returns the memory type.
1125
+ pub fn r#type(&self) -> MemoryType {
1126
+ x!()
1127
+ }
1128
+
1129
+ /// Returns the size (in pages) of the memory.
1130
+ pub fn size(&self) -> Integer {
1131
+ x!()
1132
+ }
1133
+
1134
+ /// Returns the size (in bytes) of the memory.
1135
+ pub fn data_size(&self) -> Integer {
1136
+ x!()
1137
+ }
1138
+
1139
+ /// Grows memory by the specified amount of WebAssembly pages.
1140
+ ///
1141
+ /// # Example
1142
+ ///
1143
+ /// ```rust,ignore
1144
+ /// # fn main() { rutie_test::test_ruby!(r#"
1145
+ /// memory = instance.exports.memory
1146
+ /// old_memory_size = memory.data_size
1147
+ ///
1148
+ /// memory.grow 1
1149
+ ///
1150
+ /// memory_size = memory.data_size
1151
+ ///
1152
+ /// assert { memory_size == 1179648 }
1153
+ /// assert { memory_size - old_memory_size == 65536 }
1154
+ /// # "#); }
1155
+ /// ```
1156
+ pub fn grow(&self, number_of_pages: Integer) -> Integer {
1157
+ x!()
1158
+ }
1159
+
1160
+ /// Creates a read-and-write view over the memory data where
1161
+ /// elements are of kind `uint8`.
1162
+ pub fn uint8_view(&self) -> Uint8View {
1163
+ x!()
1164
+ }
1165
+
1166
+ /// Creates a read-and-write view over the memory data where
1167
+ /// elements are of kind `int8`.
1168
+ pub fn int8_view(&self) -> Int8View {
1169
+ x!()
1170
+ }
1171
+
1172
+ /// Creates a read-and-write view over the memory data where
1173
+ /// elements are of kind `uint16`.
1174
+ pub fn uint16_view(&self) -> Uint16View {
1175
+ x!()
1176
+ }
1177
+
1178
+ /// Creates a read-and-write view over the memory data where
1179
+ /// elements are of kind `int16`.
1180
+ pub fn int16_view(&self) -> Int16View {
1181
+ x!()
1182
+ }
1183
+
1184
+ /// Creates a read-and-write view over the memory data where
1185
+ /// elements are of kind `uint32`.
1186
+ pub fn uint32_view(&self) -> Uint32View {
1187
+ x!()
1188
+ }
1189
+
1190
+ /// Creates a read-and-write view over the memory data where
1191
+ /// elements are of kind `int32`.
1192
+ pub fn int32_view(&self) -> Int32View {
1193
+ x!()
1194
+ }
1195
+ }
1196
+
1197
+ pub struct Uint8View;
1198
+ pub struct Int8View;
1199
+ pub struct Uint16View;
1200
+ pub struct Int16View;
1201
+ pub struct Uint32View;
1202
+ pub struct Int32View;
1203
+
1204
+ /// Represents a WebAssembly global instance.
1205
+ ///
1206
+ /// A global instance is the runtime representation of a global
1207
+ /// variable. It consists of an individual value and a flag
1208
+ /// indicating whether it is mutable.
1209
+ ///
1210
+ /// Specification: <https://webassembly.github.io/spec/core/exec/runtime.html#global-instances>
1211
+ ///
1212
+ /// # Example
1213
+ ///
1214
+ /// ```rust
1215
+ /// # fn main() { rutie_test::test_ruby!(r#"
1216
+ /// store = Wasmer::Store.new
1217
+ /// global = Wasmer::Global.new store, Wasmer::Value.i32(42), false
1218
+ ///
1219
+ /// assert { global.value == 42 }
1220
+ ///
1221
+ /// type = global.type
1222
+ ///
1223
+ /// assert { type.type == Wasmer::Type::I32 }
1224
+ /// assert { type.mutable? == false }
1225
+ /// # "#); }
1226
+ /// ```
1227
+ pub struct Global;
1228
+
1229
+ impl Global {
1230
+ /// Creates a new `Global`.
1231
+ pub fn new(store: Store, value: Value, mutable: Boolean) -> Self {
1232
+ x!()
1233
+ }
1234
+
1235
+ /// Returns whether the global is muable.
1236
+ pub fn mutable(&self) -> Boolean {
1237
+ x!()
1238
+ }
1239
+
1240
+ /// Get or set a new value to the global if mutable.
1241
+ ///
1242
+ /// # Example
1243
+ ///
1244
+ /// ```rust
1245
+ /// # fn main() { rutie_test::test_ruby!(r#"
1246
+ /// store = Wasmer::Store.new
1247
+ /// global = Wasmer::Global.new store, Wasmer::Value.i32(42), true
1248
+ ///
1249
+ /// assert { global.value == 42 }
1250
+ ///
1251
+ /// type = global.type
1252
+ ///
1253
+ /// assert { type.type == Wasmer::Type::I32 }
1254
+ /// assert { type.mutable? == true }
1255
+ ///
1256
+ /// global.value = 153
1257
+ ///
1258
+ /// assert { global.value == 153 }
1259
+ /// # "#); }
1260
+ /// ```
1261
+ pub fn value(&self, value: Any) -> Any {
1262
+ x!()
1263
+ }
1264
+
1265
+ /// Returns the global type.
1266
+ pub fn r#type(&self) -> GlobalType {
1267
+ x!()
1268
+ }
1269
+ }
1270
+
1271
+ /// A WebAssembly table instance.
1272
+ ///
1273
+ /// The Table class is an array-like structure representing a
1274
+ /// WebAssembly table, which stores function references.
1275
+ ///
1276
+ /// A table created by the host or in WebAssembly code will be
1277
+ /// accessible and mutable from both host and WebAssembly.
1278
+ ///
1279
+ /// Specification: <https://webassembly.github.io/spec/core/exec/runtime.html#table-instances>
1280
+ pub struct Table;
1281
+
1282
+ impl Table {
1283
+ /// Creates a new `Table`.
1284
+ pub fn new(store: Store, table_type: TableType, initia_value: Value) -> Self {
1285
+ x!()
1286
+ }
1287
+ }
1288
+
1289
+ /// Represents a WebAssembly value of a specific type.
1290
+ ///
1291
+ /// Most of the time, the types for WebAssembly values will be
1292
+ /// inferred. When it's not possible, the `Value` class is
1293
+ /// necessary.
1294
+ pub struct Value;
1295
+
1296
+ impl Value {
1297
+ /// Creates a new `Value` containing a `int32`.
1298
+ ///
1299
+ /// # Example
1300
+ ///
1301
+ /// ```rust
1302
+ /// # fn main() { rutie_test::test_ruby!(r#"
1303
+ /// Wasmer::Value.i32(7)
1304
+ /// # "#); }
1305
+ /// ```
1306
+ pub fn i32(value: Integer) -> Self {
1307
+ x!()
1308
+ }
1309
+
1310
+ /// Creates a new `Value` containing a `int64`.
1311
+ ///
1312
+ /// # Example
1313
+ ///
1314
+ /// ```rust
1315
+ /// # fn main() { rutie_test::test_ruby!(r#"
1316
+ /// Wasmer::Value.i64(7)
1317
+ /// # "#); }
1318
+ /// ```
1319
+ pub fn i64(value: Integer) -> Self {
1320
+ x!()
1321
+ }
1322
+
1323
+ /// Creates a new `Value` containing a `float32`.
1324
+ ///
1325
+ /// # Example
1326
+ ///
1327
+ /// ```rust
1328
+ /// # fn main() { rutie_test::test_ruby!(r#"
1329
+ /// Wasmer::Value.f32(4.2)
1330
+ /// # "#); }
1331
+ /// ```
1332
+ pub fn f32(value: Float) -> Self {
1333
+ x!()
1334
+ }
1335
+
1336
+ /// Creates a new `Value` containing a `float64`.
1337
+ ///
1338
+ /// # Example
1339
+ ///
1340
+ /// ```rust
1341
+ /// # fn main() { rutie_test::test_ruby!(r#"
1342
+ /// Wasmer::Value.f64(4.2)
1343
+ /// # "#); }
1344
+ /// ```
1345
+ pub fn f64(value: Float) -> Self {
1346
+ x!()
1347
+ }
1348
+ }
1349
+
1350
+ /// Wasmer's [WASI] implementation.
1351
+ ///
1352
+ /// From the user perspective, WASI is a bunch of imports. To
1353
+ /// generate the appropriated imports, you can use
1354
+ /// [`StateBuilder`](Wasi::StateBuilder) to build an
1355
+ /// [`Environment`](Wasi::Environment). This environment holds the
1356
+ /// WASI memory, and can be used to generate a valid
1357
+ /// [`ImportObject`]. This last one can be passed to [`Instance`]
1358
+ /// to instantiate a [`Module`] that needs WASI support.
1359
+ ///
1360
+ /// [WASI]: https://github.com/WebAssembly/WASI
1361
+ ///
1362
+ /// # Example
1363
+ ///
1364
+ /// ```rust,ignore
1365
+ /// # fn main() { rutie_test::test_ruby!(r#"
1366
+ /// store = Wasmer::Store.new
1367
+ /// module_ = Wasmer::Module.new store, bytes
1368
+ ///
1369
+ /// ## Get the WASI version.
1370
+ /// wasi_version = Wasmer::Wasi::get_version module_, true
1371
+ ///
1372
+ /// ## Build a WASI environment for the imports.
1373
+ /// wasi_env = Wasmer::Wasi::StateBuilder.new("test-program")
1374
+ /// .argument("--foo")
1375
+ /// .environments({"ABC" => "DEF", "X" => "YZ"})
1376
+ /// .map_directory("the_host_directory", ".")
1377
+ /// .finalize
1378
+ ///
1379
+ /// ## Generate an `ImportObject` for the WASI environment.
1380
+ /// import_object = wasi_env.generate_import_object store, wasi_version
1381
+ ///
1382
+ /// ## Now we are ready to instantiate the module.
1383
+ /// instance = Wasmer::Instance.new module_, import_object
1384
+ ///
1385
+ /// # Here we go, let's start the program.
1386
+ /// instance.exports._start.()
1387
+ /// # "#); }
1388
+ /// ```
1389
+ pub mod Wasi {
1390
+ use super::*;
1391
+ use crate::doc::Ruby::*;
1392
+
1393
+ /// Represents a WASI version.
1394
+ #[allow(non_camel_case_types)]
1395
+ pub enum Version {
1396
+ LATEST_VERSION,
1397
+ SNAPSHOT0,
1398
+ SNAPSHOT1,
1399
+ }
1400
+
1401
+ /// Convenient builder API for configuring WASI.
1402
+ ///
1403
+ /// Use the constructor to pass the arguments, environments,
1404
+ /// preopen directories and map directories, or use the
1405
+ /// associated methods to build the state step-by-steps.
1406
+ pub struct StateBuilder;
1407
+
1408
+ impl StateBuilder {
1409
+ pub fn new(program_name: String) -> Self {
1410
+ x!()
1411
+ }
1412
+
1413
+ /// Adds an argument.
1414
+ ///
1415
+ /// Arguments must not contain the nul (`0x0`) byte.
1416
+ pub fn argument(&mut self, argument: String) -> Self {
1417
+ x!()
1418
+ }
1419
+
1420
+ /// Adds multiple arguments.
1421
+ ///
1422
+ /// Arguments must not contain the nul (`0x0`) byte.
1423
+ pub fn arguments(&mut self, arguments: Array<String>) -> Self {
1424
+ x!()
1425
+ }
1426
+
1427
+ /// Add an environment variable pair.
1428
+ ///
1429
+ /// Environment variable keys and values must not contain
1430
+ /// the byte `=` (`0x3d`) or null (`0x0`).
1431
+ pub fn environment(&mut self, key: String, value: String) -> Self {
1432
+ x!()
1433
+ }
1434
+
1435
+ /// Add environment variable pairs.
1436
+ ///
1437
+ /// Environment variable keys and values must not contain
1438
+ /// the byte `=` (`0x3d`) or null (`0x0`).
1439
+ pub fn environments(&mut self, pairs: Hash<String, String>) -> Self {
1440
+ x!()
1441
+ }
1442
+
1443
+ /// Preopen a directory with a different name exposed to the WASI.
1444
+ ///
1445
+ /// This opens the given directories at the virtual root,
1446
+ /// `/`, and allows the WASI module to read and write to the
1447
+ /// given directories.
1448
+ pub fn preopen_directory(&mut self, alias: String, value: String) -> Self {
1449
+ x!()
1450
+ }
1451
+
1452
+ /// Preopen directories with a different name exposed to the WASI.
1453
+ ///
1454
+ /// This opens the given directories at the virtual root,
1455
+ /// `/`, and allows the WASI module to read and write to the
1456
+ /// given directories.
1457
+ pub fn preopen_directories(&mut self, pairs: Hash<String, String>) -> Self {
1458
+ x!()
1459
+ }
1460
+
1461
+ /// Preopen a directory with a different name exposed to the WASI.
1462
+ pub fn map_directory(&mut self, alias: String, value: String) -> Self {
1463
+ x!()
1464
+ }
1465
+
1466
+ /// Preopen directories with a different name exposed to the WASI.
1467
+ pub fn map_directories(&mut self, pairs: Hash<String, String>) -> Self {
1468
+ x!()
1469
+ }
1470
+
1471
+ /// Produces a WASI [`Environment`] based on this state builder.
1472
+ pub fn finalize(&mut self) -> Environment {
1473
+ x!()
1474
+ }
1475
+ }
1476
+
1477
+ /// The environment provided to the WASI imports.
1478
+ ///
1479
+ /// To build it, use [`StateBuilder`]. See
1480
+ /// [`StateBuilder::finalize`] to learn more.
1481
+ pub struct Environment;
1482
+
1483
+ impl Environment {
1484
+ /// Create an [`ImportObject`] with an existing
1485
+ /// [`Environment`]. The import object will be different
1486
+ /// according to the WASI version.
1487
+ ///
1488
+ /// Use the [`Version`] enum to use a specific WASI
1489
+ /// version, or use [`get_version`] to read the WASI
1490
+ /// version from a [`Module`].
1491
+ pub fn generate_import_object(
1492
+ &self,
1493
+ store: Store,
1494
+ wasi_version: Version,
1495
+ ) -> ImportObject {
1496
+ x!()
1497
+ }
1498
+ }
1499
+
1500
+ /// Detect the version of WASI being used based on the import
1501
+ /// namespaces.
1502
+ ///
1503
+ /// A strict detection expects that all imports live in a
1504
+ /// single WASI namespace. A non-strict detection expects that
1505
+ /// at least one WASI namespace exits to detect the
1506
+ /// version. Note that the strict detection is faster than the
1507
+ /// non-strict one.
1508
+ pub fn get_version(module: Module, strict: Boolean) -> Version {
1509
+ x!()
1510
+ }
1511
+ }
1512
+ }