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 @@
1
+ pub mod views;
@@ -0,0 +1,112 @@
1
+ use crate::{
2
+ error::{to_ruby_err, ArgumentError, IndexError, TypeError},
3
+ prelude::*,
4
+ };
5
+ use rutie::{Integer, NilClass, VM};
6
+ use std::{
7
+ convert::{TryFrom, TryInto},
8
+ mem::size_of,
9
+ };
10
+
11
+ macro_rules! memory_view {
12
+ ($class_name:ident over $wasm_type:ty | $bytes_per_element:expr) => {
13
+ #[rubyclass(module = "Wasmer")]
14
+ pub struct $class_name {
15
+ memory: wasmer::Memory,
16
+ offset: usize,
17
+ }
18
+
19
+ impl $class_name {
20
+ pub const BYTES_PER_ELEMENT: u32 = $bytes_per_element;
21
+
22
+ pub fn new(memory: wasmer::Memory, offset: usize) -> Self {
23
+ Self { memory, offset }
24
+ }
25
+ }
26
+
27
+ #[rubymethods]
28
+ impl $class_name {
29
+ pub fn length(&self) -> RubyResult<Integer> {
30
+ Ok(Integer::new(
31
+ (self.memory.view::<$wasm_type>()[self.offset..].len()
32
+ / size_of::<$wasm_type>())
33
+ .try_into()
34
+ .map_err(to_ruby_err::<TypeError, _>)?,
35
+ ))
36
+ }
37
+
38
+ pub fn set(&self, index: &Integer, value: &Integer) -> RubyResult<NilClass> {
39
+ let index =
40
+ isize::try_from(index.to_i32()).map_err(to_ruby_err::<ArgumentError, _>)?;
41
+ let value = <$wasm_type>::try_from(value.to_u64())
42
+ .map_err(to_ruby_err::<ArgumentError, _>)?;
43
+
44
+ let offset = self.offset;
45
+ let view = self.memory.view::<$wasm_type>();
46
+
47
+ if index < 0 {
48
+ return Err(to_ruby_err::<IndexError, _>(
49
+ "Out of bound: Index cannot be negative",
50
+ ));
51
+ }
52
+
53
+ let index = index as usize;
54
+
55
+ if view.len() <= offset + index {
56
+ return Err(to_ruby_err::<IndexError, _>(format!(
57
+ "Out of bound: Maximum index {} is larger than the memory size {}",
58
+ offset + index,
59
+ view.len()
60
+ )));
61
+ }
62
+
63
+ view[offset + index].set(value);
64
+
65
+ Ok(NilClass::new())
66
+ }
67
+
68
+ pub fn get(&self, index: &Integer) -> RubyResult<Integer> {
69
+ let index =
70
+ isize::try_from(index.to_i32()).map_err(to_ruby_err::<ArgumentError, _>)?;
71
+
72
+ let offset = self.offset;
73
+ let view = self.memory.view::<$wasm_type>();
74
+
75
+ if index < 0 {
76
+ return Err(to_ruby_err::<IndexError, _>(
77
+ "Out of bound: Index cannot be negative.",
78
+ ));
79
+ }
80
+
81
+ let index = index as usize;
82
+
83
+ if view.len() <= offset + index {
84
+ return Err(to_ruby_err::<IndexError, _>(format!(
85
+ "Out of bound: Maximum index {} is larger than the memory size {}.",
86
+ offset + index,
87
+ view.len()
88
+ )));
89
+ }
90
+
91
+ Ok(Integer::new(view[offset + index].get().into()))
92
+ }
93
+
94
+ pub fn each(&self) -> RubyResult<NilClass> {
95
+ let view = self.memory.view::<$wasm_type>();
96
+
97
+ for nth in self.offset..view.len() {
98
+ VM::yield_object(Integer::new(view[nth].get().into()));
99
+ }
100
+
101
+ Ok(NilClass::new())
102
+ }
103
+ }
104
+ };
105
+ }
106
+
107
+ memory_view!(Uint8Array over u8|1);
108
+ memory_view!(Int8Array over i8|1);
109
+ memory_view!(Uint16Array over u16|2);
110
+ memory_view!(Int16Array over i16|2);
111
+ memory_view!(Uint32Array over u32|4);
112
+ memory_view!(Int32Array over i32|4);
@@ -0,0 +1,106 @@
1
+ use crate::{
2
+ error::{to_ruby_err, RuntimeError},
3
+ prelude::*,
4
+ store::Store,
5
+ types::{ExportType, ImportType},
6
+ };
7
+ use rutie::{AnyObject, Array, Boolean, Encoding, NilClass, Object, RString};
8
+ use std::convert::TryFrom;
9
+
10
+ #[rubyclass(module = "Wasmer")]
11
+ pub struct Module {
12
+ inner: wasmer::Module,
13
+ }
14
+
15
+ impl Module {
16
+ pub(crate) fn inner(&self) -> &wasmer::Module {
17
+ &self.inner
18
+ }
19
+
20
+ fn inner_mut(&mut self) -> &mut wasmer::Module {
21
+ &mut self.inner
22
+ }
23
+ }
24
+
25
+ #[rubymethods]
26
+ impl Module {
27
+ pub fn new(store: &Store, bytes: &RString) -> RubyResult<AnyObject> {
28
+ let module = wasmer::Module::new(store.inner(), bytes.to_bytes_unchecked());
29
+
30
+ Ok(Module::ruby_new(Module {
31
+ inner: module.map_err(to_ruby_err::<RuntimeError, _>)?,
32
+ }))
33
+ }
34
+
35
+ pub fn validate(store: &Store, bytes: &AnyObject) -> RubyResult<Boolean> {
36
+ Ok(Boolean::new(match bytes.try_convert_to::<RString>() {
37
+ Ok(bytes) => {
38
+ wasmer::Module::validate(store.inner(), bytes.to_bytes_unchecked()).is_ok()
39
+ }
40
+ _ => false,
41
+ }))
42
+ }
43
+
44
+ pub fn get_name(&self) -> RubyResult<AnyObject> {
45
+ Ok(self.inner().name().map_or_else(
46
+ || NilClass::new().to_any_object(),
47
+ |name| RString::new_utf8(name).to_any_object(),
48
+ ))
49
+ }
50
+
51
+ pub fn set_name(&mut self, name: &RString) -> RubyResult<NilClass> {
52
+ self.inner_mut().set_name(name.to_str());
53
+
54
+ Ok(NilClass::new())
55
+ }
56
+
57
+ pub fn exports(&self) -> RubyResult<Array> {
58
+ let exports = self.inner.exports();
59
+ let mut array = Array::with_capacity(exports.len());
60
+
61
+ for export_type in exports.map(|export_type| ExportType::try_from(export_type)) {
62
+ array.push(ExportType::ruby_new(export_type?));
63
+ }
64
+
65
+ Ok(array)
66
+ }
67
+
68
+ pub fn imports(&self) -> RubyResult<Array> {
69
+ let imports = self.inner.imports();
70
+ let mut array = Array::with_capacity(imports.len());
71
+
72
+ for import_type in imports.map(|import_type| ImportType::try_from(import_type)) {
73
+ array.push(ImportType::ruby_new(import_type?));
74
+ }
75
+
76
+ Ok(array)
77
+ }
78
+
79
+ pub fn custom_sections(&self, name: &RString) -> RubyResult<Array> {
80
+ Ok(self
81
+ .inner()
82
+ .custom_sections(name.to_str())
83
+ .map(|custom_section| {
84
+ RString::from_bytes(&custom_section, &Encoding::us_ascii()).to_any_object()
85
+ })
86
+ .collect())
87
+ }
88
+
89
+ pub fn serialize(&self) -> RubyResult<RString> {
90
+ Ok(RString::from_bytes(
91
+ self.inner()
92
+ .serialize()
93
+ .map_err(to_ruby_err::<RuntimeError, _>)?
94
+ .as_slice(),
95
+ &Encoding::us_ascii(),
96
+ ))
97
+ }
98
+
99
+ pub fn deserialize(store: &Store, bytes: &RString) -> RubyResult<AnyObject> {
100
+ let module =
101
+ unsafe { wasmer::Module::deserialize(store.inner(), bytes.to_bytes_unchecked()) }
102
+ .map_err(to_ruby_err::<RuntimeError, _>)?;
103
+
104
+ Ok(Module::ruby_new(Module { inner: module }))
105
+ }
106
+ }
@@ -0,0 +1,3 @@
1
+ pub use crate::error::RubyResult;
2
+ pub use lazy_static::lazy_static;
3
+ pub use rutie_derive::{rubyclass, rubyfunction, rubymethods, ClassInfo, UpcastRubyClass};
@@ -0,0 +1,22 @@
1
+ use crate::prelude::*;
2
+ use rutie::AnyObject;
3
+
4
+ #[rubyclass(module = "Wasmer")]
5
+ pub struct Store {
6
+ inner: wasmer::Store,
7
+ }
8
+
9
+ impl Store {
10
+ pub(crate) fn inner(&self) -> &wasmer::Store {
11
+ &self.inner
12
+ }
13
+ }
14
+
15
+ #[rubymethods]
16
+ impl Store {
17
+ pub fn new() -> RubyResult<AnyObject> {
18
+ Ok(Store::ruby_new(Store {
19
+ inner: Default::default(),
20
+ }))
21
+ }
22
+ }
@@ -0,0 +1,390 @@
1
+ use crate::{
2
+ error::{to_ruby_err, TypeError},
3
+ prelude::*,
4
+ };
5
+ use rutie::{AnyException, AnyObject, Array, Boolean, Integer, NilClass, Object, RString};
6
+ use std::convert::TryFrom;
7
+
8
+ #[derive(Debug, Copy, Clone)]
9
+ #[repr(u8)]
10
+ pub enum Type {
11
+ I32 = 1,
12
+ I64 = 2,
13
+ F32 = 3,
14
+ F64 = 4,
15
+ V128 = 5,
16
+ ExternRef = 6,
17
+ FuncRef = 7,
18
+ }
19
+
20
+ impl Type {
21
+ fn to_integer(&self) -> Integer {
22
+ match self {
23
+ Self::I32 => Integer::new(1),
24
+ Self::I64 => Integer::new(2),
25
+ Self::F32 => Integer::new(3),
26
+ Self::F64 => Integer::new(4),
27
+ Self::V128 => Integer::new(5),
28
+ Self::ExternRef => Integer::new(6),
29
+ Self::FuncRef => Integer::new(7),
30
+ }
31
+ }
32
+ }
33
+
34
+ impl From<&wasmer::Type> for Type {
35
+ fn from(value: &wasmer::Type) -> Self {
36
+ match value {
37
+ wasmer::Type::I32 => Self::I32,
38
+ wasmer::Type::I64 => Self::I64,
39
+ wasmer::Type::F32 => Self::F32,
40
+ wasmer::Type::F64 => Self::F64,
41
+ wasmer::Type::V128 => Self::V128,
42
+ wasmer::Type::ExternRef => Self::ExternRef,
43
+ wasmer::Type::FuncRef => Self::FuncRef,
44
+ }
45
+ }
46
+ }
47
+
48
+ impl Into<wasmer::Type> for Type {
49
+ fn into(self) -> wasmer::Type {
50
+ match self {
51
+ Self::I32 => wasmer::Type::I32,
52
+ Self::I64 => wasmer::Type::I64,
53
+ Self::F32 => wasmer::Type::F32,
54
+ Self::F64 => wasmer::Type::F64,
55
+ Self::V128 => wasmer::Type::V128,
56
+ Self::ExternRef => wasmer::Type::ExternRef,
57
+ Self::FuncRef => wasmer::Type::FuncRef,
58
+ }
59
+ }
60
+ }
61
+
62
+ impl TryFrom<&Integer> for Type {
63
+ type Error = &'static str;
64
+
65
+ fn try_from(value: &Integer) -> Result<Self, Self::Error> {
66
+ Ok(match value.to_i32() {
67
+ 1 => Type::I32,
68
+ 2 => Type::I64,
69
+ 3 => Type::F32,
70
+ 4 => Type::F64,
71
+ 5 => Type::V128,
72
+ 6 => Type::ExternRef,
73
+ 7 => Type::FuncRef,
74
+ _ => return Err("Unrecognized type"),
75
+ })
76
+ }
77
+ }
78
+
79
+ #[rubyclass(module = "Wasmer")]
80
+ pub struct FunctionType {
81
+ pub params: Vec<Type>,
82
+ pub results: Vec<Type>,
83
+ }
84
+
85
+ #[rubymethods]
86
+ impl FunctionType {
87
+ pub fn new(params: &Array, results: &Array) -> RubyResult<AnyObject> {
88
+ let params = unsafe { params.to_any_object().to::<Array>() }
89
+ .into_iter()
90
+ .map(|param| {
91
+ param
92
+ .try_convert_to::<Integer>()
93
+ .and_then(|param| Type::try_from(&param).map_err(to_ruby_err::<TypeError, _>))
94
+ })
95
+ .collect::<Result<Vec<Type>, AnyException>>()?;
96
+ let results = unsafe { results.to_any_object().to::<Array>() }
97
+ .into_iter()
98
+ .map(|result| {
99
+ result
100
+ .try_convert_to::<Integer>()
101
+ .and_then(|result| Type::try_from(&result).map_err(to_ruby_err::<TypeError, _>))
102
+ })
103
+ .collect::<Result<Vec<Type>, AnyException>>()?;
104
+
105
+ Ok(FunctionType::ruby_new(FunctionType { params, results }))
106
+ }
107
+
108
+ pub fn params(&self) -> RubyResult<Array> {
109
+ Ok(self
110
+ .params
111
+ .iter()
112
+ .map(|ty| Type::to_integer(ty).to_any_object())
113
+ .collect())
114
+ }
115
+
116
+ pub fn results(&self) -> RubyResult<Array> {
117
+ Ok(self
118
+ .results
119
+ .iter()
120
+ .map(|ty| Type::to_integer(ty).to_any_object())
121
+ .collect())
122
+ }
123
+ }
124
+
125
+ impl From<&wasmer::FunctionType> for FunctionType {
126
+ fn from(value: &wasmer::FunctionType) -> Self {
127
+ Self {
128
+ params: value.params().iter().map(Into::into).collect(),
129
+ results: value.results().iter().map(Into::into).collect(),
130
+ }
131
+ }
132
+ }
133
+
134
+ impl Into<wasmer::FunctionType> for &FunctionType {
135
+ fn into(self) -> wasmer::FunctionType {
136
+ wasmer::FunctionType::new(
137
+ self.params
138
+ .iter()
139
+ .cloned()
140
+ .map(Into::into)
141
+ .collect::<Vec<_>>(),
142
+ self.results
143
+ .iter()
144
+ .cloned()
145
+ .map(Into::into)
146
+ .collect::<Vec<_>>(),
147
+ )
148
+ }
149
+ }
150
+
151
+ #[rubyclass(module = "Wasmer")]
152
+ pub struct MemoryType {
153
+ pub minimum: u32,
154
+ pub maximum: Option<u32>,
155
+ pub shared: bool,
156
+ }
157
+
158
+ #[rubymethods]
159
+ impl MemoryType {
160
+ pub fn new(minimum: &Integer, maximum: &AnyObject, shared: &Boolean) -> RubyResult<AnyObject> {
161
+ Ok(MemoryType::ruby_new(MemoryType {
162
+ minimum: minimum.to_u64() as _,
163
+ maximum: if maximum.is_nil() {
164
+ None
165
+ } else {
166
+ Some(maximum.try_convert_to::<Integer>()?.to_u64() as _)
167
+ },
168
+ shared: shared.to_bool(),
169
+ }))
170
+ }
171
+
172
+ pub fn minimum(&self) -> RubyResult<Integer> {
173
+ Ok(Integer::new(self.minimum.into()))
174
+ }
175
+
176
+ pub fn maximum(&self) -> RubyResult<AnyObject> {
177
+ Ok(match self.maximum {
178
+ Some(maximum) => Integer::new(maximum.into()).to_any_object(),
179
+ None => NilClass::new().to_any_object(),
180
+ })
181
+ }
182
+
183
+ pub fn shared(&self) -> RubyResult<Boolean> {
184
+ Ok(Boolean::new(self.shared))
185
+ }
186
+ }
187
+
188
+ impl From<&wasmer::MemoryType> for MemoryType {
189
+ fn from(value: &wasmer::MemoryType) -> Self {
190
+ Self {
191
+ minimum: value.minimum.0,
192
+ maximum: value.maximum.map(|pages| pages.0),
193
+ shared: value.shared,
194
+ }
195
+ }
196
+ }
197
+
198
+ impl Into<wasmer::MemoryType> for &MemoryType {
199
+ fn into(self) -> wasmer::MemoryType {
200
+ wasmer::MemoryType::new(self.minimum, self.maximum, self.shared)
201
+ }
202
+ }
203
+
204
+ #[rubyclass(module = "Wasmer")]
205
+ pub struct GlobalType {
206
+ pub ty: Type,
207
+ pub mutable: bool,
208
+ }
209
+
210
+ #[rubymethods]
211
+ impl GlobalType {
212
+ pub fn new(ty: &Integer, mutable: &Boolean) -> RubyResult<AnyObject> {
213
+ Ok(GlobalType::ruby_new(GlobalType {
214
+ ty: Type::try_from(ty).map_err(to_ruby_err::<TypeError, _>)?,
215
+ mutable: mutable.to_bool(),
216
+ }))
217
+ }
218
+
219
+ pub fn r#type(&self) -> RubyResult<Integer> {
220
+ Ok(self.ty.to_integer())
221
+ }
222
+
223
+ pub fn mutable(&self) -> RubyResult<Boolean> {
224
+ Ok(Boolean::new(self.mutable))
225
+ }
226
+ }
227
+
228
+ impl From<&wasmer::GlobalType> for GlobalType {
229
+ fn from(value: &wasmer::GlobalType) -> Self {
230
+ Self {
231
+ ty: (&value.ty).into(),
232
+ mutable: value.mutability.is_mutable(),
233
+ }
234
+ }
235
+ }
236
+
237
+ #[rubyclass(module = "Wasmer")]
238
+ pub struct TableType {
239
+ pub ty: Type,
240
+ pub minimum: u32,
241
+ pub maximum: Option<u32>,
242
+ }
243
+
244
+ #[rubymethods]
245
+ impl TableType {
246
+ pub fn new(ty: &Integer, minimum: &Integer, maximum: &AnyObject) -> RubyResult<AnyObject> {
247
+ Ok(TableType::ruby_new(TableType {
248
+ ty: Type::try_from(ty).map_err(to_ruby_err::<TypeError, _>)?,
249
+ minimum: minimum.to_u64() as _,
250
+ maximum: if maximum.is_nil() {
251
+ None
252
+ } else {
253
+ Some(maximum.try_convert_to::<Integer>()?.to_u64() as _)
254
+ },
255
+ }))
256
+ }
257
+
258
+ pub fn r#type(&self) -> RubyResult<Integer> {
259
+ Ok(self.ty.to_integer())
260
+ }
261
+
262
+ pub fn minimum(&self) -> RubyResult<Integer> {
263
+ Ok(Integer::new(self.minimum.into()))
264
+ }
265
+
266
+ pub fn maximum(&self) -> RubyResult<AnyObject> {
267
+ Ok(match self.maximum {
268
+ Some(maximum) => Integer::new(maximum.into()).to_any_object(),
269
+ None => NilClass::new().to_any_object(),
270
+ })
271
+ }
272
+ }
273
+
274
+ impl From<&wasmer::TableType> for TableType {
275
+ fn from(value: &wasmer::TableType) -> Self {
276
+ Self {
277
+ ty: (&value.ty).into(),
278
+ minimum: value.minimum,
279
+ maximum: value.maximum,
280
+ }
281
+ }
282
+ }
283
+
284
+ impl Into<wasmer::TableType> for &TableType {
285
+ fn into(self) -> wasmer::TableType {
286
+ wasmer::TableType::new(self.ty.into(), self.minimum, self.maximum)
287
+ }
288
+ }
289
+
290
+ #[rubyclass(module = "Wasmer")]
291
+ pub struct ExportType {
292
+ pub name: String,
293
+ pub ty: AnyObject,
294
+ }
295
+
296
+ #[rubymethods]
297
+ impl ExportType {
298
+ pub fn new(name: &RString, ty: &AnyObject) -> RubyResult<AnyObject> {
299
+ Ok(ExportType::ruby_new(ExportType {
300
+ name: name.to_string(),
301
+ ty: if ty.try_convert_to::<RubyFunctionType>().is_ok()
302
+ || ty.try_convert_to::<RubyMemoryType>().is_ok()
303
+ || ty.try_convert_to::<RubyGlobalType>().is_ok()
304
+ || ty.try_convert_to::<RubyTableType>().is_ok()
305
+ {
306
+ unsafe { ty.to::<AnyObject>() }
307
+ } else {
308
+ return Err(to_ruby_err::<TypeError, _>("Argument #2 of `ExportType.new` must be of kind `FunctionType`, `MemoryType`, `GlobalType` or `TableType`"));
309
+ },
310
+ }))
311
+ }
312
+
313
+ pub fn name(&self) -> RubyResult<RString> {
314
+ Ok(RString::new_utf8(&self.name))
315
+ }
316
+
317
+ pub fn r#type(&self) -> RubyResult<AnyObject> {
318
+ Ok(self.ty.clone())
319
+ }
320
+ }
321
+
322
+ impl TryFrom<wasmer::ExportType> for ExportType {
323
+ type Error = AnyException;
324
+
325
+ fn try_from(value: wasmer::ExportType) -> Result<Self, Self::Error> {
326
+ Ok(ExportType {
327
+ name: value.name().to_string(),
328
+ ty: extern_type_to_ruby_any_object(value.ty()),
329
+ })
330
+ }
331
+ }
332
+
333
+ #[rubyclass(module = "Wasmer")]
334
+ pub struct ImportType {
335
+ pub module: String,
336
+ pub name: String,
337
+ pub ty: AnyObject,
338
+ }
339
+
340
+ #[rubymethods]
341
+ impl ImportType {
342
+ pub fn new(module: &RString, name: &RString, ty: &AnyObject) -> RubyResult<AnyObject> {
343
+ Ok(ImportType::ruby_new(ImportType {
344
+ module: module.to_string(),
345
+ name: name.to_string(),
346
+ ty: if ty.try_convert_to::<RubyFunctionType>().is_ok()
347
+ || ty.try_convert_to::<RubyMemoryType>().is_ok()
348
+ || ty.try_convert_to::<RubyGlobalType>().is_ok()
349
+ || ty.try_convert_to::<RubyTableType>().is_ok()
350
+ {
351
+ unsafe { ty.to::<AnyObject>() }
352
+ } else {
353
+ return Err(to_ruby_err::<TypeError, _>("Argument #3 of `ImportType.new` must be of kind `FunctionType`, `MemoryType`, `GlobalType` or `TableType`"));
354
+ },
355
+ }))
356
+ }
357
+
358
+ pub fn module(&self) -> RubyResult<RString> {
359
+ Ok(RString::new_utf8(&self.module))
360
+ }
361
+
362
+ pub fn name(&self) -> RubyResult<RString> {
363
+ Ok(RString::new_utf8(&self.name))
364
+ }
365
+
366
+ pub fn r#type(&self) -> RubyResult<AnyObject> {
367
+ Ok(self.ty.clone())
368
+ }
369
+ }
370
+
371
+ impl TryFrom<wasmer::ImportType> for ImportType {
372
+ type Error = AnyException;
373
+
374
+ fn try_from(value: wasmer::ImportType) -> Result<Self, Self::Error> {
375
+ Ok(ImportType {
376
+ module: value.module().to_string(),
377
+ name: value.name().to_string(),
378
+ ty: extern_type_to_ruby_any_object(value.ty()),
379
+ })
380
+ }
381
+ }
382
+
383
+ fn extern_type_to_ruby_any_object(value: &wasmer::ExternType) -> AnyObject {
384
+ match value {
385
+ wasmer::ExternType::Function(t) => FunctionType::ruby_new(FunctionType::from(t)),
386
+ wasmer::ExternType::Memory(t) => MemoryType::ruby_new(MemoryType::from(t)),
387
+ wasmer::ExternType::Global(t) => GlobalType::ruby_new(GlobalType::from(t)),
388
+ wasmer::ExternType::Table(t) => TableType::ruby_new(TableType::from(t)),
389
+ }
390
+ }