wasmer 0.1.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.cargo/config +1 -1
- data/.github/workflows/documentation.yml +50 -0
- data/.github/workflows/test.yml +73 -0
- data/.gitignore +3 -1
- data/CHANGELOG.md +225 -0
- data/Cargo.lock +747 -708
- data/Cargo.toml +7 -21
- data/Gemfile +2 -3
- data/LICENSE +21 -0
- data/README.md +1 -0
- data/Rakefile +4 -3
- data/bors.toml +6 -0
- data/crates/rutie-derive-macros/Cargo.toml +19 -0
- data/crates/rutie-derive-macros/README.md +4 -0
- data/crates/rutie-derive-macros/src/class.rs +156 -0
- data/crates/rutie-derive-macros/src/function.rs +178 -0
- data/crates/rutie-derive-macros/src/lib.rs +27 -0
- data/crates/rutie-derive-macros/src/methods.rs +282 -0
- data/crates/rutie-derive/Cargo.toml +14 -0
- data/crates/rutie-derive/README.md +97 -0
- data/crates/rutie-derive/src/lib.rs +4 -0
- data/crates/rutie-derive/src/upcast.rs +47 -0
- data/crates/rutie-test/Cargo.toml +10 -0
- data/crates/rutie-test/src/lib.rs +38 -0
- data/crates/wasmer/Cargo.toml +27 -0
- data/crates/wasmer/README.md +229 -0
- data/crates/wasmer/src/doc.rs +1512 -0
- data/crates/wasmer/src/error.rs +55 -0
- data/crates/wasmer/src/exports.rs +107 -0
- data/crates/wasmer/src/externals/function.rs +159 -0
- data/crates/wasmer/src/externals/global.rs +62 -0
- data/crates/wasmer/src/externals/memory.rs +117 -0
- data/crates/wasmer/src/externals/mod.rs +9 -0
- data/crates/wasmer/src/externals/table.rs +41 -0
- data/crates/wasmer/src/import_object.rs +78 -0
- data/crates/wasmer/src/instance.rs +45 -0
- data/crates/wasmer/src/lib.rs +307 -0
- data/crates/wasmer/src/memory/mod.rs +1 -0
- data/crates/wasmer/src/memory/views.rs +112 -0
- data/crates/wasmer/src/module.rs +106 -0
- data/crates/wasmer/src/prelude.rs +3 -0
- data/crates/wasmer/src/store.rs +22 -0
- data/crates/wasmer/src/types.rs +396 -0
- data/crates/wasmer/src/values.rs +84 -0
- data/crates/wasmer/src/wasi.rs +226 -0
- data/crates/wasmer/src/wat.rs +20 -0
- data/justfile +20 -2
- data/lib/wasmer.rb +29 -3
- data/wasmer.gemspec +8 -12
- metadata +53 -49
- data/.circleci/config.yml +0 -70
- data/README.md +0 -279
- data/lib/wasmer/version.rb +0 -3
- data/src/instance.rs +0 -282
- data/src/lib.rs +0 -98
- data/src/memory/mod.rs +0 -120
- data/src/memory/view.rs +0 -127
- 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 = "1.0.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 = "2.0"
|
19
|
+
wasmer-wasi = "2.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,229 @@
|
|
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://wasmerio.github.io/wasmer-ruby/wasmer_ruby/index.html">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-all` recipe will automatically build and run all the
|
174
|
+
tests. It includes library tests, along with documentation tests and
|
175
|
+
the examples:
|
176
|
+
|
177
|
+
```sh
|
178
|
+
$ just test-all
|
179
|
+
```
|
180
|
+
|
181
|
+
### Documentation
|
182
|
+
|
183
|
+
To generate the documentation, run the following command:
|
184
|
+
|
185
|
+
```sh
|
186
|
+
$ just doc
|
187
|
+
```
|
188
|
+
|
189
|
+
All the examples in the documentation are automatically run as tests,
|
190
|
+
called doctests. To run the doctests, run `just test`.
|
191
|
+
|
192
|
+
## What is WebAssembly?
|
193
|
+
|
194
|
+
Quoting [the WebAssembly site][wasm]:
|
195
|
+
|
196
|
+
> WebAssembly (abbreviated Wasm) is a binary instruction format for a
|
197
|
+
> stack-based virtual machine. Wasm is designed as a portable target
|
198
|
+
> for compilation of high-level languages like C/C++/Rust, enabling
|
199
|
+
> deployment on the web for client and server applications.
|
200
|
+
|
201
|
+
About speed:
|
202
|
+
|
203
|
+
> WebAssembly aims to execute at native speed by taking advantage of
|
204
|
+
> [common hardware
|
205
|
+
> capabilities](https://webassembly.org/docs/portability/#assumptions-for-efficient-execution)
|
206
|
+
> available on a wide range of platforms.
|
207
|
+
|
208
|
+
About safety:
|
209
|
+
|
210
|
+
> WebAssembly describes a memory-safe, sandboxed [execution
|
211
|
+
> environment](https://webassembly.org/docs/semantics/#linear-memory) […].
|
212
|
+
|
213
|
+
[wasm]: https://webassembly.org/
|
214
|
+
|
215
|
+
## License
|
216
|
+
|
217
|
+
The entire project is under the MIT License. Please read [the
|
218
|
+
`LICENSE` file][license].
|
219
|
+
|
220
|
+
[license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE
|
221
|
+
|
222
|
+
[Wasmer]: https://github.com/wasmerio/wasmer
|
223
|
+
[rust]: https://www.rust-lang.org/
|
224
|
+
[install-rust]: https://www.rust-lang.org/tools/install
|
225
|
+
[wasmer-gem]: https://rubygems.org/gems/wasmer
|
226
|
+
[rutie]: https://github.com/danielpclark/rutie
|
227
|
+
[rbenv]: https://github.com/rbenv/rbenv
|
228
|
+
[rustup]: https://rustup.rs/
|
229
|
+
[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
|
+
}
|