wasmtime 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Cargo.lock +941 -627
- data/Cargo.toml +2 -14
- data/LICENSE +23 -21
- data/README.md +47 -118
- data/ext/Cargo.toml +17 -0
- data/ext/extconf.rb +6 -0
- data/ext/src/helpers/mod.rs +3 -0
- data/ext/src/helpers/wrapped_struct.rs +84 -0
- data/ext/src/lib.rs +9 -0
- data/ext/src/ruby_api/config.rs +68 -0
- data/ext/src/ruby_api/convert.rs +92 -0
- data/ext/src/ruby_api/engine.rs +66 -0
- data/ext/src/ruby_api/errors.rs +56 -0
- data/ext/src/ruby_api/externals.rs +113 -0
- data/ext/src/ruby_api/func.rs +388 -0
- data/ext/src/ruby_api/func_type.rs +139 -0
- data/ext/src/ruby_api/instance.rs +174 -0
- data/ext/src/ruby_api/linker.rs +296 -0
- data/ext/src/ruby_api/macros.rs +12 -0
- data/ext/src/ruby_api/memory.rs +142 -0
- data/ext/src/ruby_api/memory_type.rs +56 -0
- data/ext/src/ruby_api/mod.rs +48 -0
- data/ext/src/ruby_api/module.rs +107 -0
- data/ext/src/ruby_api/params.rs +42 -0
- data/ext/src/ruby_api/static_id.rs +57 -0
- data/ext/src/ruby_api/store.rs +182 -0
- data/ext/src/ruby_api/trap.rs +135 -0
- data/lib/wasmtime/version.rb +1 -1
- data/lib/wasmtime.rb +29 -4
- metadata +54 -30
- data/.cargo/config +0 -4
- data/CHANGELOG.md +0 -27
- data/ext/wasmtime/Makefile +0 -5
- data/ext/wasmtime/Rakefile +0 -3
- data/ext/wasmtime/extconf.rb +0 -5
- data/lib/tasks/compile.rake +0 -27
- data/lib/wasmtime/refinements.rb +0 -20
- data/lib/wasmtime/require.rb +0 -72
- data/src/export.rs +0 -19
- data/src/func.rs +0 -175
- data/src/instance.rs +0 -93
- data/src/lib.rs +0 -22
- data/src/memory.rs +0 -48
- data/src/ruby_type.rs +0 -32
- data/src/vm.rs +0 -6
@@ -0,0 +1,135 @@
|
|
1
|
+
use std::convert::TryFrom;
|
2
|
+
|
3
|
+
use crate::helpers::WrappedStruct;
|
4
|
+
use crate::ruby_api::{errors::base_error, root};
|
5
|
+
use magnus::Error;
|
6
|
+
use magnus::{
|
7
|
+
memoize, method, rb_sys::AsRawValue, DataTypeFunctions, ExceptionClass, Module as _, Symbol,
|
8
|
+
TypedData, Value,
|
9
|
+
};
|
10
|
+
|
11
|
+
pub fn trap_error() -> ExceptionClass {
|
12
|
+
*memoize!(ExceptionClass: root().define_error("Trap", base_error()).unwrap())
|
13
|
+
}
|
14
|
+
|
15
|
+
macro_rules! trap_const {
|
16
|
+
($trap:ident) => {
|
17
|
+
trap_error().const_get(stringify!($trap)).map(Some)
|
18
|
+
};
|
19
|
+
}
|
20
|
+
|
21
|
+
#[derive(TypedData, Debug)]
|
22
|
+
#[magnus(class = "Wasmtime::Trap", size, free_immediatly)]
|
23
|
+
/// @yard
|
24
|
+
pub struct Trap {
|
25
|
+
trap: wasmtime::Trap,
|
26
|
+
wasm_backtrace: Option<wasmtime::WasmBacktrace>,
|
27
|
+
}
|
28
|
+
impl DataTypeFunctions for Trap {}
|
29
|
+
|
30
|
+
impl Trap {
|
31
|
+
pub fn new(trap: wasmtime::Trap, wasm_backtrace: Option<wasmtime::WasmBacktrace>) -> Self {
|
32
|
+
Self {
|
33
|
+
trap,
|
34
|
+
wasm_backtrace,
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
/// @yard
|
39
|
+
/// Returns a textual description of the trap error, for example:
|
40
|
+
/// wasm trap: wasm `unreachable` instruction executed
|
41
|
+
/// @return [String]
|
42
|
+
pub fn message(&self) -> String {
|
43
|
+
self.trap.to_string()
|
44
|
+
}
|
45
|
+
|
46
|
+
/// @yard
|
47
|
+
/// Returns a textual representation of the Wasm backtrce, if it exists.
|
48
|
+
/// For example:
|
49
|
+
/// error while executing at wasm backtrace:
|
50
|
+
/// 0: 0x1a - <unknown>!<wasm function 0>
|
51
|
+
/// @return [String, nil]
|
52
|
+
pub fn wasm_backtrace_message(&self) -> Option<String> {
|
53
|
+
self.wasm_backtrace.as_ref().map(|bt| format!("{}", bt))
|
54
|
+
}
|
55
|
+
|
56
|
+
/// @yard
|
57
|
+
/// Returns the trap code as a Symbol, possibly nil if the trap did not
|
58
|
+
/// origin from Wasm code. All possible trap codes are defined as constants on {Trap}.
|
59
|
+
/// @return [Symbol, nil]
|
60
|
+
pub fn code(&self) -> Result<Option<Symbol>, Error> {
|
61
|
+
match self.trap {
|
62
|
+
wasmtime::Trap::HeapMisaligned => trap_const!(HEAP_MISALIGNED),
|
63
|
+
wasmtime::Trap::TableOutOfBounds => trap_const!(TABLE_OUT_OF_BOUNDS),
|
64
|
+
wasmtime::Trap::IndirectCallToNull => trap_const!(INDIRECT_CALL_TO_NULL),
|
65
|
+
wasmtime::Trap::BadSignature => trap_const!(BAD_SIGNATURE),
|
66
|
+
wasmtime::Trap::IntegerOverflow => trap_const!(INTEGER_OVERFLOW),
|
67
|
+
wasmtime::Trap::IntegerDivisionByZero => trap_const!(INTEGER_DIVISION_BY_ZERO),
|
68
|
+
wasmtime::Trap::BadConversionToInteger => trap_const!(BAD_CONVERSION_TO_INTEGER),
|
69
|
+
wasmtime::Trap::UnreachableCodeReached => trap_const!(UNREACHABLE_CODE_REACHED),
|
70
|
+
wasmtime::Trap::Interrupt => trap_const!(INTERRUPT),
|
71
|
+
wasmtime::Trap::AlwaysTrapAdapter => trap_const!(ALWAYS_TRAP_ADAPTER),
|
72
|
+
// When adding a trap code here, define a matching constant on Wasmtime::Trap (in Ruby)
|
73
|
+
_ => trap_const!(UNKNOWN),
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
// pub fn wasm_backtrace(&self) -> Option<RArray> {
|
78
|
+
// self.wasm_backtrace.as_ref().map(|backtrace| {
|
79
|
+
// let array = RArray::with_capacity(backtrace.frames().len());
|
80
|
+
// backtrace
|
81
|
+
// .frames()
|
82
|
+
// .iter()
|
83
|
+
// .for_each(|frame| array.push(frame.format()).unwrap());
|
84
|
+
|
85
|
+
// array
|
86
|
+
// })
|
87
|
+
// }
|
88
|
+
|
89
|
+
pub fn inspect(rb_self: WrappedStruct<Self>) -> Result<String, Error> {
|
90
|
+
let rs_self = rb_self.get()?;
|
91
|
+
|
92
|
+
Ok(format!(
|
93
|
+
"#<Wasmtime::Trap:0x{:016x} @trap_code={}>",
|
94
|
+
rb_self.to_value().as_raw(),
|
95
|
+
Value::from(rs_self.code()?).inspect()
|
96
|
+
))
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
impl From<Trap> for Error {
|
101
|
+
fn from(trap: Trap) -> Self {
|
102
|
+
magnus::Value::from(trap)
|
103
|
+
.try_convert::<magnus::Exception>()
|
104
|
+
.unwrap() // Can't fail: Wasmtime::Trap is an Exception
|
105
|
+
.into()
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
impl TryFrom<anyhow::Error> for Trap {
|
110
|
+
type Error = anyhow::Error;
|
111
|
+
|
112
|
+
fn try_from(value: anyhow::Error) -> Result<Self, Self::Error> {
|
113
|
+
match value.downcast_ref::<wasmtime::Trap>() {
|
114
|
+
Some(trap) => {
|
115
|
+
let trap = trap.to_owned();
|
116
|
+
let bt = value.downcast::<wasmtime::WasmBacktrace>();
|
117
|
+
Ok(Trap::new(trap, bt.map(Some).unwrap_or(None)))
|
118
|
+
}
|
119
|
+
None => Err(value),
|
120
|
+
}
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
pub fn init() -> Result<(), Error> {
|
125
|
+
let class = trap_error();
|
126
|
+
class.define_method("message", method!(Trap::message, 0))?;
|
127
|
+
class.define_method(
|
128
|
+
"wasm_backtrace_message",
|
129
|
+
method!(Trap::wasm_backtrace_message, 0),
|
130
|
+
)?;
|
131
|
+
class.define_method("code", method!(Trap::code, 0))?;
|
132
|
+
class.define_method("inspect", method!(Trap::inspect, 0))?;
|
133
|
+
class.define_alias("to_s", "message")?;
|
134
|
+
Ok(())
|
135
|
+
}
|
data/lib/wasmtime/version.rb
CHANGED
data/lib/wasmtime.rb
CHANGED
@@ -1,7 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative "wasmtime/version"
|
4
4
|
|
5
|
-
require
|
6
|
-
|
7
|
-
|
5
|
+
# Tries to require the extension for the given Ruby version first
|
6
|
+
begin
|
7
|
+
RUBY_VERSION =~ /(\d+\.\d+)/
|
8
|
+
require "wasmtime/#{Regexp.last_match(1)}/ext"
|
9
|
+
rescue LoadError
|
10
|
+
require "wasmtime/ext"
|
11
|
+
end
|
12
|
+
|
13
|
+
module Wasmtime
|
14
|
+
class Error < StandardError; end
|
15
|
+
|
16
|
+
class ConversionError < Error; end
|
17
|
+
|
18
|
+
class Trap < Error
|
19
|
+
STACK_OVERFLOW = :stack_overflow
|
20
|
+
HEAP_MISALIGNED = :heap_misaligned
|
21
|
+
TABLE_OUT_OF_BOUNDS = :table_out_of_bounds
|
22
|
+
INDIRECT_CALL_TO_NULL = :indirect_call_to_null
|
23
|
+
BAD_SIGNATURE = :bad_signature
|
24
|
+
INTEGER_OVERFLOW = :integer_overflow
|
25
|
+
INTEGER_DIVISION_BY_ZERO = :integer_division_by_zero
|
26
|
+
BAD_CONVERSION_TO_INTEGER = :bad_conversion_to_integer
|
27
|
+
UNREACHABLE_CODE_REACHED = :unreachable_code_reached
|
28
|
+
INTERRUPT = :interrupt
|
29
|
+
ALWAYS_TRAP_ADAPTER = :always_trap_adapter
|
30
|
+
UNKNOWN = :unknown
|
31
|
+
end
|
32
|
+
end
|
metadata
CHANGED
@@ -1,50 +1,74 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wasmtime
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- The Wasmtime Project Developers
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
|
11
|
+
date: 2022-11-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rb_sys
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.9.39
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.9.39
|
27
|
+
description: A Ruby binding for Wasmtime, a WebAssembly runtime.
|
14
28
|
email:
|
15
|
-
-
|
29
|
+
- hello@bytecodealliance.org
|
16
30
|
executables: []
|
17
31
|
extensions:
|
18
|
-
- ext/
|
32
|
+
- ext/extconf.rb
|
19
33
|
extra_rdoc_files: []
|
20
34
|
files:
|
21
|
-
- ".cargo/config"
|
22
|
-
- CHANGELOG.md
|
23
35
|
- Cargo.lock
|
24
36
|
- Cargo.toml
|
25
37
|
- LICENSE
|
26
38
|
- README.md
|
27
|
-
- ext/
|
28
|
-
- ext/
|
29
|
-
- ext/
|
30
|
-
-
|
39
|
+
- ext/Cargo.toml
|
40
|
+
- ext/extconf.rb
|
41
|
+
- ext/src/helpers/mod.rs
|
42
|
+
- ext/src/helpers/wrapped_struct.rs
|
43
|
+
- ext/src/lib.rs
|
44
|
+
- ext/src/ruby_api/config.rs
|
45
|
+
- ext/src/ruby_api/convert.rs
|
46
|
+
- ext/src/ruby_api/engine.rs
|
47
|
+
- ext/src/ruby_api/errors.rs
|
48
|
+
- ext/src/ruby_api/externals.rs
|
49
|
+
- ext/src/ruby_api/func.rs
|
50
|
+
- ext/src/ruby_api/func_type.rs
|
51
|
+
- ext/src/ruby_api/instance.rs
|
52
|
+
- ext/src/ruby_api/linker.rs
|
53
|
+
- ext/src/ruby_api/macros.rs
|
54
|
+
- ext/src/ruby_api/memory.rs
|
55
|
+
- ext/src/ruby_api/memory_type.rs
|
56
|
+
- ext/src/ruby_api/mod.rs
|
57
|
+
- ext/src/ruby_api/module.rs
|
58
|
+
- ext/src/ruby_api/params.rs
|
59
|
+
- ext/src/ruby_api/static_id.rs
|
60
|
+
- ext/src/ruby_api/store.rs
|
61
|
+
- ext/src/ruby_api/trap.rs
|
31
62
|
- lib/wasmtime.rb
|
32
|
-
- lib/wasmtime/refinements.rb
|
33
|
-
- lib/wasmtime/require.rb
|
34
63
|
- lib/wasmtime/version.rb
|
35
|
-
|
36
|
-
- src/func.rs
|
37
|
-
- src/instance.rs
|
38
|
-
- src/lib.rs
|
39
|
-
- src/memory.rs
|
40
|
-
- src/ruby_type.rs
|
41
|
-
- src/vm.rs
|
42
|
-
homepage: https://github.com/dtcristo/wasmtime-ruby
|
64
|
+
homepage: https://github.com/BytecodeAlliance/wasmtime-rb
|
43
65
|
licenses:
|
44
|
-
- Apache-2.0
|
66
|
+
- Apache-2.0
|
45
67
|
metadata:
|
46
|
-
|
47
|
-
|
68
|
+
homepage_uri: https://github.com/BytecodeAlliance/wasmtime-rb
|
69
|
+
source_code_uri: https://github.com/BytecodeAlliance/wasmtime-rb
|
70
|
+
cargo_crate_name: ext
|
71
|
+
changelog_uri: https://github.com/bytecodealliance/wasmtime-rb/blob/main/CHANGELOG.md
|
48
72
|
post_install_message:
|
49
73
|
rdoc_options: []
|
50
74
|
require_paths:
|
@@ -53,15 +77,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
53
77
|
requirements:
|
54
78
|
- - ">="
|
55
79
|
- !ruby/object:Gem::Version
|
56
|
-
version: 2.
|
80
|
+
version: 2.7.0
|
57
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
82
|
requirements:
|
59
83
|
- - ">="
|
60
84
|
- !ruby/object:Gem::Version
|
61
85
|
version: '0'
|
62
86
|
requirements: []
|
63
|
-
rubygems_version: 3.
|
87
|
+
rubygems_version: 3.3.7
|
64
88
|
signing_key:
|
65
89
|
specification_version: 4
|
66
|
-
summary:
|
90
|
+
summary: Wasmtime bindings for Ruby
|
67
91
|
test_files: []
|
data/.cargo/config
DELETED
data/CHANGELOG.md
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# Changelog
|
2
|
-
|
3
|
-
All notable changes to this project will be documented in this file.
|
4
|
-
|
5
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
-
|
8
|
-
## [Unreleased]
|
9
|
-
|
10
|
-
## [0.2.0] - 2020-05-19
|
11
|
-
|
12
|
-
- Exported functions now live on `Wasmtime::Instance#exports` instead of `#funcs`.
|
13
|
-
- Exports hash is now keyed by strings instead of symbols.
|
14
|
-
- Added support for `Wasmtime::Memory` exports with `#data_size`, `#size` and `#grow` methods.
|
15
|
-
|
16
|
-
## [0.1.0] - 2020-05-07
|
17
|
-
|
18
|
-
### Added
|
19
|
-
|
20
|
-
- Initial release.
|
21
|
-
- Support for calling exported functions on a module.
|
22
|
-
- Support for 32 and 64-bit integers and floats in arguments and as return values.
|
23
|
-
- Require patch for defining a Ruby module with functions for each export.
|
24
|
-
|
25
|
-
[unreleased]: https://github.com/dtcristo/wasmtime-ruby/compare/v0.2.0...HEAD
|
26
|
-
[0.2.0]: https://github.com/dtcristo/wasmtime-ruby/releases/tag/v0.2.0
|
27
|
-
[0.1.0]: https://github.com/dtcristo/wasmtime-ruby/releases/tag/v0.1.0
|
data/ext/wasmtime/Makefile
DELETED
data/ext/wasmtime/Rakefile
DELETED
data/ext/wasmtime/extconf.rb
DELETED
data/lib/tasks/compile.rake
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rbconfig'
|
4
|
-
|
5
|
-
SOEXT = RbConfig::CONFIG['SOEXT']
|
6
|
-
DLEXT = RbConfig::CONFIG['DLEXT']
|
7
|
-
|
8
|
-
SO = File.expand_path("../../target/release/libwasmtime_ruby.#{SOEXT}", __dir__)
|
9
|
-
DL = File.expand_path("../wasmtime/native.#{DLEXT}", __dir__)
|
10
|
-
|
11
|
-
desc 'Remove compile artifacts'
|
12
|
-
task :clean do
|
13
|
-
sh 'cargo clean'
|
14
|
-
rm_rf SO
|
15
|
-
rm_rf DL
|
16
|
-
end
|
17
|
-
|
18
|
-
desc 'Compile native extension'
|
19
|
-
task :compile do
|
20
|
-
unless `rustup target list`.include?('wasm32-unknown-unknown (installed)')
|
21
|
-
sh 'rustup target add wasm32-unknown-unknown'
|
22
|
-
end
|
23
|
-
|
24
|
-
ENV['NO_LINK_RUTIE'] = '1'
|
25
|
-
sh 'cargo build --release'
|
26
|
-
cp SO, DL
|
27
|
-
end
|
data/lib/wasmtime/refinements.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Wasmtime
|
4
|
-
module Refinements
|
5
|
-
refine String do
|
6
|
-
def camelize(uppercase_first_letter = true)
|
7
|
-
string = self
|
8
|
-
if uppercase_first_letter
|
9
|
-
string = string.sub(/^[a-z\d]*/, &:capitalize)
|
10
|
-
else
|
11
|
-
string = string.sub(/^(?:(?=\b|[A-Z_])|\w)/, &:downcase)
|
12
|
-
end
|
13
|
-
string.gsub(%r{(?:_|(\/))([a-z\d]*)}) { "#{$1}#{$2.capitalize}" }.gsub(
|
14
|
-
'/',
|
15
|
-
'::'
|
16
|
-
)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/lib/wasmtime/require.rb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'wasmtime'
|
4
|
-
|
5
|
-
using Wasmtime::Refinements
|
6
|
-
|
7
|
-
module Kernel
|
8
|
-
unless defined?(wasmtime_original_require)
|
9
|
-
alias_method :wasmtime_original_require, :require
|
10
|
-
private :wasmtime_original_require
|
11
|
-
end
|
12
|
-
|
13
|
-
def require(path)
|
14
|
-
wasmtime_original_require(path)
|
15
|
-
rescue LoadError => load_error
|
16
|
-
try_load =
|
17
|
-
Proc.new do |path, extention|
|
18
|
-
path_with_extention =
|
19
|
-
path.end_with?(".#{extention}") ? path : "#{path}.#{extention}"
|
20
|
-
|
21
|
-
if path_with_extention.start_with?('.', '/', '~')
|
22
|
-
absolute_path = File.expand_path(path_with_extention)
|
23
|
-
return Wasmtime.load(absolute_path) if File.file?(absolute_path)
|
24
|
-
end
|
25
|
-
$LOAD_PATH.each do |load_dir|
|
26
|
-
absolute_path = File.expand_path(path_with_extention, load_dir)
|
27
|
-
return Wasmtime.load(absolute_path) if File.file?(absolute_path)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
try_load.call(path, 'wasm')
|
32
|
-
try_load.call(path, 'wat')
|
33
|
-
|
34
|
-
raise load_error
|
35
|
-
end
|
36
|
-
|
37
|
-
unless defined?(wasmtime_original_require_relative)
|
38
|
-
alias_method :wasmtime_original_require_relative, :require_relative
|
39
|
-
private :wasmtime_original_require_relative
|
40
|
-
end
|
41
|
-
|
42
|
-
def require_relative(path)
|
43
|
-
absolute_path =
|
44
|
-
File.expand_path(path, File.dirname(caller_locations[0].absolute_path))
|
45
|
-
require(absolute_path)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
module Wasmtime
|
50
|
-
module_function
|
51
|
-
|
52
|
-
def load(absolute_path)
|
53
|
-
return false if $LOADED_FEATURES.include?(absolute_path)
|
54
|
-
filename = absolute_path.split(File::SEPARATOR).last
|
55
|
-
module_name =
|
56
|
-
if filename.end_with?('.wasm')
|
57
|
-
filename.delete_suffix('.wasm')
|
58
|
-
else
|
59
|
-
filename.delete_suffix('.wat')
|
60
|
-
end
|
61
|
-
mod = Object.const_set(module_name.camelize, Module.new)
|
62
|
-
instance = Wasmtime::Instance.new(absolute_path)
|
63
|
-
instance.exports.each do |name, export|
|
64
|
-
case export
|
65
|
-
when Wasmtime::Func
|
66
|
-
mod.define_singleton_method(name) { |*args| export.call(*args) }
|
67
|
-
end
|
68
|
-
end
|
69
|
-
$LOADED_FEATURES << absolute_path
|
70
|
-
true
|
71
|
-
end
|
72
|
-
end
|
data/src/export.rs
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
use rutie::{AnyObject, Object};
|
2
|
-
use wasmtime as w;
|
3
|
-
|
4
|
-
use crate::func::{Func, RubyFunc};
|
5
|
-
use crate::memory::RubyMemory;
|
6
|
-
|
7
|
-
pub enum Export {
|
8
|
-
Func(Func),
|
9
|
-
Memory(w::Memory),
|
10
|
-
}
|
11
|
-
|
12
|
-
impl From<Export> for AnyObject {
|
13
|
-
fn from(export: Export) -> Self {
|
14
|
-
match export {
|
15
|
-
Export::Func(func) => RubyFunc::from(func).value().into(),
|
16
|
-
Export::Memory(memory) => RubyMemory::from(memory).value().into(),
|
17
|
-
}
|
18
|
-
}
|
19
|
-
}
|
data/src/func.rs
DELETED
@@ -1,175 +0,0 @@
|
|
1
|
-
use lazy_static::lazy_static;
|
2
|
-
use rutie as r;
|
3
|
-
use rutie::rubysys;
|
4
|
-
use rutie::{
|
5
|
-
class, methods, wrappable_struct, AnyObject, Array, Float, Hash, Integer, Module, NilClass,
|
6
|
-
Object, RString, Symbol,
|
7
|
-
};
|
8
|
-
use std::mem;
|
9
|
-
use wasmtime as w;
|
10
|
-
|
11
|
-
use crate::ruby_type::RubyType;
|
12
|
-
use crate::vm::raise;
|
13
|
-
|
14
|
-
pub struct Func {
|
15
|
-
func: w::Func,
|
16
|
-
}
|
17
|
-
|
18
|
-
impl Func {
|
19
|
-
pub fn new(func: w::Func) -> Self {
|
20
|
-
Func { func }
|
21
|
-
}
|
22
|
-
|
23
|
-
pub fn call(&mut self, args: &[w::Val]) -> Vec<w::Val> {
|
24
|
-
self.func.call(args).expect("failed to call func").to_vec()
|
25
|
-
}
|
26
|
-
|
27
|
-
fn parse_param_types(&self) -> Vec<RubyType> {
|
28
|
-
self.func
|
29
|
-
.ty()
|
30
|
-
.params()
|
31
|
-
.iter()
|
32
|
-
.map(|val_type| val_type.into())
|
33
|
-
.collect()
|
34
|
-
}
|
35
|
-
|
36
|
-
fn parse_result_type(&self) -> RubyType {
|
37
|
-
match self.func.ty().results().len() {
|
38
|
-
0 => RubyType::NilClass,
|
39
|
-
1 => self.func.ty().results().first().unwrap().into(),
|
40
|
-
_ => raise("StandardError", "multiple return values are not supported"),
|
41
|
-
}
|
42
|
-
}
|
43
|
-
}
|
44
|
-
|
45
|
-
fn translate_incoming(args: Array, param_types: &[RubyType]) -> Vec<w::Val> {
|
46
|
-
if args.length() != param_types.len() {
|
47
|
-
raise(
|
48
|
-
"ArgumentError",
|
49
|
-
&format!(
|
50
|
-
"wrong number of arguments (given {}, expected {})",
|
51
|
-
args.length(),
|
52
|
-
param_types.len()
|
53
|
-
),
|
54
|
-
)
|
55
|
-
}
|
56
|
-
args.into_iter()
|
57
|
-
.zip(param_types)
|
58
|
-
.map(|(arg, param_type)| match param_type {
|
59
|
-
RubyType::Integer32 => w::Val::I32(
|
60
|
-
arg.try_convert_to::<Integer>()
|
61
|
-
.expect("failed to convert integer")
|
62
|
-
.to_i32(),
|
63
|
-
),
|
64
|
-
RubyType::Integer64 => w::Val::I64(
|
65
|
-
arg.try_convert_to::<Integer>()
|
66
|
-
.expect("failed to convert integer")
|
67
|
-
.to_i64(),
|
68
|
-
),
|
69
|
-
RubyType::Float32 => w::Val::F32(
|
70
|
-
(arg.try_convert_to::<Float>()
|
71
|
-
.expect("failed to convert float")
|
72
|
-
.to_f64() as f32)
|
73
|
-
.to_bits(),
|
74
|
-
),
|
75
|
-
RubyType::Float64 => w::Val::F64(
|
76
|
-
arg.try_convert_to::<Float>()
|
77
|
-
.expect("failed to convert float")
|
78
|
-
.to_f64()
|
79
|
-
.to_bits(),
|
80
|
-
),
|
81
|
-
RubyType::NilClass | RubyType::Unsupported => raise(
|
82
|
-
"StandardError",
|
83
|
-
&format!("unsupported arg type: {:?}", param_type),
|
84
|
-
),
|
85
|
-
})
|
86
|
-
.collect()
|
87
|
-
}
|
88
|
-
|
89
|
-
fn translate_outgoing(native_results: Vec<w::Val>) -> AnyObject {
|
90
|
-
let results: Vec<AnyObject> = native_results
|
91
|
-
.into_iter()
|
92
|
-
.map(|r| match r {
|
93
|
-
w::Val::I32(v) => Integer::new(v.into()).into(),
|
94
|
-
w::Val::I64(v) => Integer::new(v).into(),
|
95
|
-
w::Val::F32(v) => Float::new(f32::from_bits(v).into()).into(),
|
96
|
-
w::Val::F64(v) => Float::new(f64::from_bits(v)).into(),
|
97
|
-
_ => raise("StandardError", &format!("unsupported value: {:?}", r)),
|
98
|
-
})
|
99
|
-
.collect();
|
100
|
-
|
101
|
-
match results.len() {
|
102
|
-
0 => NilClass::new().into(),
|
103
|
-
1 => results.first().unwrap().into(),
|
104
|
-
_ => raise("StandardError", "multiple return values are not supported"),
|
105
|
-
}
|
106
|
-
}
|
107
|
-
|
108
|
-
wrappable_struct!(Func, FuncWrapper, FUNC_WRAPPER);
|
109
|
-
class!(RubyFunc);
|
110
|
-
|
111
|
-
impl From<Func> for RubyFunc {
|
112
|
-
fn from(func: Func) -> Self {
|
113
|
-
Module::from_existing("Wasmtime")
|
114
|
-
.get_nested_class("Func")
|
115
|
-
.wrap_data(func, &*FUNC_WRAPPER)
|
116
|
-
}
|
117
|
-
}
|
118
|
-
|
119
|
-
#[rustfmt::skip]
|
120
|
-
methods!(
|
121
|
-
RubyFunc,
|
122
|
-
itself,
|
123
|
-
|
124
|
-
fn ruby_func_signature() -> Hash {
|
125
|
-
let func = itself.get_data(&*FUNC_WRAPPER);
|
126
|
-
|
127
|
-
let mut param_types = Array::new();
|
128
|
-
for param_type in func.parse_param_types().iter() {
|
129
|
-
param_types.push(RString::new_utf8(&format!("{:?}", param_type)));
|
130
|
-
}
|
131
|
-
|
132
|
-
let result_type: AnyObject = func.parse_result_type().into();
|
133
|
-
|
134
|
-
let mut signature = Hash::new();
|
135
|
-
signature.store(Symbol::new("params"), param_types);
|
136
|
-
signature.store(Symbol::new("result"), result_type);
|
137
|
-
|
138
|
-
signature
|
139
|
-
}
|
140
|
-
);
|
141
|
-
|
142
|
-
pub extern "C" fn ruby_func_call(
|
143
|
-
argc: r::types::Argc,
|
144
|
-
argv: *const AnyObject,
|
145
|
-
mut itself: AnyObject,
|
146
|
-
) -> AnyObject {
|
147
|
-
// TODO: Remove this section when rutie `methods!` macro has support for variadic functions
|
148
|
-
// https://github.com/danielpclark/rutie/blob/1c951b59e00944d305ca425267c54115c8c1bb86/README.md#variadic-functions--splat-operator
|
149
|
-
let args_raw = r::types::Value::from(0);
|
150
|
-
unsafe {
|
151
|
-
let p_argv: *const r::types::Value = mem::transmute(argv);
|
152
|
-
rubysys::class::rb_scan_args(
|
153
|
-
argc,
|
154
|
-
p_argv,
|
155
|
-
r::util::str_to_cstring("*").as_ptr(),
|
156
|
-
&args_raw,
|
157
|
-
)
|
158
|
-
};
|
159
|
-
let args = Array::from(args_raw);
|
160
|
-
// ---
|
161
|
-
let func = itself.get_data_mut(&*FUNC_WRAPPER);
|
162
|
-
|
163
|
-
let args_native = translate_incoming(args, &func.parse_param_types());
|
164
|
-
let results_native = func.call(&args_native[..]);
|
165
|
-
translate_outgoing(results_native)
|
166
|
-
}
|
167
|
-
|
168
|
-
pub fn ruby_init() {
|
169
|
-
Module::from_existing("Wasmtime").define(|module| {
|
170
|
-
module.define_nested_class("Func", None).define(|class| {
|
171
|
-
class.def("signature", ruby_func_signature);
|
172
|
-
class.def("call", ruby_func_call);
|
173
|
-
});
|
174
|
-
});
|
175
|
-
}
|