sophiajt / truffle

Fast embeddable scripting for Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Async Support Experiment: circumvent then redesign registration API

yaahc opened this issue · comments

TODO: explain the reasoning behind this direction

// execute an async function
//  define one
//      make the first param a mutable reference
//      box<&dyn Any> that gets downcast
//  engine will likely need to wrap it into an enum so it can handle other kinds of functions
// invoke it from a script equivalent
//   store it, then retrieve and call it

use futures::future::{BoxFuture, FutureExt};
use std::any::Any;

fn main() {
    let mut engine = Engine { fns: vec![] };
    let f = Function::AsyncFn { f: wrapped_fn };
    engine.fns.push(f);

    let s = String::new();
    let mut s: Box<dyn Any + Send + Sync> = Box::new(s);
    {
        let s = &mut s;

        match engine.fns.get(0).unwrap() {
            Function::AsyncFn { f } => futures::executor::block_on(f(s)),
        }
    }
    let s = *s.downcast::<String>().unwrap();
    dbg!(s);
}

async fn modify_this(this: &mut String) {
    this.push_str("I got evaluated in the async context!")
}

fn wrapped_fn(mut this: &mut Box<dyn Any + Send + Sync>) -> BoxFuture<'_, ()> {
    async move {
        let this = this.downcast_mut().unwrap();
        modify_this(this).await
    }
    .boxed()
}

struct Engine {
    fns: Vec<Function>,
}

type WrappedFn1 = fn(&mut Box<dyn Any + Send + Sync>) -> BoxFuture<'_, ()>;

enum Function {
    AsyncFn { f: WrappedFn1 },
}