tchoutchou/src/internal/core/runtime.rs
2023-03-23 18:10:59 +01:00

76 lines
2.0 KiB
Rust

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<Lua>,
pub routers: Routers,
}
impl Runtime {
pub async fn from_script(lua_script: &Vec<u8>) -> Result<Self, &str> {
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::<HashMap<u16, (String, Vec<(Method, String, String)>)>>()
.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;
}
}