wasmer 0.4.0 → 0.5.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/.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
|
-
}
|