use std::{collections::HashMap, net::SocketAddr, rc::Rc}; use futures::future::join_all; use hyper::{Method, Server}; use mlua::Lua; use tokio::task::LocalSet; use crate::internal::{ core::service::{LocalExec, MakeSvc}, lua::app::App, }; use super::routers::Routers; pub struct Runtime { pub lua: Rc, pub routers: Routers, } impl Runtime { pub async fn from_script(lua_script: &Vec) -> Result { let lua = Rc::new(Lua::new()); lua.globals().set("internal_app_counter", 0).unwrap(); let app_constructor = lua.create_function(|l, ()| { let app_counter: u16 = l.globals().get("internal_app_counter")?; l.globals().set("internal_app_counter", app_counter + 1)?; Ok(App { id: app_counter + 1, handlers: Vec::new(), }) }); lua.globals() .set("create_app", app_constructor.unwrap()) .unwrap(); lua.load(std::str::from_utf8(lua_script).unwrap()) .eval::<()>() .unwrap(); let apps = lua .to_owned() .app_data_ref::)>>() .unwrap() .to_owned(); Ok(Self { lua: lua.to_owned(), routers: Routers::from(apps, &lua).await, }) } pub fn load(&self, f: &dyn Fn(&Lua) -> ()) { f(&self.lua); } pub async fn start(&self) { let mut servers = Vec::new(); for (port, router) in self.routers.to_owned() { println!("Server listening at http://localhost:{}", port); let addr = SocketAddr::from(([127, 0, 0, 1], port)); let server = Server::bind(&addr) .executor(LocalExec) .serve(MakeSvc(self.lua.to_owned(), router)); servers.push(server); } // Create `LocalSet` to spawn !Send futures let local = LocalSet::new(); local.run_until(join_all(servers)).await; } }