use std::ffi::CStr;
use crate::state::Lua;
use crate::sys::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DebugWhat {
Lua,
Main,
C,
Unknown,
}
#[derive(Debug, Clone)]
pub struct Debug {
name: Option<String>,
what: DebugWhat,
source: Option<String>,
short_src: Option<String>,
current_line: Option<i64>,
line_defined: Option<i64>,
}
impl Debug {
pub fn name(&self) -> Option<&str> {
self.name.as_deref()
}
pub fn what(&self) -> DebugWhat {
self.what
}
pub fn source(&self) -> Option<&str> {
self.source.as_deref()
}
pub fn short_src(&self) -> Option<&str> {
self.short_src.as_deref()
}
pub fn current_line(&self) -> Option<i64> {
self.current_line
}
pub fn line_defined(&self) -> Option<i64> {
self.line_defined
}
}
impl Lua {
pub fn inspect_stack(&self, level: usize) -> Option<Debug> {
let state = self.state();
unsafe {
let mut ar: LuaDebug = core::mem::zeroed();
let opt = c"nsl";
let ok = lua_getinfo(
state,
level as c_int,
opt.as_ptr() as *const c_char,
&mut ar,
);
if ok == 0 {
return None;
}
let cstr = |p: *const c_char| -> Option<String> {
if p.is_null() {
None
} else {
Some(CStr::from_ptr(p).to_string_lossy().into_owned())
}
};
let what_str = cstr(ar.what).unwrap_or_default();
let what = match what_str.as_str() {
"Lua" => DebugWhat::Lua,
"main" => DebugWhat::Main,
"C" => DebugWhat::C,
_ => DebugWhat::Unknown,
};
let current_line = if ar.currentline >= 0 {
Some(ar.currentline as i64)
} else {
None
};
let line_defined = if ar.linedefined > 0 {
Some(ar.linedefined as i64)
} else {
None
};
Some(Debug {
name: cstr(ar.name),
what,
source: cstr(ar.source),
short_src: cstr(ar.short_src),
current_line,
line_defined,
})
}
}
}