use std::ffi::{c_int, CStr};
use std::fmt::Display;
use crate::ffi::{self, lua_State};
pub unsafe fn grow_stack(lstate: *mut lua_State, n: c_int) {
if ffi::lua_gettop(lstate) < n {
ffi::lua_settop(lstate, n);
}
}
pub unsafe fn debug_value(
lstate: *mut lua_State,
n: c_int,
) -> Box<dyn Display> {
match ffi::lua_type(lstate, n) {
ffi::LUA_TNONE | ffi::LUA_TNIL => Box::new("()"),
ffi::LUA_TBOOLEAN => Box::new(ffi::lua_toboolean(lstate, n) == 1),
ffi::LUA_TSTRING => Box::new(
CStr::from_ptr(ffi::lua_tostring(lstate, n)).to_string_lossy(),
),
ffi::LUA_TNUMBER => Box::new(ffi::lua_tonumber(lstate, n)),
_ => Box::new("other"),
}
}
pub unsafe fn is_table_array(lstate: *mut lua_State, index: c_int) -> bool {
ffi::lua_pushnil(lstate);
if ffi::lua_next(lstate, index - 1) == 0 {
if ffi::lua_getmetatable(lstate, index) == 0 {
return true;
}
ffi::lua_pop(lstate, 1);
return false;
}
let ty = ffi::lua_type(lstate, -2);
ffi::lua_pop(lstate, 2);
ty == ffi::LUA_TNUMBER
}
pub unsafe fn debug_type(lstate: *mut lua_State, n: c_int) -> impl Display {
CStr::from_ptr(ffi::luaL_typename(lstate, n)).to_string_lossy()
}
pub unsafe fn debug_stack(lstate: *mut lua_State) {
let height = ffi::lua_gettop(lstate);
let stack_pp = (1..height + 1)
.map(|n| {
let idx = height + 1 - n;
let value = debug_value(lstate, -n);
let typename = debug_type(lstate, -n);
format!("{idx}: {value} ({typename})")
})
.collect::<Vec<String>>()
.join("\n");
crate::print!("{stack_pp}");
}
pub unsafe fn handle_error<E: std::error::Error + ?Sized>(
lstate: *mut lua_State,
err: &E,
) -> ! {
let msg = err.to_string();
ffi::lua_pushlstring(lstate, msg.as_ptr() as *const _, msg.len());
ffi::lua_error(lstate);
}
pub fn type_name(ty: c_int) -> &'static str {
match ty {
ffi::LUA_TNONE => "empty stack",
ffi::LUA_TNIL => "nil",
ffi::LUA_TBOOLEAN => "boolean",
ffi::LUA_TLIGHTUSERDATA => "light userdata",
ffi::LUA_TNUMBER => "number",
ffi::LUA_TSTRING => "string",
ffi::LUA_TTABLE => "table",
ffi::LUA_TFUNCTION => "function",
ffi::LUA_TUSERDATA => "userdata",
ffi::LUA_TTHREAD => "thread",
_ => unreachable!(),
}
}