use mlua::{Function, Lua, Value};
use crate::error::{Error, Result};
use crate::perms::PermsRegistry;
extern "C-unwind" {
fn luaopen_eris(L: *mut mlua_sys::lua_State) -> std::os::raw::c_int;
}
pub struct ErisLua {
lua: Lua,
perms: PermsRegistry,
}
impl ErisLua {
pub fn new() -> Result<Self> {
Self::from_lua(Lua::new())
}
pub unsafe fn unsafe_new() -> Result<Self> {
Self::from_lua(Lua::unsafe_new())
}
pub fn from_lua(lua: Lua) -> Result<Self> {
unsafe {
let opener = lua.create_c_function(luaopen_eris)?;
let eris_table: mlua::Table = opener.call(())?;
lua.globals().set("eris", eris_table)?;
}
let perms = PermsRegistry::with_default_stdlib(&lua)?;
Ok(Self { lua, perms })
}
pub fn lua(&self) -> &Lua {
&self.lua
}
pub fn perms(&self) -> &PermsRegistry {
&self.perms
}
pub fn perms_mut(&mut self) -> &mut PermsRegistry {
&mut self.perms
}
pub fn register_perm(&mut self, key: &str, func: Function) -> Result<()> {
self.perms.register_function(key, func)
}
pub fn persist(&self, value: Value) -> Result<Vec<u8>> {
let eris: mlua::Table = self.lua.globals().get("eris")?;
let persist_fn: Function = eris.get("persist")?;
let perms = self.perms.perms_table()?;
let result: mlua::String = persist_fn
.call((perms, value))
.map_err(|e| Error::PersistFailed(e.to_string()))?;
Ok(result.as_bytes().to_vec())
}
pub fn unpersist(&self, blob: &[u8]) -> Result<Value> {
let eris: mlua::Table = self.lua.globals().get("eris")?;
let unpersist_fn: Function = eris.get("unpersist")?;
let uperms = self.perms.uperms_table()?;
let blob_str = self.lua.create_string(blob)?;
let result: Value = unpersist_fn
.call((uperms, blob_str))
.map_err(|e| Error::UnpersistFailed(e.to_string()))?;
Ok(result)
}
}