wasmer 0.1.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|