wasmer 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/documentation.yml +50 -0
  3. data/.github/workflows/test.yml +34 -61
  4. data/CHANGELOG.md +89 -29
  5. data/Cargo.lock +812 -380
  6. data/Cargo.toml +7 -20
  7. data/Gemfile +2 -3
  8. data/README.md +1 -0
  9. data/Rakefile +4 -3
  10. data/crates/rutie-derive-macros/Cargo.toml +19 -0
  11. data/crates/rutie-derive-macros/README.md +4 -0
  12. data/crates/rutie-derive-macros/src/class.rs +156 -0
  13. data/crates/rutie-derive-macros/src/function.rs +178 -0
  14. data/crates/rutie-derive-macros/src/lib.rs +27 -0
  15. data/crates/rutie-derive-macros/src/methods.rs +282 -0
  16. data/crates/rutie-derive/Cargo.toml +14 -0
  17. data/crates/rutie-derive/README.md +97 -0
  18. data/crates/rutie-derive/src/lib.rs +4 -0
  19. data/crates/rutie-derive/src/upcast.rs +47 -0
  20. data/crates/rutie-test/Cargo.toml +10 -0
  21. data/crates/rutie-test/src/lib.rs +38 -0
  22. data/crates/wasmer/Cargo.toml +27 -0
  23. data/crates/wasmer/README.md +228 -0
  24. data/crates/wasmer/src/doc.rs +1512 -0
  25. data/crates/wasmer/src/error.rs +55 -0
  26. data/crates/wasmer/src/exports.rs +107 -0
  27. data/crates/wasmer/src/externals/function.rs +159 -0
  28. data/crates/wasmer/src/externals/global.rs +62 -0
  29. data/crates/wasmer/src/externals/memory.rs +117 -0
  30. data/crates/wasmer/src/externals/mod.rs +9 -0
  31. data/crates/wasmer/src/externals/table.rs +41 -0
  32. data/crates/wasmer/src/import_object.rs +78 -0
  33. data/crates/wasmer/src/instance.rs +45 -0
  34. data/crates/wasmer/src/lib.rs +307 -0
  35. data/crates/wasmer/src/memory/mod.rs +1 -0
  36. data/crates/wasmer/src/memory/views.rs +112 -0
  37. data/crates/wasmer/src/module.rs +106 -0
  38. data/crates/wasmer/src/prelude.rs +3 -0
  39. data/crates/wasmer/src/store.rs +22 -0
  40. data/crates/wasmer/src/types.rs +390 -0
  41. data/crates/wasmer/src/values.rs +84 -0
  42. data/crates/wasmer/src/wasi.rs +226 -0
  43. data/crates/wasmer/src/wat.rs +20 -0
  44. data/justfile +7 -1
  45. data/lib/wasmer.rb +29 -3
  46. data/wasmer.gemspec +6 -10
  47. metadata +45 -47
  48. data/README.md +0 -332
  49. data/lib/wasmer/version.rb +0 -3
  50. data/src/error.rs +0 -16
  51. data/src/instance/exports.rs +0 -215
  52. data/src/instance/globals.rs +0 -234
  53. data/src/instance/mod.rs +0 -141
  54. data/src/lib.rs +0 -162
  55. data/src/memory/mod.rs +0 -158
  56. data/src/memory/view.rs +0 -145
  57. data/src/module.rs +0 -28
@@ -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
+ );