use luna_core::runtime::Value;
use luna_core::vm::LuaError;
use luna_jit::Lua;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll, Waker};
fn block_on<F: Future>(mut fut: F) -> F::Output {
let mut fut = unsafe { Pin::new_unchecked(&mut fut) };
let waker = noop_waker();
let mut cx = Context::from_waker(&waker);
loop {
match fut.as_mut().poll(&mut cx) {
Poll::Ready(v) => return v,
Poll::Pending => {} }
}
}
fn noop_waker() -> Waker {
use std::task::{RawWaker, RawWakerVTable};
static VTABLE: RawWakerVTable = RawWakerVTable::new(
|_| RawWaker::new(std::ptr::null(), &VTABLE),
|_| {},
|_| {},
|_| {},
);
let raw = RawWaker::new(std::ptr::null(), &VTABLE);
unsafe { Waker::from_raw(raw) }
}
fn async_double(
vm: *mut luna_core::vm::Vm,
fs: u32,
_nargs: u32,
) -> Pin<Box<dyn Future<Output = Result<u32, LuaError>>>> {
Box::pin(async move {
let vm = unsafe { &mut *vm };
let arg = vm.nat_arg(fs, 1, 0);
let n = match arg {
Value::Int(i) => i,
Value::Float(f) => f as i64,
_ => return Err(LuaError(Value::Nil)),
};
let doubled = n * 2;
Ok(vm.nat_return(fs, &[Value::Int(doubled)]))
})
}
fn main() {
let mut lua = Lua::new();
lua.open_base();
lua.open_math();
lua.open_string();
lua.set_async_native("double_async", async_double).unwrap();
let result: i64 = block_on(lua.eval_async(
r#"
local sum = 0
for i = 1, 10 do
sum = sum + double_async(i)
end
return sum
"#,
))
.unwrap();
assert_eq!(result, 110);
println!("async_host: sum = {result}");
println!("ok");
}