1use std::ffi::{c_int, CStr};
2use std::fmt::Display;
3
4use crate::ffi::{self, lua_State};
5
6pub unsafe fn grow_stack(lstate: *mut lua_State, n: c_int) {
9 if ffi::lua_gettop(lstate) < n {
10 ffi::lua_settop(lstate, n);
11 }
12}
13
14pub unsafe fn debug_value(
17 lstate: *mut lua_State,
18 n: c_int,
19) -> Box<dyn Display> {
20 match ffi::lua_type(lstate, n) {
21 ffi::LUA_TNONE | ffi::LUA_TNIL => Box::new("()"),
22
23 ffi::LUA_TBOOLEAN => Box::new(ffi::lua_toboolean(lstate, n) == 1),
24
25 ffi::LUA_TSTRING => Box::new(
26 CStr::from_ptr(ffi::lua_tostring(lstate, n)).to_string_lossy(),
27 ),
28
29 ffi::LUA_TNUMBER => Box::new(ffi::lua_tonumber(lstate, n)),
30
31 _ => Box::new("other"),
32 }
33}
34
35pub unsafe fn is_table_array(lstate: *mut lua_State, index: c_int) -> bool {
38 ffi::lua_pushnil(lstate);
39
40 if ffi::lua_next(lstate, index - 1) == 0 {
41 if ffi::lua_getmetatable(lstate, index) == 0 {
43 return true;
44 }
45 ffi::lua_pop(lstate, 1);
46 return false;
47 }
48
49 let ty = ffi::lua_type(lstate, -2);
50 ffi::lua_pop(lstate, 2);
51 ty == ffi::LUA_TNUMBER
52}
53
54pub unsafe fn debug_type(lstate: *mut lua_State, n: c_int) -> impl Display {
56 CStr::from_ptr(ffi::luaL_typename(lstate, n)).to_string_lossy()
57}
58
59pub unsafe fn debug_stack(lstate: *mut lua_State) {
61 let height = ffi::lua_gettop(lstate);
62
63 let stack_pp = (1..height + 1)
64 .map(|n| {
65 let idx = height + 1 - n;
66 let value = debug_value(lstate, -n);
67 let typename = debug_type(lstate, -n);
68 format!("{idx}: {value} ({typename})")
69 })
70 .collect::<Vec<String>>()
71 .join("\n");
72
73 crate::print!("{stack_pp}");
74}
75
76pub unsafe fn handle_error<E: std::error::Error + ?Sized>(
77 lstate: *mut lua_State,
78 err: &E,
79) -> ! {
80 let msg = err.to_string();
81 ffi::lua_pushlstring(lstate, msg.as_ptr() as *const _, msg.len());
82 ffi::lua_error(lstate);
83}
84
85pub fn type_name(ty: c_int) -> &'static str {
86 match ty {
87 ffi::LUA_TNONE => "empty stack",
88 ffi::LUA_TNIL => "nil",
89 ffi::LUA_TBOOLEAN => "boolean",
90 ffi::LUA_TLIGHTUSERDATA => "light userdata",
91 ffi::LUA_TNUMBER => "number",
92 ffi::LUA_TSTRING => "string",
93 ffi::LUA_TTABLE => "table",
94 ffi::LUA_TFUNCTION => "function",
95 ffi::LUA_TUSERDATA => "userdata",
96 ffi::LUA_TTHREAD => "thread",
97 _ => unreachable!(),
98 }
99}