wasmer 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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: []