wasmer 0.1.1 → 1.0.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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.cargo/config +1 -1
  3. data/.github/workflows/documentation.yml +50 -0
  4. data/.github/workflows/test.yml +73 -0
  5. data/.gitignore +3 -1
  6. data/CHANGELOG.md +225 -0
  7. data/Cargo.lock +747 -708
  8. data/Cargo.toml +7 -21
  9. data/Gemfile +2 -3
  10. data/LICENSE +21 -0
  11. data/README.md +1 -0
  12. data/Rakefile +4 -3
  13. data/bors.toml +6 -0
  14. data/crates/rutie-derive-macros/Cargo.toml +19 -0
  15. data/crates/rutie-derive-macros/README.md +4 -0
  16. data/crates/rutie-derive-macros/src/class.rs +156 -0
  17. data/crates/rutie-derive-macros/src/function.rs +178 -0
  18. data/crates/rutie-derive-macros/src/lib.rs +27 -0
  19. data/crates/rutie-derive-macros/src/methods.rs +282 -0
  20. data/crates/rutie-derive/Cargo.toml +14 -0
  21. data/crates/rutie-derive/README.md +97 -0
  22. data/crates/rutie-derive/src/lib.rs +4 -0
  23. data/crates/rutie-derive/src/upcast.rs +47 -0
  24. data/crates/rutie-test/Cargo.toml +10 -0
  25. data/crates/rutie-test/src/lib.rs +38 -0
  26. data/crates/wasmer/Cargo.toml +27 -0
  27. data/crates/wasmer/README.md +229 -0
  28. data/crates/wasmer/src/doc.rs +1512 -0
  29. data/crates/wasmer/src/error.rs +55 -0
  30. data/crates/wasmer/src/exports.rs +107 -0
  31. data/crates/wasmer/src/externals/function.rs +159 -0
  32. data/crates/wasmer/src/externals/global.rs +62 -0
  33. data/crates/wasmer/src/externals/memory.rs +117 -0
  34. data/crates/wasmer/src/externals/mod.rs +9 -0
  35. data/crates/wasmer/src/externals/table.rs +41 -0
  36. data/crates/wasmer/src/import_object.rs +78 -0
  37. data/crates/wasmer/src/instance.rs +45 -0
  38. data/crates/wasmer/src/lib.rs +307 -0
  39. data/crates/wasmer/src/memory/mod.rs +1 -0
  40. data/crates/wasmer/src/memory/views.rs +112 -0
  41. data/crates/wasmer/src/module.rs +106 -0
  42. data/crates/wasmer/src/prelude.rs +3 -0
  43. data/crates/wasmer/src/store.rs +22 -0
  44. data/crates/wasmer/src/types.rs +396 -0
  45. data/crates/wasmer/src/values.rs +84 -0
  46. data/crates/wasmer/src/wasi.rs +226 -0
  47. data/crates/wasmer/src/wat.rs +20 -0
  48. data/justfile +20 -2
  49. data/lib/wasmer.rb +29 -3
  50. data/wasmer.gemspec +8 -12
  51. metadata +53 -49
  52. data/.circleci/config.yml +0 -70
  53. data/README.md +0 -279
  54. data/lib/wasmer/version.rb +0 -3
  55. data/src/instance.rs +0 -282
  56. data/src/lib.rs +0 -98
  57. data/src/memory/mod.rs +0 -120
  58. data/src/memory/view.rs +0 -127
  59. data/src/module.rs +0 -28
@@ -0,0 +1,27 @@
1
+ mod class;
2
+ mod function;
3
+ mod methods;
4
+
5
+ #[proc_macro_attribute]
6
+ pub fn rubyclass(
7
+ attr: proc_macro::TokenStream,
8
+ input: proc_macro::TokenStream,
9
+ ) -> proc_macro::TokenStream {
10
+ class::entry(attr, input)
11
+ }
12
+
13
+ #[proc_macro_attribute]
14
+ pub fn rubymethods(
15
+ attr: proc_macro::TokenStream,
16
+ input: proc_macro::TokenStream,
17
+ ) -> proc_macro::TokenStream {
18
+ methods::entry(attr, input)
19
+ }
20
+
21
+ #[proc_macro_attribute]
22
+ pub fn rubyfunction(
23
+ attr: proc_macro::TokenStream,
24
+ input: proc_macro::TokenStream,
25
+ ) -> proc_macro::TokenStream {
26
+ function::entry(attr, input)
27
+ }
@@ -0,0 +1,282 @@
1
+ use proc_macro2::{Group, Ident, Span, TokenStream, TokenTree};
2
+ use quote::{quote, ToTokens};
3
+ use syn::{punctuated::Punctuated, token::Colon2, *};
4
+
5
+ pub fn entry(
6
+ _attr: proc_macro::TokenStream,
7
+ input: proc_macro::TokenStream,
8
+ ) -> proc_macro::TokenStream {
9
+ let impl_block = parse_macro_input!(input as ItemImpl);
10
+
11
+ let ty_name = match *impl_block.self_ty {
12
+ Type::Path(TypePath { qself: None, path }) if path.get_ident().is_some() => {
13
+ path.get_ident().unwrap().clone()
14
+ }
15
+
16
+ Type::Group(TypeGroup { elem, .. }) => match *elem {
17
+ Type::Path(TypePath { qself: None, path }) if path.get_ident().is_some() => {
18
+ path.get_ident().unwrap().clone()
19
+ }
20
+ _ => panic!("`impl` block must target a simple grouped identifier"),
21
+ },
22
+
23
+ _ => panic!("`impl` block must target a simple identifier, e.g. `impl T`"),
24
+ };
25
+
26
+ let ruby_rust_module_name = Ident::new(
27
+ &format!("ruby_{}", ty_name.to_string().to_lowercase()),
28
+ Span::call_site(),
29
+ );
30
+ let ruby_ty_name = Ident::new(&format!("Ruby{}", ty_name), ty_name.span());
31
+
32
+ let mut ruby_items = Vec::with_capacity(impl_block.items.len());
33
+
34
+ for item in impl_block.items {
35
+ match item {
36
+ ImplItem::Method(method) => {
37
+ if !method.attrs.is_empty() {
38
+ panic!("Methods in `impl` block do not support attributes for the moment");
39
+ }
40
+
41
+ let method_name = method.sig.ident.to_string();
42
+
43
+ if method.sig.constness.is_some() {
44
+ panic!("Method `{}` cannot be `const`", method_name);
45
+ }
46
+
47
+ if method.sig.asyncness.is_some() {
48
+ panic!("Method `{}` cannot be `async`", method_name);
49
+ }
50
+
51
+ if method.sig.unsafety.is_some() {
52
+ panic!("Method `{}` cannot be `unsafe`", method_name);
53
+ }
54
+
55
+ if method.sig.abi.is_some() {
56
+ panic!("Method `{}` cannot have a different ABI", method_name);
57
+ }
58
+
59
+ if !method.sig.generics.params.is_empty() {
60
+ panic!("Method `{}` cannot be generic", method_name);
61
+ }
62
+
63
+ if method.sig.variadic.is_some() {
64
+ panic!("Method `{}` cannot be variadic", method_name);
65
+ }
66
+
67
+ let ruby_method_name = &method.sig.ident;
68
+ let ruby_method_block = &method.block;
69
+ let ruby_method_visibility = &method.vis;
70
+
71
+ let mut need_self = false;
72
+ let mut need_mut_self = false;
73
+
74
+ let ruby_arguments_parsing = {
75
+ let (ruby_input_names, ruby_input_types): (
76
+ Vec<Ident>,
77
+ Vec<Punctuated<PathSegment, Colon2>>,
78
+ ) = method
79
+ .sig
80
+ .inputs
81
+ .iter()
82
+ .filter_map(|input| match input {
83
+ FnArg::Receiver(Receiver { mutability, .. }) => {
84
+ need_self = true;
85
+ need_mut_self = mutability.is_some();
86
+
87
+ None
88
+ }
89
+ FnArg::Typed(PatType { pat, ty, .. }) => match (&**pat, &**ty) {
90
+ (
91
+ Pat::Ident(ident),
92
+ Type::Reference(TypeReference { elem, .. }),
93
+ ) => match &**elem {
94
+ Type::Path(TypePath {
95
+ qself: None,
96
+ path: Path { segments: ty, .. },
97
+ }) => Some((ident.ident.clone(), ty.clone())),
98
+ _ => panic!(
99
+ "Typed input has an unsupported form (method `{}`)",
100
+ method_name
101
+ ),
102
+ },
103
+ _ => panic!(
104
+ "Typed input has an unsupported form (method `{}`), it must be a reference type",
105
+ method_name
106
+ ),
107
+ },
108
+ })
109
+ .unzip();
110
+
111
+ if ruby_input_names.is_empty() {
112
+ quote! {}
113
+ } else {
114
+ quote! {
115
+ let ( #( #ruby_input_names ),* ) =
116
+ {
117
+ let arguments = rutie::util::parse_arguments(argc, argv);
118
+ let mut argument_nth = 0;
119
+
120
+ (
121
+ #(
122
+ {
123
+ let argument = arguments
124
+ .get(argument_nth)
125
+ .ok_or_else(|| {
126
+ <rutie::AnyException as rutie::Exception>::new(
127
+ "ArgumentError",
128
+ Some(&format!(concat!("Argument #{} (`", stringify!( #ruby_input_types ), "`) of method `", stringify!( #ty_name ), ".", stringify!( #ruby_method_name ), "` is missing"), argument_nth)),
129
+ )
130
+ })
131
+ .and_then(|argument| {
132
+ <rutie::AnyObject as rutie::Object>
133
+ ::try_convert_to::<< #ruby_input_types as rutie_derive::ClassInfo>::RubyClass>(argument)
134
+ })
135
+ .unwrap_or_else(|error| {
136
+ rutie::VM::raise_ex(error);
137
+ unreachable!()
138
+ });
139
+
140
+ argument_nth += 1;
141
+
142
+ argument
143
+ }
144
+ ),*
145
+ )
146
+ };
147
+
148
+ let ( #( #ruby_input_names ),* ) =
149
+ (
150
+ #(
151
+ rutie_derive::UpcastRubyClass::<
152
+ <
153
+ < #ruby_input_types as rutie_derive::ClassInfo>::RubyClass as rutie_derive::ClassInfo
154
+ >::Class
155
+ >::upcast(&#ruby_input_names)
156
+ ),*
157
+ );
158
+ }
159
+ }
160
+ };
161
+
162
+ let ruby_input_receiver = if need_mut_self {
163
+ quote! { mut _ruby_self: #ruby_ty_name }
164
+ } else {
165
+ quote! { _ruby_self: #ruby_ty_name }
166
+ };
167
+
168
+ let ruby_output = match method.sig.output {
169
+ ReturnType::Type(_, ty) => match *ty {
170
+ Type::Path(TypePath {
171
+ qself: None,
172
+ path: Path {
173
+ leading_colon: None,
174
+ segments,
175
+ }
176
+ }) if segments.first().unwrap().ident.to_string() == "RubyResult" => {
177
+ match &segments.first().unwrap().arguments {
178
+ PathArguments::AngleBracketed(AngleBracketedGenericArguments {
179
+ args,
180
+ ..
181
+ }) => match args.first().unwrap() {
182
+ GenericArgument::Type(ty) => ty.clone(),
183
+ _ => panic!("Method has not well-formed rerturned type, expect `RubyResult<T>` where `T` is a type"),
184
+ },
185
+ _ => panic!("Method has not well-formed returned type, expect `RubyResult<T>`"),
186
+ }
187
+ }
188
+ _ => panic!("Method must wrap their output type inside `RubyResult<T>`"),
189
+ },
190
+ _ => panic!("Method must have an output of the form `RubyResult<T>`"),
191
+ };
192
+
193
+ let ruby_method_block = if need_self {
194
+ let slf_declaration = if need_mut_self {
195
+ quote! {
196
+ let _slf = _ruby_self.upcast_mut();
197
+ }
198
+ } else {
199
+ quote! {
200
+ let _slf = _ruby_self.upcast();
201
+ }
202
+ };
203
+ let block = rename_self(ruby_method_block.into_token_stream());
204
+
205
+ quote! {
206
+ #slf_declaration
207
+
208
+ #block
209
+ }
210
+ } else {
211
+ ruby_method_block.into_token_stream()
212
+ };
213
+
214
+ let ruby_block_visibility = if need_mut_self {
215
+ quote! { mut }
216
+ } else {
217
+ quote! {}
218
+ };
219
+
220
+ ruby_items.push(quote! {
221
+ #[allow(improper_ctypes_definitions)] // Not ideal but that's how Rutie works.
222
+ #ruby_method_visibility extern "C" fn #ruby_method_name(
223
+ argc: rutie::types::Argc,
224
+ argv: *const rutie::AnyObject,
225
+ #ruby_input_receiver,
226
+ ) -> #ruby_output {
227
+ #ruby_arguments_parsing
228
+
229
+ let #ruby_block_visibility block = || -> Result<_, rutie::AnyException> {
230
+ #ruby_method_block
231
+ };
232
+
233
+ match block() {
234
+ Ok(x) => x,
235
+ Err(e) => {
236
+ rutie::VM::raise_ex(e);
237
+ unreachable!()
238
+ }
239
+ }
240
+ }
241
+ });
242
+ }
243
+
244
+ _ => panic!("`impl` block only supports methods for the moment"),
245
+ }
246
+ }
247
+
248
+ (quote! {
249
+ pub(crate) mod #ruby_rust_module_name {
250
+ use super::*;
251
+
252
+ #(#ruby_items)*
253
+ }
254
+ })
255
+ .into()
256
+ }
257
+
258
+ fn rename_self(stream: TokenStream) -> TokenStream {
259
+ let mut output_stream = TokenStream::new();
260
+
261
+ output_stream.extend(
262
+ stream
263
+ .into_iter()
264
+ .map(|token| match token {
265
+ TokenTree::Group(group) => {
266
+ TokenTree::Group(Group::new(group.delimiter(), rename_self(group.stream())))
267
+ }
268
+ TokenTree::Ident(ident) => {
269
+ if ident.to_string() == "self" {
270
+ TokenTree::Ident(Ident::new("_slf", ident.span()))
271
+ } else {
272
+ TokenTree::Ident(ident)
273
+ }
274
+ }
275
+ TokenTree::Punct(punct) => TokenTree::Punct(punct),
276
+ TokenTree::Literal(literal) => TokenTree::Literal(literal),
277
+ })
278
+ .collect::<Vec<TokenTree>>(),
279
+ );
280
+
281
+ output_stream
282
+ }
@@ -0,0 +1,14 @@
1
+ [package]
2
+ name = "rutie-derive"
3
+ version = "0.1.0"
4
+ authors = ["Wasmer Engineering Team <engineering@wasmer.io>"]
5
+ edition = "2018"
6
+ description = "Provide useful types to complete the `rutie-derive-macros` crate"
7
+ readme = "README.md"
8
+ repository = "https://github.com/wasmerio/wasmer-ruby"
9
+ keywords = ["ruby", "extension"]
10
+ publish = false
11
+
12
+ [dependencies]
13
+ rutie = "0.8"
14
+ rutie-derive-macros = { path = "../rutie-derive-macros", version = "0.1.0" }
@@ -0,0 +1,97 @@
1
+ # `rutie-derive`
2
+
3
+ **Note**: This is not an official project from
4
+ [`rutie`](https://github.com/danielpclark/rutie).
5
+
6
+ We try to extend `rutie` with a new Domain Specific Language (DSL for
7
+ short) based on new procedural macros to make it easier to declare
8
+ Ruby modules, classes, methods and functions.
9
+
10
+ This crate is the front API that provides the `#[ruby*]` procedural
11
+ macros from the `rutie-derive-macros` crate, along with some extra
12
+ traits and implementations to make everything work magically.
13
+
14
+ ## Ruby class
15
+
16
+ To declare a new Ruby class, use `#[rubyclass(module = "X::Y::Z")]`:
17
+
18
+ ```rust
19
+ #[rubyclass(module = "Wasmer")]
20
+ pub struct Foo;
21
+ ```
22
+
23
+ It will create a new type `Foo` in Rust, and a new class `Foo` in Ruby
24
+ inside the `Wasmer` module.
25
+
26
+ ### Constructor
27
+
28
+ Every class has a Rust `ruby_new` associated method to create a new
29
+ instance of this Ruby type.
30
+
31
+ ## Ruby methods
32
+
33
+ To declare methods attached to a class, use `#[rubymethods]`:
34
+
35
+ ```rust
36
+ #[rubymethods]
37
+ impl Foo {
38
+ /// Constructor.
39
+ pub fn new() -> RubyResult<Foo> {
40
+ Ok(Foo::ruby_new(Foo))
41
+ }
42
+
43
+ // Method.
44
+ pub fn bar(&self, x: &Integer, y: &Integer) -> RubyResult<Integer> {
45
+ Ok(Integer::new(x.to_i64() + x.to_i64()))
46
+ }
47
+ }
48
+ ```
49
+
50
+ Ruby methods are like Rust methods:
51
+
52
+ * Without a receiver (`&self`), it's a static method (`def self`),
53
+ * With a receiver (`&self` or `&mut self`), it's a method (`def`),
54
+ * All arguments are received by reference,
55
+ * The returned type is required to be a `RubyResult`. The error type
56
+ is `AnyException`.
57
+
58
+ ### “Rust-defined” Ruby types
59
+
60
+ Arguments can be of kind “user-defined types”, let's see:
61
+
62
+ ```rust
63
+ #[rubyclass(module = "Wasmer")]
64
+ pub struct Baz {
65
+ inner: i32,
66
+ };
67
+
68
+ #[rubyclass(module = "Wasmer")]
69
+ pub struct Foo;
70
+
71
+ #[rubymethods]
72
+ impl Foo {
73
+ pub fn bar(&self, baz: &Baz) -> RubyResult<…> {
74
+ let inner = &baz.inner;
75
+
76
+
77
+ }
78
+ }
79
+ ```
80
+
81
+ ## Ruby functions
82
+
83
+ Just like `#[rubymethods]`, `#[rubyfunction]` will create a Ruby
84
+ function:
85
+
86
+ ```rust
87
+ #[rubyfunction]
88
+ fn hello(who: &RString) -> RubyResult<RString> {
89
+ Ok(RString::new_utf8(&format!("Hello, {}!", who.to_str())))
90
+ }
91
+ ```
92
+
93
+ ## License
94
+
95
+ Check the license of
96
+ [`wasmer-ruby`](https://github.com/wasmerio/wasmer-ruby/) as it is
97
+ part of this same project.
@@ -0,0 +1,4 @@
1
+ mod upcast;
2
+
3
+ pub use rutie_derive_macros::{rubyclass, rubyfunction, rubymethods};
4
+ pub use upcast::*;
@@ -0,0 +1,47 @@
1
+ pub trait ClassInfo {
2
+ type Class;
3
+ type RubyClass;
4
+ }
5
+
6
+ pub trait UpcastRubyClass<T> {
7
+ fn upcast(&self) -> &T;
8
+
9
+ fn upcast_mut(&mut self) -> &mut T;
10
+ }
11
+
12
+ macro_rules! id_impl {
13
+ ($ty:ty) => {
14
+ impl ClassInfo for $ty {
15
+ type Class = Self;
16
+ type RubyClass = Self;
17
+ }
18
+
19
+ impl UpcastRubyClass<$ty> for $ty {
20
+ fn upcast(&self) -> &$ty {
21
+ self
22
+ }
23
+
24
+ fn upcast_mut(&mut self) -> &mut $ty {
25
+ self
26
+ }
27
+ }
28
+ };
29
+
30
+ ( $( $ty:ty ),+ $(,)* ) => {
31
+ $( id_impl!( $ty ); )*
32
+ }
33
+ }
34
+
35
+ id_impl!(
36
+ rutie::AnyObject,
37
+ rutie::Array,
38
+ rutie::Boolean,
39
+ rutie::Fixnum,
40
+ rutie::Float,
41
+ rutie::Hash,
42
+ rutie::Integer,
43
+ rutie::NilClass,
44
+ rutie::Proc,
45
+ rutie::RString,
46
+ rutie::Symbol,
47
+ );