worldwideportal/src/lua_state.rs

69 lines
2.3 KiB
Rust

use anyhow::Error;
use piccolo::{Callback, Closure, Context, Executor, IntoValue, Lua, StashedExecutor, Table};
use crate::{echo_to_term_frame, GlobalCell, TermFrame};
use std::str;
pub struct LuaState {
pub interp: Lua,
pub exec: StashedExecutor,
}
impl LuaState {
pub fn setup() -> Result<LuaState, String> {
let mut interp = Lua::core();
let exec: StashedExecutor =
interp.enter(|ctx| Ok::<StashedExecutor, String>(ctx.stash(Executor::new(ctx))))?;
Ok(LuaState { interp, exec })
}
pub fn execute(&mut self, command: &str) -> Result<String, String> {
self.interp
.try_enter(|ctx| {
let closure = Closure::load(ctx, None, format!("return ({})", command).as_bytes())
.or_else(|_| Closure::load(ctx, None, command.as_bytes()))?;
ctx.fetch(&self.exec).restart(ctx, closure.into(), ());
Ok(())
})
.map_err(|err| format!("{}", err))?;
Ok("Blah".to_owned())
}
}
pub fn install_lua_globals(global: &GlobalCell) -> Result<(), String> {
global
.lua_engine
.borrow_mut()
.interp
.try_enter(|ctx| {
let cmd_table = Table::new(&ctx);
cmd_table
.set(
ctx,
ctx.intern_static(b"echo_frame"),
echo_frame(ctx, global.clone()),
)
.map_err(|_| Error::msg("Can't add command"))?;
ctx.set_global(ctx.intern_static(b"commands").into_value(ctx), cmd_table)
.map(|_| ())
.map_err(|_| Error::msg("Can't set commands key"))?;
Ok(())
})
.map_err(|e| e.to_string())?;
Ok(())
}
fn echo_frame(ctx: Context, global: GlobalCell) -> Callback {
Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
let frame_no: u64 = stack.consume(ctx)?;
let message: piccolo::String = stack.consume(ctx)?;
let message_str = str::from_utf8(message.as_bytes())
.map_err(|_| "Expected message to echo to be UTF-8.".into_value(ctx))?;
echo_to_term_frame(&global, &TermFrame(frame_no), message_str)
.map_err(|m| m.into_value(ctx))?;
Ok(piccolo::CallbackReturn::Return)
})
}