Include (known) userdata type to Value debug pretty-print
This commit is contained in:
parent
3d7796de55
commit
b674d7906d
|
@ -19,6 +19,7 @@ use {
|
|||
use crate::error::{Error, Result};
|
||||
use crate::function::Function;
|
||||
use crate::lua::Lua;
|
||||
use crate::string::String;
|
||||
use crate::table::{Table, TablePairs};
|
||||
use crate::types::{Callback, LuaRef, MaybeSend};
|
||||
use crate::util::{check_stack, get_userdata, take_userdata, StackGuard};
|
||||
|
@ -150,7 +151,7 @@ impl PartialEq<MetaMethod> for &str {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq<MetaMethod> for String {
|
||||
impl PartialEq<MetaMethod> for StdString {
|
||||
fn eq(&self, other: &MetaMethod) -> bool {
|
||||
self == other.name()
|
||||
}
|
||||
|
@ -411,18 +412,23 @@ pub trait UserDataMethods<'lua, T> {
|
|||
//
|
||||
|
||||
#[doc(hidden)]
|
||||
fn add_callback(&mut self, _name: String, _callback: Callback<'lua, 'static>) {}
|
||||
fn add_callback(&mut self, _name: StdString, _callback: Callback<'lua, 'static>) {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "async")]
|
||||
fn add_async_callback(&mut self, _name: String, _callback: AsyncCallback<'lua, 'static>) {}
|
||||
fn add_async_callback(&mut self, _name: StdString, _callback: AsyncCallback<'lua, 'static>) {}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn add_meta_callback(&mut self, _name: String, _callback: Callback<'lua, 'static>) {}
|
||||
fn add_meta_callback(&mut self, _name: StdString, _callback: Callback<'lua, 'static>) {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "async")]
|
||||
fn add_async_meta_callback(&mut self, _name: String, _callback: AsyncCallback<'lua, 'static>) {}
|
||||
fn add_async_meta_callback(
|
||||
&mut self,
|
||||
_name: StdString,
|
||||
_callback: AsyncCallback<'lua, 'static>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Field registry for [`UserData`] implementors.
|
||||
|
@ -495,10 +501,10 @@ pub trait UserDataFields<'lua, T> {
|
|||
//
|
||||
|
||||
#[doc(hidden)]
|
||||
fn add_field_getter(&mut self, _name: String, _callback: Callback<'lua, 'static>) {}
|
||||
fn add_field_getter(&mut self, _name: StdString, _callback: Callback<'lua, 'static>) {}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn add_field_setter(&mut self, _name: String, _callback: Callback<'lua, 'static>) {}
|
||||
fn add_field_setter(&mut self, _name: StdString, _callback: Callback<'lua, 'static>) {}
|
||||
}
|
||||
|
||||
/// Trait for custom userdata types.
|
||||
|
@ -1045,6 +1051,30 @@ impl<'lua> AnyUserData<'lua> {
|
|||
OwnedAnyUserData(self.0.into_owned())
|
||||
}
|
||||
|
||||
/// Returns a type name of this `UserData` (from `__name` metatable field).
|
||||
pub(crate) fn type_name(&self) -> Result<Option<StdString>> {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 3)?;
|
||||
|
||||
lua.push_userdata_ref(&self.0)?;
|
||||
let protect = !lua.unlikely_memory_error();
|
||||
let name_type = if protect {
|
||||
protect_lua!(state, 1, 1, |state| {
|
||||
ffi::luaL_getmetafield(state, -1, cstr!("__name"))
|
||||
})?
|
||||
} else {
|
||||
ffi::luaL_getmetafield(state, -1, cstr!("__name"))
|
||||
};
|
||||
match name_type {
|
||||
ffi::LUA_TSTRING => Ok(Some(String(lua.pop_ref()).to_str()?.to_owned())),
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn equals<T: AsRef<Self>>(&self, other: T) -> Result<bool> {
|
||||
let other = other.as_ref();
|
||||
// Uses lua_rawequal() under the hood
|
||||
|
@ -1220,7 +1250,7 @@ impl<'lua, V> Iterator for UserDataMetatablePairs<'lua, V>
|
|||
where
|
||||
V: FromLua<'lua>,
|
||||
{
|
||||
type Item = Result<(String, V)>;
|
||||
type Item = Result<(StdString, V)>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
|
|
17
src/value.rs
17
src/value.rs
|
@ -214,7 +214,7 @@ impl<'lua> Value<'lua> {
|
|||
Value::Nil => write!(fmt, "nil"),
|
||||
Value::Boolean(b) => write!(fmt, "{b}"),
|
||||
Value::LightUserData(ud) if ud.0.is_null() => write!(fmt, "null"),
|
||||
Value::LightUserData(ud) => write!(fmt, "<lightuserdata {:?}>", ud.0),
|
||||
Value::LightUserData(ud) => write!(fmt, "lightuserdata: {:?}", ud.0),
|
||||
Value::Integer(i) => write!(fmt, "{i}"),
|
||||
Value::Number(n) => write!(fmt, "{n}"),
|
||||
#[cfg(feature = "luau")]
|
||||
|
@ -223,13 +223,16 @@ impl<'lua> Value<'lua> {
|
|||
Value::Table(t) if recursive && !visited.contains(&t.to_pointer()) => {
|
||||
t.fmt_pretty(fmt, ident, visited)
|
||||
}
|
||||
t @ Value::Table(_) => write!(fmt, "<table {:?}>", t.to_pointer()),
|
||||
f @ Value::Function(_) => write!(fmt, "<function {:?}>", f.to_pointer()),
|
||||
t @ Value::Thread(_) => write!(fmt, "<thread {:?}>", t.to_pointer()),
|
||||
// TODO: Show type name for registered userdata
|
||||
u @ Value::UserData(_) => write!(fmt, "<userdata {:?}>", u.to_pointer()),
|
||||
t @ Value::Table(_) => write!(fmt, "table: {:?}", t.to_pointer()),
|
||||
f @ Value::Function(_) => write!(fmt, "function: {:?}", f.to_pointer()),
|
||||
t @ Value::Thread(_) => write!(fmt, "thread: {:?}", t.to_pointer()),
|
||||
u @ Value::UserData(ud) => {
|
||||
let name = ud.type_name().ok().flatten();
|
||||
let name = name.unwrap_or_else(|| "userdata".to_string());
|
||||
write!(fmt, "{name}: {:?}", u.to_pointer())
|
||||
}
|
||||
Value::Error(e) if recursive => write!(fmt, "{e:?}"),
|
||||
Value::Error(_) => write!(fmt, "<error>"),
|
||||
Value::Error(_) => write!(fmt, "error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ fn test_debug_format() -> Result<()> {
|
|||
// Globals
|
||||
let globals = lua.globals();
|
||||
let dump = format!("{globals:#?}");
|
||||
assert!(dump.starts_with("{\n [\"_G\"] = <table"));
|
||||
assert!(dump.starts_with("{\n [\"_G\"] = table:"));
|
||||
|
||||
// TODO: Other cases
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::collections::HashMap;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
use std::string::String as StdString;
|
||||
|
@ -139,3 +140,16 @@ fn test_value_to_string() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_debug_format() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
lua.register_userdata_type::<HashMap<i32, StdString>>(|_| {})?;
|
||||
let ud = lua
|
||||
.create_any_userdata::<HashMap<i32, StdString>>(HashMap::new())
|
||||
.map(Value::UserData)?;
|
||||
assert!(format!("{ud:#?}").starts_with("HashMap<i32, String>:"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue