flow_impl_derive/
lib.rs

1#![deny(missing_docs)]
2//! `flow_impl_derive` is a derive macro that inserts code to allow a flow "implementation"
3//! to be called when compiled to wasm32
4extern crate proc_macro;
5
6use quote::quote;
7
8use crate::proc_macro::TokenStream;
9
10#[proc_macro_derive(FlowImpl)]
11/// Implement the `FlowImpl` derive macro
12pub fn flow_impl_derive(input: TokenStream) -> TokenStream {
13    // Construct a representation of Rust code as a syntax tree that we can manipulate
14    let ast = syn::parse(input).unwrap();
15
16    // Build the trait implementation
17    impl_flow_impl(&ast)
18}
19
20fn impl_flow_impl(ast: &syn::DeriveInput) -> TokenStream {
21    let name = &ast.ident;
22    let gen = quote! {
23        use std::os::raw::c_void;
24
25        // Allocate a chunk of memory of `size` bytes in wasm module
26        #[cfg(target_arch = "wasm32")]
27        #[no_mangle]
28        pub extern "C" fn alloc(size: usize) -> *mut c_void {
29            use std::mem;
30            let mut buf = Vec::with_capacity(size);
31            let ptr = buf.as_mut_ptr();
32            mem::forget(buf);
33            return ptr as *mut c_void;
34        }
35
36        // Wrapper function for running a wasm implementation
37        #[cfg(target_arch = "wasm32")]
38        #[no_mangle]
39        pub extern "C" fn run_wasm(input_data_ptr: *mut c_void, input_data_length: i32) -> i32 {
40            use std::ptr::copy;
41            let input_data: Vec<u8> = unsafe {
42                Vec::from_raw_parts(input_data_ptr as *mut u8,
43                                      input_data_length as usize, input_data_length as usize)
44            };
45
46            let inputs: Vec<Value> = serde_json::from_slice(&input_data).unwrap();
47            let object = #name {};
48            let result = object.run(&inputs);
49
50            let return_data = serde_json::to_vec(&result).unwrap();
51
52            unsafe { copy(return_data.as_ptr(), input_data_ptr as *mut u8, return_data.len()); }
53
54            return_data.len() as i32
55        }
56    };
57    gen.into()
58}