wasmer 0.1.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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 @@
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,396 @@
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::from(&value)
191
+ }
192
+ }
193
+
194
+ impl From<&wasmer::MemoryType> for MemoryType {
195
+ fn from(value: &wasmer::MemoryType) -> Self {
196
+ Self {
197
+ minimum: value.minimum.0,
198
+ maximum: value.maximum.map(|pages| pages.0),
199
+ shared: value.shared,
200
+ }
201
+ }
202
+ }
203
+
204
+ impl Into<wasmer::MemoryType> for &MemoryType {
205
+ fn into(self) -> wasmer::MemoryType {
206
+ wasmer::MemoryType::new(self.minimum, self.maximum, self.shared)
207
+ }
208
+ }
209
+
210
+ #[rubyclass(module = "Wasmer")]
211
+ pub struct GlobalType {
212
+ pub ty: Type,
213
+ pub mutable: bool,
214
+ }
215
+
216
+ #[rubymethods]
217
+ impl GlobalType {
218
+ pub fn new(ty: &Integer, mutable: &Boolean) -> RubyResult<AnyObject> {
219
+ Ok(GlobalType::ruby_new(GlobalType {
220
+ ty: Type::try_from(ty).map_err(to_ruby_err::<TypeError, _>)?,
221
+ mutable: mutable.to_bool(),
222
+ }))
223
+ }
224
+
225
+ pub fn r#type(&self) -> RubyResult<Integer> {
226
+ Ok(self.ty.to_integer())
227
+ }
228
+
229
+ pub fn mutable(&self) -> RubyResult<Boolean> {
230
+ Ok(Boolean::new(self.mutable))
231
+ }
232
+ }
233
+
234
+ impl From<&wasmer::GlobalType> for GlobalType {
235
+ fn from(value: &wasmer::GlobalType) -> Self {
236
+ Self {
237
+ ty: (&value.ty).into(),
238
+ mutable: value.mutability.is_mutable(),
239
+ }
240
+ }
241
+ }
242
+
243
+ #[rubyclass(module = "Wasmer")]
244
+ pub struct TableType {
245
+ pub ty: Type,
246
+ pub minimum: u32,
247
+ pub maximum: Option<u32>,
248
+ }
249
+
250
+ #[rubymethods]
251
+ impl TableType {
252
+ pub fn new(ty: &Integer, minimum: &Integer, maximum: &AnyObject) -> RubyResult<AnyObject> {
253
+ Ok(TableType::ruby_new(TableType {
254
+ ty: Type::try_from(ty).map_err(to_ruby_err::<TypeError, _>)?,
255
+ minimum: minimum.to_u64() as _,
256
+ maximum: if maximum.is_nil() {
257
+ None
258
+ } else {
259
+ Some(maximum.try_convert_to::<Integer>()?.to_u64() as _)
260
+ },
261
+ }))
262
+ }
263
+
264
+ pub fn r#type(&self) -> RubyResult<Integer> {
265
+ Ok(self.ty.to_integer())
266
+ }
267
+
268
+ pub fn minimum(&self) -> RubyResult<Integer> {
269
+ Ok(Integer::new(self.minimum.into()))
270
+ }
271
+
272
+ pub fn maximum(&self) -> RubyResult<AnyObject> {
273
+ Ok(match self.maximum {
274
+ Some(maximum) => Integer::new(maximum.into()).to_any_object(),
275
+ None => NilClass::new().to_any_object(),
276
+ })
277
+ }
278
+ }
279
+
280
+ impl From<&wasmer::TableType> for TableType {
281
+ fn from(value: &wasmer::TableType) -> Self {
282
+ Self {
283
+ ty: (&value.ty).into(),
284
+ minimum: value.minimum,
285
+ maximum: value.maximum,
286
+ }
287
+ }
288
+ }
289
+
290
+ impl Into<wasmer::TableType> for &TableType {
291
+ fn into(self) -> wasmer::TableType {
292
+ wasmer::TableType::new(self.ty.into(), self.minimum, self.maximum)
293
+ }
294
+ }
295
+
296
+ #[rubyclass(module = "Wasmer")]
297
+ pub struct ExportType {
298
+ pub name: String,
299
+ pub ty: AnyObject,
300
+ }
301
+
302
+ #[rubymethods]
303
+ impl ExportType {
304
+ pub fn new(name: &RString, ty: &AnyObject) -> RubyResult<AnyObject> {
305
+ Ok(ExportType::ruby_new(ExportType {
306
+ name: name.to_string(),
307
+ ty: if ty.try_convert_to::<RubyFunctionType>().is_ok()
308
+ || ty.try_convert_to::<RubyMemoryType>().is_ok()
309
+ || ty.try_convert_to::<RubyGlobalType>().is_ok()
310
+ || ty.try_convert_to::<RubyTableType>().is_ok()
311
+ {
312
+ unsafe { ty.to::<AnyObject>() }
313
+ } else {
314
+ return Err(to_ruby_err::<TypeError, _>("Argument #2 of `ExportType.new` must be of kind `FunctionType`, `MemoryType`, `GlobalType` or `TableType`"));
315
+ },
316
+ }))
317
+ }
318
+
319
+ pub fn name(&self) -> RubyResult<RString> {
320
+ Ok(RString::new_utf8(&self.name))
321
+ }
322
+
323
+ pub fn r#type(&self) -> RubyResult<AnyObject> {
324
+ Ok(self.ty.clone())
325
+ }
326
+ }
327
+
328
+ impl TryFrom<wasmer::ExportType> for ExportType {
329
+ type Error = AnyException;
330
+
331
+ fn try_from(value: wasmer::ExportType) -> Result<Self, Self::Error> {
332
+ Ok(ExportType {
333
+ name: value.name().to_string(),
334
+ ty: extern_type_to_ruby_any_object(value.ty()),
335
+ })
336
+ }
337
+ }
338
+
339
+ #[rubyclass(module = "Wasmer")]
340
+ pub struct ImportType {
341
+ pub module: String,
342
+ pub name: String,
343
+ pub ty: AnyObject,
344
+ }
345
+
346
+ #[rubymethods]
347
+ impl ImportType {
348
+ pub fn new(module: &RString, name: &RString, ty: &AnyObject) -> RubyResult<AnyObject> {
349
+ Ok(ImportType::ruby_new(ImportType {
350
+ module: module.to_string(),
351
+ name: name.to_string(),
352
+ ty: if ty.try_convert_to::<RubyFunctionType>().is_ok()
353
+ || ty.try_convert_to::<RubyMemoryType>().is_ok()
354
+ || ty.try_convert_to::<RubyGlobalType>().is_ok()
355
+ || ty.try_convert_to::<RubyTableType>().is_ok()
356
+ {
357
+ unsafe { ty.to::<AnyObject>() }
358
+ } else {
359
+ return Err(to_ruby_err::<TypeError, _>("Argument #3 of `ImportType.new` must be of kind `FunctionType`, `MemoryType`, `GlobalType` or `TableType`"));
360
+ },
361
+ }))
362
+ }
363
+
364
+ pub fn module(&self) -> RubyResult<RString> {
365
+ Ok(RString::new_utf8(&self.module))
366
+ }
367
+
368
+ pub fn name(&self) -> RubyResult<RString> {
369
+ Ok(RString::new_utf8(&self.name))
370
+ }
371
+
372
+ pub fn r#type(&self) -> RubyResult<AnyObject> {
373
+ Ok(self.ty.clone())
374
+ }
375
+ }
376
+
377
+ impl TryFrom<wasmer::ImportType> for ImportType {
378
+ type Error = AnyException;
379
+
380
+ fn try_from(value: wasmer::ImportType) -> Result<Self, Self::Error> {
381
+ Ok(ImportType {
382
+ module: value.module().to_string(),
383
+ name: value.name().to_string(),
384
+ ty: extern_type_to_ruby_any_object(value.ty()),
385
+ })
386
+ }
387
+ }
388
+
389
+ fn extern_type_to_ruby_any_object(value: &wasmer::ExternType) -> AnyObject {
390
+ match value {
391
+ wasmer::ExternType::Function(t) => FunctionType::ruby_new(FunctionType::from(t)),
392
+ wasmer::ExternType::Memory(t) => MemoryType::ruby_new(MemoryType::from(t)),
393
+ wasmer::ExternType::Global(t) => GlobalType::ruby_new(GlobalType::from(t)),
394
+ wasmer::ExternType::Table(t) => TableType::ruby_new(TableType::from(t)),
395
+ }
396
+ }