@@ -14,6 +14,16 @@ fn reverse_string(a: String) -> String {
1414 return a. chars ( ) . rev ( ) . collect ( ) ;
1515}
1616
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+
1727#[ rustler:: nif]
1828fn wasm_example_0 ( source : String , f : String ) -> Result < i32 , Error > {
1929 // return Ok(5);
@@ -281,9 +291,68 @@ fn wasm_example_2_i32_string_internal(wat_source: String, f: String, a: i32, b:
281291 return Ok ( string) ;
282292}
283293
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+
284352rustler:: init!( "Elixir.ComponentsGuide.Rustler.Math" , [
285353 add,
286354 reverse_string,
355+ wasm_example_n_i32,
287356 wasm_example_0,
288357 wasm_example_1_i32,
289358 wasm_example_2_i32,
0 commit comments