Set `__name` field in userdata metatable if not provided
This commit is contained in:
parent
2efc637ab9
commit
68e65a8ffe
10
src/lua.rs
10
src/lua.rs
|
@ -34,7 +34,7 @@ use crate::util::{
|
|||
self, assert_stack, callback_error, check_stack, get_destructed_userdata_metatable,
|
||||
get_gc_metatable, get_gc_userdata, get_main_state, get_userdata, init_error_registry,
|
||||
init_gc_metatable, init_userdata_metatable, pop_error, push_gc_userdata, push_string,
|
||||
push_table, rawset_field, safe_pcall, safe_xpcall, StackGuard, WrappedFailure,
|
||||
push_table, rawset_field, safe_pcall, safe_xpcall, short_type_name, StackGuard, WrappedFailure,
|
||||
};
|
||||
use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, MultiValue, Nil, Value};
|
||||
|
||||
|
@ -2529,10 +2529,18 @@ impl Lua {
|
|||
self.push_value(Value::Function(self.create_async_callback(m)?))?;
|
||||
rawset_field(state, -2, MetaMethod::validate(&k)?)?;
|
||||
}
|
||||
let mut has_name = false;
|
||||
for (k, f) in registry.meta_fields {
|
||||
has_name = has_name || k == "__name";
|
||||
self.push_value(f(self)?)?;
|
||||
rawset_field(state, -2, MetaMethod::validate(&k)?)?;
|
||||
}
|
||||
// Set `__name` if not provided
|
||||
if !has_name {
|
||||
let type_name = short_type_name::<T>();
|
||||
push_string(state, type_name.as_bytes(), !self.unlikely_memory_error())?;
|
||||
rawset_field(state, -2, "__name")?;
|
||||
}
|
||||
let metatable_index = ffi::lua_absindex(state, -1);
|
||||
|
||||
let mut extra_tables_count = 0;
|
||||
|
|
|
@ -538,30 +538,22 @@ fn test_fields() -> Result<()> {
|
|||
#[test]
|
||||
fn test_metatable() -> Result<()> {
|
||||
#[derive(Copy, Clone)]
|
||||
struct MyUserData(i64);
|
||||
struct MyUserData;
|
||||
|
||||
impl UserData for MyUserData {
|
||||
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_meta_field_with("__type_name", |_| Ok("MyUserData"));
|
||||
}
|
||||
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_function("my_type_name", |_, data: AnyUserData| {
|
||||
let metatable = data.get_metatable()?;
|
||||
metatable.get::<String>("__type_name")
|
||||
metatable.get::<String>("__name")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
globals.set("ud", MyUserData(7))?;
|
||||
lua.load(
|
||||
r#"
|
||||
assert(ud:my_type_name() == "MyUserData")
|
||||
"#,
|
||||
)
|
||||
.exec()?;
|
||||
globals.set("ud", MyUserData)?;
|
||||
lua.load(r#"assert(ud:my_type_name() == "MyUserData")"#)
|
||||
.exec()?;
|
||||
|
||||
let ud: AnyUserData = globals.get("ud")?;
|
||||
let metatable = ud.get_metatable()?;
|
||||
|
@ -583,10 +575,10 @@ fn test_metatable() -> Result<()> {
|
|||
.map(|kv: Result<(_, Value)>| Ok(kv?.0))
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
methods.sort();
|
||||
assert_eq!(methods, vec!["__index", "__type_name"]);
|
||||
assert_eq!(methods, vec!["__index", "__name"]);
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct MyUserData2(i64);
|
||||
struct MyUserData2;
|
||||
|
||||
impl UserData for MyUserData2 {
|
||||
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
|
@ -594,12 +586,25 @@ fn test_metatable() -> Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
match lua.create_userdata(MyUserData2(1)) {
|
||||
match lua.create_userdata(MyUserData2) {
|
||||
Ok(_) => panic!("expected MetaMethodTypeError, got no error"),
|
||||
Err(Error::MetaMethodTypeError { .. }) => {}
|
||||
Err(e) => panic!("expected MetaMethodTypeError, got {:?}", e),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct MyUserData3;
|
||||
|
||||
impl UserData for MyUserData3 {
|
||||
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_meta_field_with("__name", |_| Ok("CustomName"));
|
||||
}
|
||||
}
|
||||
|
||||
let ud = lua.create_userdata(MyUserData3)?;
|
||||
let metatable = ud.get_metatable()?;
|
||||
assert_eq!(metatable.get::<String>("__name")?.to_str()?, "CustomName");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue