1use core::ffi::{CStr, c_int};
2use core::fmt::Display;
3
4use crate::ffi::{self, State};
5
6pub unsafe fn grow_stack(lstate: *mut State, n: c_int) {
9 unsafe {
10 if ffi::lua_gettop(lstate) < n {
11 ffi::lua_settop(lstate, n);
12 }
13 }
14}
15
16pub unsafe fn debug_value(lstate: *mut State, n: c_int) -> Box<dyn Display> {
19 match ffi::lua_type(lstate, n) {
20 ffi::LUA_TNONE | ffi::LUA_TNIL => Box::new("()"),
21
22 ffi::LUA_TBOOLEAN => Box::new(ffi::lua_toboolean(lstate, n) == 1),
23
24 ffi::LUA_TSTRING => Box::new(
25 CStr::from_ptr(ffi::lua_tostring(lstate, n)).to_string_lossy(),
26 ),
27
28 ffi::LUA_TNUMBER => Box::new(ffi::lua_tonumber(lstate, n)),
29
30 _ => Box::new("other"),
31 }
32}
33
34pub unsafe fn is_table_array(lstate: *mut State, index: c_int) -> bool {
37 ffi::lua_pushnil(lstate);
38
39 if ffi::lua_next(lstate, index - 1) == 0 {
40 if ffi::lua_getmetatable(lstate, index) == 0 {
42 return true;
43 }
44 ffi::lua_pop(lstate, 1);
45 return false;
46 }
47
48 let ty = ffi::lua_type(lstate, -2);
49 ffi::lua_pop(lstate, 2);
50 ty == ffi::LUA_TNUMBER
51}
52
53pub unsafe fn debug_type(lstate: *mut State, n: c_int) -> impl Display {
55 CStr::from_ptr(ffi::luaL_typename(lstate, n)).to_string_lossy()
56}
57
58pub unsafe fn debug_stack(lstate: *mut State) {
60 let height = ffi::lua_gettop(lstate);
61
62 let stack_pp = (1..height + 1)
63 .map(|n| {
64 let idx = height + 1 - n;
65 let value = debug_value(lstate, -n);
66 let typename = debug_type(lstate, -n);
67 format!("{idx}: {value} ({typename})")
68 })
69 .collect::<Vec<String>>()
70 .join("\n");
71
72 crate::print!("{stack_pp}");
73}
74
75pub unsafe fn push_error<E: core::fmt::Display + ?Sized>(
76 err: &E,
77 lstate: *mut State,
78) -> ! {
79 let msg = err.to_string();
80 ffi::lua_pushlstring(lstate, msg.as_ptr() as *const _, msg.len());
81 drop(msg);
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}