pub mod error;
pub mod messages;
use crate::{
actors::{queue::Queue, scanmgr::ScanMgr, user_engine::UserEngine},
userscript_api::{about_api::AboutApi, help_system::HelpSystem},
};
use kameo::{actor::ActorRef, error::BoxError, mailbox::unbounded::UnboundedMailbox, Actor};
use messages::RegisterUserApi;
use mlua::{prelude::*, AppDataRefMut};
pub struct LuaVM {
vm: Lua,
queue: Option<ActorRef<Queue>>,
user_engine: Option<ActorRef<UserEngine>>,
scanmgr: Option<ActorRef<ScanMgr>>,
}
impl Actor for LuaVM {
type Mailbox = UnboundedMailbox<Self>;
async fn on_start(&mut self, lua_vm: ActorRef<Self>) -> Result<(), BoxError> {
let queue: ActorRef<Queue> = Queue::spawn_with_size(lua_vm.downgrade(), 16384);
let user_engine: ActorRef<UserEngine> =
UserEngine::spawn_with_capacity(lua_vm.downgrade(), 128);
let scanmgr: ActorRef<ScanMgr> = ScanMgr::spawn(
lua_vm.downgrade(),
queue.downgrade(),
user_engine.downgrade(),
);
lua_vm
.tell(RegisterUserApi::with(HelpSystem::default()))
.await?;
lua_vm
.tell(RegisterUserApi::with(AboutApi::default()))
.await?;
lua_vm.link(&queue).await;
lua_vm.link(&user_engine).await;
lua_vm.link(&scanmgr).await;
self.queue = Some(queue);
self.user_engine = Some(user_engine);
self.scanmgr = Some(scanmgr);
let warning_buffer: String = String::with_capacity(4096);
self.vm.set_app_data(warning_buffer);
self.vm
.set_warning_function(|lua: &Lua, msg: &str, incomplete: bool| {
let mut warning_buffer: AppDataRefMut<String> =
lua.app_data_mut().expect("warning buffer should exist");
if incomplete {
warning_buffer.push_str(msg);
} else {
eprintln!("[WARN] {warning_buffer}{msg}");
warning_buffer.clear();
}
Ok(())
});
Ok(())
}
}
impl LuaVM {
#[must_use]
pub fn spawn() -> ActorRef<Self> {
let lua_vm: Self = Self {
vm: Lua::new(),
queue: None,
user_engine: None,
scanmgr: None,
};
kameo::spawn(lua_vm)
}
#[must_use]
pub unsafe fn spawn_unsafe() -> ActorRef<Self> {
let lua_vm: Self = Self {
vm: Lua::unsafe_new(),
queue: None,
user_engine: None,
scanmgr: None,
};
kameo::spawn(lua_vm)
}
}