wasmer 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/documentation.yml +50 -0
- data/.github/workflows/test.yml +34 -61
- data/CHANGELOG.md +89 -29
- data/Cargo.lock +812 -380
- data/Cargo.toml +7 -20
- data/Gemfile +2 -3
- data/README.md +1 -0
- data/Rakefile +4 -3
- 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 +228 -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 +390 -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 +7 -1
- data/lib/wasmer.rb +29 -3
- data/wasmer.gemspec +6 -10
- metadata +45 -47
- data/README.md +0 -332
- data/lib/wasmer/version.rb +0 -3
- data/src/error.rs +0 -16
- data/src/instance/exports.rs +0 -215
- data/src/instance/globals.rs +0 -234
- data/src/instance/mod.rs +0 -141
- data/src/lib.rs +0 -162
- data/src/memory/mod.rs +0 -158
- data/src/memory/view.rs +0 -145
- data/src/module.rs +0 -28
data/README.md
DELETED
@@ -1,332 +0,0 @@
|
|
1
|
-
<p align="center">
|
2
|
-
<a href="https://wasmer.io" target="_blank" rel="noopener">
|
3
|
-
<img width="300" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/assets/logo.png" alt="Wasmer logo">
|
4
|
-
</a>
|
5
|
-
</p>
|
6
|
-
|
7
|
-
<p align="center">
|
8
|
-
<a href="https://spectrum.chat/wasmer">
|
9
|
-
<img src="https://withspectrum.github.io/badge/badge.svg" alt="Join the Wasmer Community"></a>
|
10
|
-
<a href="https://rubygems.org/gems/wasmer">
|
11
|
-
<img src="https://img.shields.io/gem/v/wasmer.svg" alt="Gem"></a>
|
12
|
-
<a href="https://rubygems.org/gems/wasmer">
|
13
|
-
<img src="https://img.shields.io/gem/dt/wasmer.svg" alt="Number of gem downloads"></a>
|
14
|
-
<a href="https://github.com/wasmerio/wasmer/blob/master/LICENSE">
|
15
|
-
<img src="https://img.shields.io/github/license/wasmerio/wasmer.svg" alt="License"></a>
|
16
|
-
</p>
|
17
|
-
|
18
|
-
Wasmer is a Ruby library for executing WebAssembly binaries:
|
19
|
-
|
20
|
-
* **Easy to use**: The `wasmer` API mimics the standard WebAssembly API,
|
21
|
-
* **Fast**: `wasmer` executes the WebAssembly modules as fast as possible,
|
22
|
-
* **Safe**: All calls to WebAssembly will be fast, but more
|
23
|
-
importantly, completely safe and sandboxed.
|
24
|
-
|
25
|
-
# Install
|
26
|
-
|
27
|
-
To install the `wasmer` Ruby gem, just run this command in your shell:
|
28
|
-
|
29
|
-
```sh
|
30
|
-
$ gem install wasmer
|
31
|
-
```
|
32
|
-
|
33
|
-
**Note**: [Rust][rust] is required to install the Ruby library (Cargo
|
34
|
-
—the build tool for Rust— is used to compile the extension). See [how
|
35
|
-
to install Rust][install-rust].
|
36
|
-
|
37
|
-
[View the `wasmer` gem on RubyGems][wasmer-gem].
|
38
|
-
|
39
|
-
[rust]: https://www.rust-lang.org/
|
40
|
-
[install-rust]: https://www.rust-lang.org/tools/install
|
41
|
-
[wasmer-gem]: https://rubygems.org/gems/wasmer
|
42
|
-
|
43
|
-
# Example
|
44
|
-
|
45
|
-
There is a toy program in `examples/simple.rs`, written in Rust (or
|
46
|
-
any other language that compiles to Wasm):
|
47
|
-
|
48
|
-
```rust
|
49
|
-
#[no_mangle]
|
50
|
-
pub extern fn sum(x: i32, y: i32) -> i32 {
|
51
|
-
x + y
|
52
|
-
}
|
53
|
-
```
|
54
|
-
|
55
|
-
Once this program compiled to WebAssembly, we end up with a
|
56
|
-
`examples/simple.wasm` binary file.
|
57
|
-
|
58
|
-
Then, we can execute it in Ruby (!) with the `examples/simple.rb` file:
|
59
|
-
|
60
|
-
```rb
|
61
|
-
require "wasmer"
|
62
|
-
|
63
|
-
bytes = IO.read "simple.wasm", mode: "rb"
|
64
|
-
instance = Wasmer::Instance.new bytes
|
65
|
-
puts instance.exports.sum 1, 2
|
66
|
-
```
|
67
|
-
|
68
|
-
And then, finally, enjoy by running:
|
69
|
-
|
70
|
-
```sh
|
71
|
-
$ ruby simple.rb
|
72
|
-
3
|
73
|
-
```
|
74
|
-
|
75
|
-
# API documentation
|
76
|
-
|
77
|
-
## The `Instance` class
|
78
|
-
|
79
|
-
Instantiates a WebAssembly module represented by bytes, and calls
|
80
|
-
exported functions on it:
|
81
|
-
|
82
|
-
```ruby
|
83
|
-
require "wasmer"
|
84
|
-
|
85
|
-
# Get the Wasm module as bytes.
|
86
|
-
wasm_bytes = IO.read "my_program.wasm", mode: "rb"
|
87
|
-
|
88
|
-
# Instantiates the Wasm module.
|
89
|
-
instance = Wasmer::Instance.new wasm_bytes
|
90
|
-
|
91
|
-
# Call a function on it.
|
92
|
-
result = instance.exports.sum 1, 2
|
93
|
-
|
94
|
-
puts result # 3
|
95
|
-
```
|
96
|
-
|
97
|
-
### Exported functions
|
98
|
-
|
99
|
-
All exported functions are accessible on the `exports`
|
100
|
-
getter. Arguments of these functions are automatically casted to
|
101
|
-
WebAssembly values.
|
102
|
-
|
103
|
-
### Exported memory
|
104
|
-
|
105
|
-
The `memory` getter exposes the `Memory` class representing the memory
|
106
|
-
of that particular instance, e.g.:
|
107
|
-
|
108
|
-
```ruby
|
109
|
-
view = instance.memory.uint8_view
|
110
|
-
```
|
111
|
-
|
112
|
-
`Instance.memory` throws an exception if no memory is exported.
|
113
|
-
|
114
|
-
See below for more information.
|
115
|
-
|
116
|
-
### Exported globals
|
117
|
-
|
118
|
-
The `globals` getter exposes the `ExportedGlobal` class represented an
|
119
|
-
exported global variable, e.g.:
|
120
|
-
|
121
|
-
```ruby
|
122
|
-
# Get the `x` global.
|
123
|
-
x = instance.globals.x
|
124
|
-
|
125
|
-
# Check whether the global is mutable.
|
126
|
-
assert x.mutable
|
127
|
-
assert_equal x.value, 7
|
128
|
-
|
129
|
-
# Update its value.
|
130
|
-
x.value = 42
|
131
|
-
|
132
|
-
# Tada!
|
133
|
-
assert_equal x.value, 42
|
134
|
-
```
|
135
|
-
|
136
|
-
## The `Memory` class
|
137
|
-
|
138
|
-
A WebAssembly instance has its own memory, represented by the `Memory`
|
139
|
-
class. It is accessible by the `Wasmer::Instance.memory` getter.
|
140
|
-
|
141
|
-
The `Memory.grow` methods allows to grow the memory by a number of
|
142
|
-
pages (of 65kb each).
|
143
|
-
|
144
|
-
```ruby
|
145
|
-
instance.memory.grow 1
|
146
|
-
```
|
147
|
-
|
148
|
-
The `Memory` class offers methods to create views of the memory
|
149
|
-
internal buffer, e.g. `uint8_view`, `int8_view`, `uint16_view`
|
150
|
-
etc. All these methods accept one optional argument: `offset`, to
|
151
|
-
subset the memory buffer at a particular offset. These methods return
|
152
|
-
respectively a `*Array` object, i.e. `uint8_view` returns a
|
153
|
-
`Uint8Array` object etc.
|
154
|
-
|
155
|
-
```ruby
|
156
|
-
offset = 7
|
157
|
-
view = instance.memory.uint8_view offset
|
158
|
-
|
159
|
-
puts view[0]
|
160
|
-
```
|
161
|
-
|
162
|
-
### The `*Array` classes
|
163
|
-
|
164
|
-
These classes represent views over a memory buffer of an instance.
|
165
|
-
|
166
|
-
| Class | View buffer as a sequence of… | Bytes per element |
|
167
|
-
|-|-|-|
|
168
|
-
| `Int8Array` | `int8` | 1 |
|
169
|
-
| `Uint8Array` | `uint8` | 1 |
|
170
|
-
| `Int16Array` | `int16` | 2 |
|
171
|
-
| `Uint16Array` | `uint16` | 2 |
|
172
|
-
| `Int32Array` | `int32` | 4 |
|
173
|
-
| `Uint32Array` | `uint32` | 4 |
|
174
|
-
|
175
|
-
All these classes share the same implementation. Taking the example of
|
176
|
-
`Uint8Array`, the class looks like this:
|
177
|
-
|
178
|
-
```ruby
|
179
|
-
class Uint8Array
|
180
|
-
def bytes_per_element
|
181
|
-
def length
|
182
|
-
def [](index)
|
183
|
-
def []=(index, value)
|
184
|
-
end
|
185
|
-
```
|
186
|
-
|
187
|
-
Let's see it in action:
|
188
|
-
|
189
|
-
```ruby
|
190
|
-
require "wasmer"
|
191
|
-
|
192
|
-
# Get the Wasm module as bytes.
|
193
|
-
wasm_bytes = IO.read "my_program.wasm", mode: "rb"
|
194
|
-
|
195
|
-
# Instantiates the Wasm module.
|
196
|
-
instance = Wasmer::Instance.new wasm_bytes
|
197
|
-
|
198
|
-
# Call a function that returns a pointer to a string for instance.
|
199
|
-
pointer = instance.exports.return_string
|
200
|
-
|
201
|
-
# Get the memory view, with the offset set to `pointer` (default is 0).
|
202
|
-
memory = instance.memory.uint8_view pointer
|
203
|
-
|
204
|
-
# Read the string pointed by the pointer.
|
205
|
-
|
206
|
-
string = ""
|
207
|
-
|
208
|
-
memory.each do |char|
|
209
|
-
break if char == 0
|
210
|
-
string += char.chr
|
211
|
-
end
|
212
|
-
|
213
|
-
puts string # Hello, World!
|
214
|
-
```
|
215
|
-
|
216
|
-
Notice that `*Array` treat bytes in little-endian, as required by the
|
217
|
-
WebAssembly specification, [Chapter Structure, Section Instructions,
|
218
|
-
Sub-Section Memory
|
219
|
-
Instructions](https://webassembly.github.io/spec/core/syntax/instructions.html#memory-instructions):
|
220
|
-
|
221
|
-
> All values are read and written in [little
|
222
|
-
> endian](https://en.wikipedia.org/wiki/Endianness#Little-endian) byte
|
223
|
-
> order.
|
224
|
-
|
225
|
-
Each view shares the same memory buffer internally. Let's have some fun:
|
226
|
-
|
227
|
-
```ruby
|
228
|
-
int8 = instance.memory.int8_view
|
229
|
-
int16 = instance.memory.int16_view
|
230
|
-
int32 = instance.memory.int32_view
|
231
|
-
|
232
|
-
b₁
|
233
|
-
┌┬┬┬┬┬┬┐
|
234
|
-
int8[0] = 0b00000001
|
235
|
-
b₂
|
236
|
-
┌┬┬┬┬┬┬┐
|
237
|
-
int8[1] = 0b00000100
|
238
|
-
b₃
|
239
|
-
┌┬┬┬┬┬┬┐
|
240
|
-
int8[2] = 0b00010000
|
241
|
-
b₄
|
242
|
-
┌┬┬┬┬┬┬┐
|
243
|
-
int8[3] = 0b01000000
|
244
|
-
|
245
|
-
// No surprise with the following assertions.
|
246
|
-
b₁
|
247
|
-
┌┬┬┬┬┬┬┐
|
248
|
-
assert_equal 0b00000001, int8[0]
|
249
|
-
b₂
|
250
|
-
┌┬┬┬┬┬┬┐
|
251
|
-
assert_equal 0b00000100, int8[1]
|
252
|
-
b₃
|
253
|
-
┌┬┬┬┬┬┬┐
|
254
|
-
assert_equal 0b00010000, int8[2]
|
255
|
-
b₄
|
256
|
-
┌┬┬┬┬┬┬┐
|
257
|
-
assert_equal 0b01000000, int8[3]
|
258
|
-
|
259
|
-
// The `int16` view reads 2 bytes.
|
260
|
-
b₂ b₁
|
261
|
-
┌┬┬┬┬┬┬┐ ┌┬┬┬┬┬┬┐
|
262
|
-
assert_equal 0b00000100_00000001, int16[0]
|
263
|
-
b₄ b₃
|
264
|
-
┌┬┬┬┬┬┬┐ ┌┬┬┬┬┬┬┐
|
265
|
-
assert_equal 0b01000000_00010000, int16[1]
|
266
|
-
|
267
|
-
// The `int32` view reads 4 bytes.
|
268
|
-
b₄ b₃ b₂ b₁
|
269
|
-
┌┬┬┬┬┬┬┐ ┌┬┬┬┬┬┬┐ ┌┬┬┬┬┬┬┐ ┌┬┬┬┬┬┬┐
|
270
|
-
assert_equal 0b01000000_00010000_00000100_00000001, int32[0]
|
271
|
-
```
|
272
|
-
|
273
|
-
## The `Module` class
|
274
|
-
|
275
|
-
The `Module` class contains one static method `validate`, that checks
|
276
|
-
whether the given bytes represent valid WebAssembly bytes:
|
277
|
-
|
278
|
-
```ruby
|
279
|
-
require "wasmer"
|
280
|
-
|
281
|
-
wasm_bytes = IO.read "my_program.wasm", mode: "rb"
|
282
|
-
|
283
|
-
if not Wasmer::Module.validate wasm_bytes
|
284
|
-
puts "The program seems corrupted."
|
285
|
-
end
|
286
|
-
```
|
287
|
-
|
288
|
-
This function returns a boolean.
|
289
|
-
|
290
|
-
# Install and Testing
|
291
|
-
|
292
|
-
To compile the entire project, run the following commands:
|
293
|
-
|
294
|
-
```sh
|
295
|
-
$ just build
|
296
|
-
$ just test
|
297
|
-
$ ruby examples/simple.rb
|
298
|
-
```
|
299
|
-
|
300
|
-
(Yes, you need [`just`][just]).
|
301
|
-
|
302
|
-
[just]: https://github.com/casey/just/
|
303
|
-
|
304
|
-
# What is WebAssembly?
|
305
|
-
|
306
|
-
Quoting [the WebAssembly site][wasm]:
|
307
|
-
|
308
|
-
> WebAssembly (abbreviated Wasm) is a binary instruction format for a
|
309
|
-
> stack-based virtual machine. Wasm is designed as a portable target
|
310
|
-
> for compilation of high-level languages like C/C++/Rust, enabling
|
311
|
-
> deployment on the web for client and server applications.
|
312
|
-
|
313
|
-
About speed:
|
314
|
-
|
315
|
-
> WebAssembly aims to execute at native speed by taking advantage of
|
316
|
-
> [common hardware
|
317
|
-
> capabilities](https://webassembly.org/docs/portability/#assumptions-for-efficient-execution)
|
318
|
-
> available on a wide range of platforms.
|
319
|
-
|
320
|
-
About safety:
|
321
|
-
|
322
|
-
> WebAssembly describes a memory-safe, sandboxed [execution
|
323
|
-
> environment](https://webassembly.org/docs/semantics/#linear-memory) […].
|
324
|
-
|
325
|
-
[wasm]: https://webassembly.org/
|
326
|
-
|
327
|
-
# License
|
328
|
-
|
329
|
-
The entire project is under the MIT License. Please read [the
|
330
|
-
`LICENSE` file][license].
|
331
|
-
|
332
|
-
[license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE
|
data/lib/wasmer/version.rb
DELETED
data/src/error.rs
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
//! Functions to handle error or exception correctly.
|
2
|
-
|
3
|
-
use rutie::{AnyException, VM};
|
4
|
-
|
5
|
-
pub fn unwrap_or_raise<Output, Function>(f: Function) -> Output
|
6
|
-
where
|
7
|
-
Function: FnOnce() -> Result<Output, AnyException>,
|
8
|
-
{
|
9
|
-
match f() {
|
10
|
-
Ok(x) => x,
|
11
|
-
Err(e) => {
|
12
|
-
VM::raise_ex(e);
|
13
|
-
unreachable!()
|
14
|
-
}
|
15
|
-
}
|
16
|
-
}
|
data/src/instance/exports.rs
DELETED
@@ -1,215 +0,0 @@
|
|
1
|
-
//! The `ExportedFunctions` WebAssembly class.
|
2
|
-
|
3
|
-
use crate::error::unwrap_or_raise;
|
4
|
-
use lazy_static::lazy_static;
|
5
|
-
use rutie::{
|
6
|
-
class, methods,
|
7
|
-
rubysys::{class, value::ValueType},
|
8
|
-
types::{Argc, Value},
|
9
|
-
util::str_to_cstring,
|
10
|
-
wrappable_struct, AnyException, AnyObject, Array, Boolean, Exception, Fixnum, Float, NilClass,
|
11
|
-
Object, Symbol,
|
12
|
-
};
|
13
|
-
use std::rc::Rc;
|
14
|
-
use wasmer_runtime::{self as runtime, types::Type};
|
15
|
-
|
16
|
-
/// The `ExportedFunctions` Ruby class.
|
17
|
-
pub struct ExportedFunctions {
|
18
|
-
/// The WebAssembly runtime.
|
19
|
-
instance: Rc<runtime::Instance>,
|
20
|
-
}
|
21
|
-
|
22
|
-
impl ExportedFunctions {
|
23
|
-
/// Create a new instance of the `ExportedFunctions` Ruby class.
|
24
|
-
pub fn new(instance: Rc<runtime::Instance>) -> Self {
|
25
|
-
Self { instance }
|
26
|
-
}
|
27
|
-
|
28
|
-
/// Check that an exported function exists.
|
29
|
-
pub fn respond_to_missing(&self, method_name: &str) -> bool {
|
30
|
-
self.instance.dyn_func(method_name).is_ok()
|
31
|
-
}
|
32
|
-
|
33
|
-
/// Call an exported function on the given WebAssembly instance.
|
34
|
-
pub fn method_missing(
|
35
|
-
&self,
|
36
|
-
method_name: &str,
|
37
|
-
arguments: Array,
|
38
|
-
) -> Result<AnyObject, AnyException> {
|
39
|
-
let function = self.instance.dyn_func(method_name).map_err(|_| {
|
40
|
-
AnyException::new(
|
41
|
-
"RuntimeError",
|
42
|
-
Some(&format!("Function `{}` does not exist.", method_name)),
|
43
|
-
)
|
44
|
-
})?;
|
45
|
-
let signature = function.signature();
|
46
|
-
let parameters = signature.params();
|
47
|
-
let number_of_parameters = parameters.len() as isize;
|
48
|
-
let number_of_arguments = arguments.length() as isize;
|
49
|
-
let diff: isize = number_of_parameters - number_of_arguments;
|
50
|
-
|
51
|
-
if diff > 0 {
|
52
|
-
return Err(AnyException::new(
|
53
|
-
"ArgumentError",
|
54
|
-
Some(&format!(
|
55
|
-
"Missing {} argument(s) when calling `{}`: Expect {} argument(s), given {}.",
|
56
|
-
diff, method_name, number_of_parameters, number_of_arguments
|
57
|
-
)),
|
58
|
-
));
|
59
|
-
} else if diff < 0 {
|
60
|
-
return Err(AnyException::new(
|
61
|
-
"ArgumentError",
|
62
|
-
Some(&format!(
|
63
|
-
"Given {} extra argument(s) when calling `{}`: Expect {} argument(s), given {}.",
|
64
|
-
diff.abs(), method_name, number_of_parameters, number_of_arguments
|
65
|
-
)),
|
66
|
-
));
|
67
|
-
}
|
68
|
-
|
69
|
-
let mut function_arguments =
|
70
|
-
Vec::<runtime::Value>::with_capacity(number_of_parameters as usize);
|
71
|
-
|
72
|
-
for (nth, (parameter, argument)) in parameters.iter().zip(arguments.into_iter()).enumerate()
|
73
|
-
{
|
74
|
-
let value = match (parameter, argument.ty()) {
|
75
|
-
(Type::I32, ValueType::Fixnum) => runtime::Value::I32(
|
76
|
-
argument
|
77
|
-
.try_convert_to::<Fixnum>()
|
78
|
-
.map_err(|_| {
|
79
|
-
AnyException::new(
|
80
|
-
"TypeError",
|
81
|
-
Some(&format!(
|
82
|
-
"Cannot convert argument #{} to a WebAssembly i32 value.",
|
83
|
-
nth + 1
|
84
|
-
)),
|
85
|
-
)
|
86
|
-
})?
|
87
|
-
.to_i32(),
|
88
|
-
),
|
89
|
-
(Type::I64, ValueType::Fixnum) => runtime::Value::I64(
|
90
|
-
argument
|
91
|
-
.try_convert_to::<Fixnum>()
|
92
|
-
.map_err(|_| {
|
93
|
-
AnyException::new(
|
94
|
-
"TypeError",
|
95
|
-
Some(&format!(
|
96
|
-
"Cannot convert argument #{} to a WebAssembly i64 value.",
|
97
|
-
nth + 1
|
98
|
-
)),
|
99
|
-
)
|
100
|
-
})?
|
101
|
-
.to_i64(),
|
102
|
-
),
|
103
|
-
(Type::F32, ValueType::Float) => runtime::Value::F32(
|
104
|
-
argument
|
105
|
-
.try_convert_to::<Float>()
|
106
|
-
.map_err(|_| {
|
107
|
-
AnyException::new(
|
108
|
-
"TypeError",
|
109
|
-
Some(&format!(
|
110
|
-
"Cannot convert argument #{} to a WebAssembly f32 value.",
|
111
|
-
nth + 1
|
112
|
-
)),
|
113
|
-
)
|
114
|
-
})?
|
115
|
-
.to_f64() as f32,
|
116
|
-
),
|
117
|
-
(Type::F64, ValueType::Float) => runtime::Value::F64(
|
118
|
-
argument
|
119
|
-
.try_convert_to::<Float>()
|
120
|
-
.map_err(|_| {
|
121
|
-
AnyException::new(
|
122
|
-
"TypeError",
|
123
|
-
Some(&format!(
|
124
|
-
"Cannot convert argument #{} to a WebAssembly f64 value.",
|
125
|
-
nth + 1
|
126
|
-
)),
|
127
|
-
)
|
128
|
-
})?
|
129
|
-
.to_f64(),
|
130
|
-
),
|
131
|
-
(_, ty) => {
|
132
|
-
return Err(AnyException::new(
|
133
|
-
"ArgumentError",
|
134
|
-
Some(&format!(
|
135
|
-
"Cannot convert argument #{} to a WebAssembly value. Only integers and floats are supported. Given `{:?}`.",
|
136
|
-
nth + 1,
|
137
|
-
ty
|
138
|
-
))));
|
139
|
-
}
|
140
|
-
};
|
141
|
-
|
142
|
-
function_arguments.push(value);
|
143
|
-
}
|
144
|
-
|
145
|
-
let results = function
|
146
|
-
.call(function_arguments.as_slice())
|
147
|
-
.map_err(|e| AnyException::new("RuntimeError", Some(&format!("{}", e))))?;
|
148
|
-
|
149
|
-
if !results.is_empty() {
|
150
|
-
Ok(match results[0] {
|
151
|
-
runtime::Value::I32(result) => Fixnum::new(result as i64).into(),
|
152
|
-
runtime::Value::I64(result) => Fixnum::new(result).into(),
|
153
|
-
runtime::Value::F32(result) => Float::new(result as f64).into(),
|
154
|
-
runtime::Value::F64(result) => Float::new(result).into(),
|
155
|
-
runtime::Value::V128(_result) => {
|
156
|
-
return Err(AnyException::new(
|
157
|
-
"RuntimeError",
|
158
|
-
Some("Type `V128` isn't supported yet."),
|
159
|
-
))
|
160
|
-
}
|
161
|
-
})
|
162
|
-
} else {
|
163
|
-
Ok(NilClass::new().into())
|
164
|
-
}
|
165
|
-
}
|
166
|
-
}
|
167
|
-
|
168
|
-
wrappable_struct!(
|
169
|
-
ExportedFunctions,
|
170
|
-
ExportedFunctionsWrapper,
|
171
|
-
EXPORTED_FUNCTIONS_WRAPPER
|
172
|
-
);
|
173
|
-
|
174
|
-
class!(RubyExportedFunctions);
|
175
|
-
|
176
|
-
#[rustfmt::skip]
|
177
|
-
methods!(
|
178
|
-
RubyExportedFunctions,
|
179
|
-
itself,
|
180
|
-
|
181
|
-
// Glue code to call the `ExportedFunctions.respond_to` method.
|
182
|
-
fn ruby_exported_functions_method_exists(symbol: Symbol, _include_private: Boolean) -> Boolean {
|
183
|
-
unwrap_or_raise(|| {
|
184
|
-
let symbol = symbol?;
|
185
|
-
let exported_functions = itself.get_data(&*EXPORTED_FUNCTIONS_WRAPPER);
|
186
|
-
|
187
|
-
Ok(Boolean::new(exported_functions.respond_to_missing(symbol.to_str())))
|
188
|
-
})
|
189
|
-
}
|
190
|
-
);
|
191
|
-
|
192
|
-
/// Glue code to call the `ExportedFunctions.method_missing` method.
|
193
|
-
pub extern "C" fn ruby_exported_functions_method_missing(
|
194
|
-
argc: Argc,
|
195
|
-
argv: *const AnyObject,
|
196
|
-
itself: RubyExportedFunctions,
|
197
|
-
) -> AnyObject {
|
198
|
-
unwrap_or_raise(|| {
|
199
|
-
let arguments = Value::from(0);
|
200
|
-
|
201
|
-
unsafe {
|
202
|
-
let argv_pointer = argv as *const Value;
|
203
|
-
|
204
|
-
class::rb_scan_args(argc, argv_pointer, str_to_cstring("*").as_ptr(), &arguments)
|
205
|
-
};
|
206
|
-
|
207
|
-
let mut arguments = Array::from(arguments);
|
208
|
-
let method_name = unsafe { arguments.shift().to::<Symbol>() };
|
209
|
-
let method_name = method_name.to_str();
|
210
|
-
|
211
|
-
itself
|
212
|
-
.get_data(&*EXPORTED_FUNCTIONS_WRAPPER)
|
213
|
-
.method_missing(method_name, arguments)
|
214
|
-
})
|
215
|
-
}
|