wasmer 0.1.1

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.
data/src/lib.rs ADDED
@@ -0,0 +1,98 @@
1
+ #![deny(warnings)]
2
+
3
+ use rutie::{Class, Object};
4
+
5
+ pub mod instance;
6
+ pub mod memory;
7
+ pub mod module;
8
+
9
+ #[allow(non_snake_case)]
10
+ #[no_mangle]
11
+ pub extern "C" fn Init_wasmer() {
12
+ let instance_data_class = Class::from_existing("Object");
13
+
14
+ // Declare the `Instance` Ruby class.
15
+ Class::new("Instance", Some(&instance_data_class)).define(|itself| {
16
+ // Declare the `self.new` method.
17
+ itself.def_self("new", instance::ruby_instance_new);
18
+
19
+ // Declare the `exports` getter method.
20
+ itself.def("exports", instance::ruby_instance_exported_functions);
21
+
22
+ // Declare the `memory` getter method.
23
+ itself.def("memory", instance::ruby_instance_memory);
24
+ });
25
+
26
+ let exported_functions_data_class = Class::from_existing("Object");
27
+
28
+ // Declare the `ExportedFunctions` Ruby class.
29
+ Class::new("ExportedFunctions", Some(&exported_functions_data_class)).define(|itself| {
30
+ // Declare the `method_missing` method.
31
+ itself.def(
32
+ "method_missing",
33
+ instance::ruby_exported_functions_method_missing,
34
+ );
35
+ });
36
+
37
+ let module_data_class = Class::from_existing("Object");
38
+
39
+ // Declare the `Module` Ruby class.
40
+ Class::new("Module", Some(&module_data_class)).define(|itself| {
41
+ // Declare the `self.validate` method.
42
+ itself.def_self("validate", module::ruby_module_validate);
43
+ });
44
+
45
+ let memory_data_class = Class::from_existing("Object");
46
+
47
+ // Declare the `Memory` Ruby class.
48
+ Class::new("Memory", Some(&memory_data_class)).define(|itself| {
49
+ // Declare the `view` method.
50
+ itself.def("uint8_view", memory::ruby_memory_uint8array);
51
+
52
+ // Declare the `view` method.
53
+ itself.def("int8_view", memory::ruby_memory_int8array);
54
+
55
+ // Declare the `view` method.
56
+ itself.def("uint16_view", memory::ruby_memory_uint16array);
57
+
58
+ // Declare the `view` method.
59
+ itself.def("int16_view", memory::ruby_memory_int16array);
60
+
61
+ // Declare the `view` method.
62
+ itself.def("uint32_view", memory::ruby_memory_uint32array);
63
+
64
+ // Declare the `view` method.
65
+ itself.def("int32_view", memory::ruby_memory_int32array);
66
+ });
67
+
68
+ macro_rules! memory_view {
69
+ ($class_name:ident in $mod_name:ident) => {
70
+ let uint8array_data_class = Class::from_existing("Object");
71
+
72
+ // Declare the `MemoryView` Ruby class.
73
+ Class::new(stringify!($class_name), Some(&uint8array_data_class)).define(|itself| {
74
+ // Declare the `bytes_per_element` getter method.
75
+ itself.def(
76
+ "bytes_per_element",
77
+ memory::view::$mod_name::ruby_memory_view_bytes_per_element,
78
+ );
79
+
80
+ // Declare the `length` method.
81
+ itself.def("length", memory::view::$mod_name::ruby_memory_view_length);
82
+
83
+ // Declare the `[]=` (set) method.
84
+ itself.def("[]=", memory::view::$mod_name::ruby_memory_view_set);
85
+
86
+ // Declare the `[]` (get) method.
87
+ itself.def("[]", memory::view::$mod_name::ruby_memory_view_get);
88
+ });
89
+ };
90
+ }
91
+
92
+ memory_view!(Uint8Array in uint8array);
93
+ memory_view!(Int8Array in int8array);
94
+ memory_view!(Uint16Array in uint16array);
95
+ memory_view!(Int16Array in int16array);
96
+ memory_view!(Uint32Array in uint32array);
97
+ memory_view!(Int32Array in int32array);
98
+ }
data/src/memory/mod.rs ADDED
@@ -0,0 +1,120 @@
1
+ //! The `Memory` WebAssembly class.
2
+
3
+ pub mod view;
4
+
5
+ use crate::memory::view::{
6
+ int16array::{RubyMemoryView as RubyInt16Array, MEMORY_VIEW_WRAPPER as INT16ARRAY_WRAPPER},
7
+ int32array::{RubyMemoryView as RubyInt32Array, MEMORY_VIEW_WRAPPER as INT32ARRAY_WRAPPER},
8
+ int8array::{RubyMemoryView as RubyInt8Array, MEMORY_VIEW_WRAPPER as INT8ARRAY_WRAPPER},
9
+ uint16array::{RubyMemoryView as RubyUint16Array, MEMORY_VIEW_WRAPPER as UINT16ARRAY_WRAPPER},
10
+ uint32array::{RubyMemoryView as RubyUint32Array, MEMORY_VIEW_WRAPPER as UINT32ARRAY_WRAPPER},
11
+ uint8array::{RubyMemoryView as RubyUint8Array, MEMORY_VIEW_WRAPPER as UINT8ARRAY_WRAPPER},
12
+ };
13
+ use lazy_static::lazy_static;
14
+ use rutie::{class, methods, wrappable_struct, Class, Integer, Object};
15
+ use std::rc::Rc;
16
+ use wasmer_runtime as runtime;
17
+
18
+ pub struct Memory {
19
+ memory: Rc<runtime::Memory>,
20
+ }
21
+
22
+ impl Memory {
23
+ pub fn new(memory: Rc<runtime::Memory>) -> Self {
24
+ Self { memory }
25
+ }
26
+
27
+ pub fn uint8_view(&self, offset: usize) -> view::uint8array::MemoryView {
28
+ view::uint8array::MemoryView::new(self.memory.clone(), offset)
29
+ }
30
+
31
+ pub fn int8_view(&self, offset: usize) -> view::int8array::MemoryView {
32
+ view::int8array::MemoryView::new(self.memory.clone(), offset)
33
+ }
34
+
35
+ pub fn uint16_view(&self, offset: usize) -> view::uint16array::MemoryView {
36
+ view::uint16array::MemoryView::new(self.memory.clone(), offset)
37
+ }
38
+
39
+ pub fn int16_view(&self, offset: usize) -> view::int16array::MemoryView {
40
+ view::int16array::MemoryView::new(self.memory.clone(), offset)
41
+ }
42
+
43
+ pub fn uint32_view(&self, offset: usize) -> view::uint32array::MemoryView {
44
+ view::uint32array::MemoryView::new(self.memory.clone(), offset)
45
+ }
46
+
47
+ pub fn int32_view(&self, offset: usize) -> view::int32array::MemoryView {
48
+ view::int32array::MemoryView::new(self.memory.clone(), offset)
49
+ }
50
+ }
51
+
52
+ wrappable_struct!(Memory, MemoryWrapper, MEMORY_WRAPPER);
53
+
54
+ class!(RubyMemory);
55
+
56
+ #[rustfmt::skip]
57
+ methods!(
58
+ RubyMemory,
59
+ itself,
60
+
61
+ // Glue code to call the `Memory.uint8_view` method.
62
+ fn ruby_memory_uint8array(offset: Integer) -> RubyUint8Array {
63
+ let offset = offset
64
+ .map(|offset| offset.to_i64() as usize)
65
+ .unwrap_or(0);
66
+ let memory_view = itself.get_data(&*MEMORY_WRAPPER).uint8_view(offset);
67
+
68
+ Class::from_existing("Uint8Array").wrap_data(memory_view, &*UINT8ARRAY_WRAPPER)
69
+ }
70
+
71
+ // Glue code to call the `Memory.int8_view` method.
72
+ fn ruby_memory_int8array(offset: Integer) -> RubyInt8Array {
73
+ let offset = offset
74
+ .map(|offset| offset.to_i64() as usize)
75
+ .unwrap_or(0);
76
+ let memory_view = itself.get_data(&*MEMORY_WRAPPER).int8_view(offset);
77
+
78
+ Class::from_existing("Int8Array").wrap_data(memory_view, &*INT8ARRAY_WRAPPER)
79
+ }
80
+
81
+ // Glue code to call the `Memory.uint16_view` method.
82
+ fn ruby_memory_uint16array(offset: Integer) -> RubyUint16Array {
83
+ let offset = offset
84
+ .map(|offset| offset.to_i64() as usize)
85
+ .unwrap_or(0);
86
+ let memory_view = itself.get_data(&*MEMORY_WRAPPER).uint16_view(offset);
87
+
88
+ Class::from_existing("Uint16Array").wrap_data(memory_view, &*UINT16ARRAY_WRAPPER)
89
+ }
90
+
91
+ // Glue code to call the `Memory.int16_view` method.
92
+ fn ruby_memory_int16array(offset: Integer) -> RubyInt16Array {
93
+ let offset = offset
94
+ .map(|offset| offset.to_i64() as usize)
95
+ .unwrap_or(0);
96
+ let memory_view = itself.get_data(&*MEMORY_WRAPPER).int16_view(offset);
97
+
98
+ Class::from_existing("Int16Array").wrap_data(memory_view, &*INT16ARRAY_WRAPPER)
99
+ }
100
+
101
+ // Glue code to call the `Memory.uint32_view` method.
102
+ fn ruby_memory_uint32array(offset: Integer) -> RubyUint32Array {
103
+ let offset = offset
104
+ .map(|offset| offset.to_i64() as usize)
105
+ .unwrap_or(0);
106
+ let memory_view = itself.get_data(&*MEMORY_WRAPPER).uint32_view(offset);
107
+
108
+ Class::from_existing("Uint32Array").wrap_data(memory_view, &*UINT32ARRAY_WRAPPER)
109
+ }
110
+
111
+ // Glue code to call the `Memory.int32_view` method.
112
+ fn ruby_memory_int32array(offset: Integer) -> RubyInt32Array {
113
+ let offset = offset
114
+ .map(|offset| offset.to_i64() as usize)
115
+ .unwrap_or(0);
116
+ let memory_view = itself.get_data(&*MEMORY_WRAPPER).int32_view(offset);
117
+
118
+ Class::from_existing("Int32Array").wrap_data(memory_view, &*INT32ARRAY_WRAPPER)
119
+ }
120
+ );
@@ -0,0 +1,127 @@
1
+ //! The `TypedArray`/`MemoryView` WebAssembly classes.
2
+
3
+ macro_rules! memory_view {
4
+ ($mod_name:ident over $wasm_type:ty | $bytes_per_element:expr) => {
5
+ pub mod $mod_name {
6
+ use lazy_static::lazy_static;
7
+ use rutie::{
8
+ class, methods, wrappable_struct, AnyException, Exception, Fixnum, Integer,
9
+ NilClass, Object, VM,
10
+ };
11
+ use std::{mem::size_of, rc::Rc};
12
+ use wasmer_runtime as runtime;
13
+
14
+ pub struct MemoryView {
15
+ memory: Rc<runtime::memory::Memory>,
16
+ offset: usize,
17
+ }
18
+
19
+ impl MemoryView {
20
+ pub fn new(memory: Rc<runtime::Memory>, offset: usize) -> Self {
21
+ Self { memory, offset }
22
+ }
23
+
24
+ pub fn len(&self) -> usize {
25
+ self.memory.view::<$wasm_type>()[self.offset..].len() / size_of::<$wasm_type>()
26
+ }
27
+
28
+ pub fn set(&self, index: isize, value: $wasm_type) -> Result<(), String> {
29
+ let offset = self.offset;
30
+ let view = self.memory.view::<$wasm_type>();
31
+
32
+ if index < 0 {
33
+ return Err("Out of bound: Index cannot be negative.".into());
34
+ }
35
+
36
+ let index = index as usize;
37
+
38
+ if view.len() <= offset + index {
39
+ Err(format!(
40
+ "Out of bound: Maximum index {} is larger than the memory size {}.",
41
+ offset + index,
42
+ view.len()
43
+ ))
44
+ } else {
45
+ view[offset + index].set(value);
46
+
47
+ Ok(())
48
+ }
49
+ }
50
+
51
+ pub fn get(&self, index: isize) -> Result<$wasm_type, String> {
52
+ let offset = self.offset;
53
+ let view = self.memory.view::<$wasm_type>();
54
+
55
+ if index < 0 {
56
+ return Err("Out of bound: Index cannot be negative.".into());
57
+ }
58
+
59
+ let index = index as usize;
60
+
61
+ if view.len() <= offset + index {
62
+ Err(format!(
63
+ "Out of bound: Maximum index {} is larger than the memory size {}.",
64
+ offset + index,
65
+ view.len()
66
+ ))
67
+ } else {
68
+ Ok(view[offset + index].get())
69
+ }
70
+ }
71
+ }
72
+
73
+ wrappable_struct!(MemoryView, MemoryViewWrapper, MEMORY_VIEW_WRAPPER);
74
+
75
+ class!(RubyMemoryView);
76
+
77
+ #[rustfmt::skip]
78
+ methods!(
79
+ RubyMemoryView,
80
+ _itself,
81
+
82
+ // The `TypedArray.bytes_per_element` method.
83
+ fn ruby_memory_view_bytes_per_element() -> Fixnum {
84
+ Fixnum::new($bytes_per_element)
85
+ }
86
+
87
+ // Glue code to call the `TypedArray.length` method.
88
+ fn ruby_memory_view_length() -> Fixnum {
89
+ Fixnum::new(_itself.get_data(&*MEMORY_VIEW_WRAPPER).len() as i64)
90
+ }
91
+
92
+ // Glue code to call the `TypedArray.set` method.
93
+ fn ruby_memory_view_set(index: Integer, value: Integer) -> NilClass {
94
+ let memory_view = _itself.get_data(&*MEMORY_VIEW_WRAPPER);
95
+ memory_view
96
+ .set(
97
+ index.map_err(|e| VM::raise_ex(e)).unwrap().to_i32() as isize,
98
+ value.map_err(|e| VM::raise_ex(e)).unwrap().to_i32() as $wasm_type,
99
+ )
100
+ .map_err(|e| VM::raise_ex(AnyException::new("ArgumentError", Some(&e))))
101
+ .unwrap();
102
+
103
+ NilClass::new()
104
+ }
105
+
106
+ // Glue code to call the `TypedArray.get` method.
107
+ fn ruby_memory_view_get(index: Integer) -> Fixnum {
108
+ let memory_view = _itself.get_data(&*MEMORY_VIEW_WRAPPER);
109
+
110
+ Fixnum::new(
111
+ memory_view
112
+ .get(index.map_err(|e| VM::raise_ex(e)).unwrap().to_i32() as isize)
113
+ .map_err(|e| VM::raise_ex(AnyException::new("ArgumentError", Some(&e))))
114
+ .unwrap() as i64,
115
+ )
116
+ }
117
+ );
118
+ }
119
+ };
120
+ }
121
+
122
+ memory_view!(uint8array over u8|1);
123
+ memory_view!(int8array over i8|1);
124
+ memory_view!(uint16array over u16|2);
125
+ memory_view!(int16array over i16|2);
126
+ memory_view!(uint32array over u32|4);
127
+ memory_view!(int32array over i32|4);
data/src/module.rs ADDED
@@ -0,0 +1,28 @@
1
+ use rutie::{class, methods, rubysys::value::ValueType, AnyObject, Boolean, Object, RString};
2
+ use wasmer_runtime::validate;
3
+
4
+ class!(Module);
5
+
6
+ methods!(
7
+ Module,
8
+ _itself,
9
+ fn ruby_module_validate(bytes: AnyObject) -> Boolean {
10
+ if let Ok(bytes) = bytes {
11
+ match bytes.ty() {
12
+ ValueType::RString => bytes.try_convert_to::<RString>().ok().map_or_else(
13
+ || Boolean::new(false),
14
+ |string| {
15
+ if validate(string.to_bytes_unchecked()) {
16
+ Boolean::new(true)
17
+ } else {
18
+ Boolean::new(false)
19
+ }
20
+ },
21
+ ),
22
+ _ => Boolean::new(false),
23
+ }
24
+ } else {
25
+ Boolean::new(false)
26
+ }
27
+ }
28
+ );
data/wasmer.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require "wasmer/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "wasmer"
8
+ spec.version = Wasmer::VERSION
9
+ spec.authors = ["Ivan Enderlin"]
10
+ spec.email = ["ivan.enderlin@hoa-project.net"]
11
+
12
+ spec.summary = "Run WebAssembly binaries."
13
+ spec.description = "Wasmer is a Ruby extension to run WebAssembly binaries."
14
+ spec.homepage = "https://github.com/wasmerio/ruby-ext-wasm"
15
+ spec.license = "BSD-3-Clause"
16
+
17
+ spec.extensions = %w(Rakefile)
18
+
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(examples|tests)/}) }
21
+ end
22
+
23
+ spec.require_paths = %w(lib)
24
+
25
+ spec.add_dependency "rutie", "~> 0.0.3"
26
+ spec.add_development_dependency "bundler", "~> 2.0"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "minitest", "~> 5.0"
29
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wasmer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Ivan Enderlin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-05-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rutie
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.3
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ description: Wasmer is a Ruby extension to run WebAssembly binaries.
70
+ email:
71
+ - ivan.enderlin@hoa-project.net
72
+ executables: []
73
+ extensions:
74
+ - Rakefile
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".cargo/config"
78
+ - ".circleci/config.yml"
79
+ - ".github/ISSUE_TEMPLATE/---bug-report.md"
80
+ - ".github/ISSUE_TEMPLATE/---feature-request.md"
81
+ - ".github/ISSUE_TEMPLATE/--question.md"
82
+ - ".gitignore"
83
+ - Cargo.lock
84
+ - Cargo.toml
85
+ - Gemfile
86
+ - README.md
87
+ - Rakefile
88
+ - justfile
89
+ - lib/wasmer.rb
90
+ - lib/wasmer/version.rb
91
+ - src/instance.rs
92
+ - src/lib.rs
93
+ - src/memory/mod.rs
94
+ - src/memory/view.rs
95
+ - src/module.rs
96
+ - wasmer.gemspec
97
+ homepage: https://github.com/wasmerio/ruby-ext-wasm
98
+ licenses:
99
+ - BSD-3-Clause
100
+ metadata: {}
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubygems_version: 3.0.3
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Run WebAssembly binaries.
120
+ test_files: []