@@ -14,6 +14,16 @@ fn reverse_string(a: String) -> String {
14
14
return a. chars ( ) . rev ( ) . collect ( ) ;
15
15
}
16
16
17
+ #[ rustler:: nif]
18
+ fn wasm_example_n_i32 ( source : String , f : String , args : Vec < i32 > ) -> Result < Vec < i32 > , Error > {
19
+ // return Ok(5);
20
+ //return Err(Error::Term(Box::new("hello")));
21
+ return match wasm_example_n_i32_internal ( source, false , f, args) {
22
+ Ok ( v) => Ok ( v) ,
23
+ Err ( e) => Err ( Error :: Term ( Box :: new ( e. to_string ( ) ) ) )
24
+ }
25
+ }
26
+
17
27
#[ rustler:: nif]
18
28
fn wasm_example_0 ( source : String , f : String ) -> Result < i32 , Error > {
19
29
// return Ok(5);
@@ -281,9 +291,68 @@ fn wasm_example_2_i32_string_internal(wat_source: String, f: String, a: i32, b:
281
291
return Ok ( string) ;
282
292
}
283
293
294
+ fn wasm_example_n_i32_internal ( wat_source : String , buffer : bool , f : String , args : Vec < i32 > ) -> Result < Vec < i32 > , anyhow:: Error > {
295
+ let engine = Engine :: default ( ) ;
296
+
297
+ // A `Store` is what will own instances, functions, globals, etc. All wasm
298
+ // items are stored within a `Store`, and it's what we'll always be using to
299
+ // interact with the wasm world. Custom data can be stored in stores but for
300
+ // now we just use `()`.
301
+ let mut store = Store :: new ( & engine, ( ) ) ;
302
+ let mut linker = Linker :: new ( & engine) ;
303
+
304
+ if buffer {
305
+ let memory_ty = MemoryType :: new ( 1 , None ) ;
306
+ let memory = Memory :: new ( & mut store, memory_ty) ?;
307
+ linker. define ( & store, "env" , "buffer" , memory) ?;
308
+ }
309
+
310
+ // We start off by creating a `Module` which represents a compiled form
311
+ // of our input wasm module. In this case it'll be JIT-compiled after
312
+ // we parse the text format.
313
+ let module = Module :: new ( & engine, wat_source) ?;
314
+
315
+ // With a compiled `Module` we can then instantiate it, creating
316
+ // an `Instance` which we can actually poke at functions on.
317
+ // let instance = Instance::new(&mut store, &module, &[])?;
318
+ let instance = linker. instantiate ( & mut store, & module) ?;
319
+
320
+ // The `Instance` gives us access to various exported functions and items,
321
+ // which we access here to pull out our `answer` exported function and
322
+ // run it.
323
+ let answer = instance
324
+ . get_func ( & mut store, & f)
325
+ . expect ( & format ! ( "{} was not an exported function" , f) ) ;
326
+
327
+ let func_type = answer. ty ( & store) ;
328
+ // There's a few ways we can call the `answer` `Func` value. The easiest
329
+ // is to statically assert its signature with `typed` (in this case
330
+ // asserting it takes no arguments and returns one i32) and then call it.
331
+ // let answer = answer.typed::<(i32, i32), i32>(&store)?;
332
+
333
+ // let args = vec![a, b];
334
+ // let args: &[Val] = &[Val::I32(a), Val::I32(b)];
335
+ // let args: &[Val] = args.iter().map(|i| Val::I32(i)).collect();
336
+ let args: Vec < Val > = args. into_iter ( ) . map ( |i| Val :: I32 ( i) ) . collect ( ) ;
337
+
338
+ let mut result: Vec < Val > = Vec :: with_capacity ( 16 ) ;
339
+ // result.resize(2, Val::I32(0));
340
+ let result_length = func_type. results ( ) . len ( ) ;
341
+ result. resize ( result_length, Val :: I32 ( 0 ) ) ;
342
+
343
+ // And finally we can call our function! Note that the error propagation
344
+ // with `?` is done to handle the case where the wasm function traps.
345
+ answer. call ( & mut store, & args, & mut result) ?;
346
+
347
+ let result: Vec < _ > = result. iter ( ) . map ( |v| v. unwrap_i32 ( ) ) . collect ( ) ;
348
+
349
+ return Ok ( result) ;
350
+ }
351
+
284
352
rustler:: init!( "Elixir.ComponentsGuide.Rustler.Math" , [
285
353
add,
286
354
reverse_string,
355
+ wasm_example_n_i32,
287
356
wasm_example_0,
288
357
wasm_example_1_i32,
289
358
wasm_example_2_i32,
0 commit comments