use crate::{chan::lb_chanlib, fs::lb_fslib, net::lb_netlib, task::lb_tasklib}; use derive_more::{Deref, DerefMut}; use luaffi::{Registry, Type}; use luajit::{Chunk, State}; use std::fmt::Display; use tokio::{ task::{JoinHandle, LocalSet, futures::TaskLocalFuture, spawn_local}, task_local, }; #[derive(Debug, Default)] pub struct Builder { registry: Registry, } impl Builder { pub fn new() -> Self { let mut registry = Registry::new(); registry .preload::("lb:task") .preload::("lb:channel") .preload::("lb:fs") .preload::("lb:net"); Self { registry } } pub fn module(&mut self, name: impl Display) -> &mut Self { self.registry.preload::(name); self } pub fn registry(&self) -> &Registry { &self.registry } pub fn build(&self) -> luajit::Result { Ok(Runtime { state: { let mut s = State::new()?; let mut chunk = Chunk::new(self.registry.done()); chunk.extend(include_bytes!("./runtime.lua")); // println!("{chunk}"); s.eval(chunk.path("[luby]"), 0, 0)?; s }, tasks: LocalSet::new(), }) } } #[derive(Debug, Deref, DerefMut)] pub struct Runtime { #[deref] #[deref_mut] state: State, tasks: LocalSet, } task_local! { static STATE: State; } impl Runtime { pub fn spawn( &self, f: impl AsyncFnOnce(&mut State) -> T + 'static, ) -> JoinHandle { self.tasks .spawn_local(async move { f(&mut STATE.with(|s| s.new_thread())).await }) } } pub fn spawn(f: impl AsyncFnOnce(&mut State) -> T + 'static) -> JoinHandle { spawn_local(async move { f(&mut STATE.with(|s| s.new_thread())).await }) } impl IntoFuture for Runtime { type Output = (); type IntoFuture = TaskLocalFuture; fn into_future(self) -> Self::IntoFuture { STATE.scope(self.state, self.tasks) } }