Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 0611906

Browse files
committed
Add Lua::type_metatable helper to get metatable of a primitive type.
The accompany function `Lua::set_type_metatable` already exists.
1 parent 72ac247 commit 0611906

File tree

4 files changed

+83
-50
lines changed

4 files changed

+83
-50
lines changed

‎src/state.rs‎

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,7 +1514,27 @@ impl Lua {
15141514
unsafe { self.lock().make_userdata(UserDataStorage::new(ud)) }
15151515
}
15161516

1517-
/// Sets the metatable for a Lua builtin type.
1517+
/// Gets the metatable of a Lua built-in (primitive) type.
1518+
///
1519+
/// The metatable is shared by all values of the given type.
1520+
///
1521+
/// See [`Lua::set_type_metatable`] for examples.
1522+
#[allow(private_bounds)]
1523+
pub fn type_metatable<T: LuaType>(&self) -> Option<Table> {
1524+
let lua = self.lock();
1525+
let state = lua.state();
1526+
unsafe {
1527+
let _sg = StackGuard::new(state);
1528+
assert_stack(state, 2);
1529+
1530+
if lua.push_primitive_type::<T>() && ffi::lua_getmetatable(state, -1) != 0 {
1531+
return Some(Table(lua.pop_ref()));
1532+
}
1533+
}
1534+
None
1535+
}
1536+
1537+
/// Sets the metatable for a Lua built-in (primitive) type.
15181538
///
15191539
/// The metatable will be shared by all values of the given type.
15201540
///
@@ -1541,44 +1561,13 @@ impl Lua {
15411561
let _sg = StackGuard::new(state);
15421562
assert_stack(state, 2);
15431563

1544-
match T::TYPE_ID {
1545-
ffi::LUA_TBOOLEAN => {
1546-
ffi::lua_pushboolean(state, 0);
1547-
}
1548-
ffi::LUA_TLIGHTUSERDATA => {
1549-
ffi::lua_pushlightuserdata(state, ptr::null_mut());
1550-
}
1551-
ffi::LUA_TNUMBER => {
1552-
ffi::lua_pushnumber(state, 0.);
1553-
}
1554-
#[cfg(feature = "luau")]
1555-
ffi::LUA_TVECTOR => {
1556-
#[cfg(not(feature = "luau-vector4"))]
1557-
ffi::lua_pushvector(state, 0., 0., 0.);
1558-
#[cfg(feature = "luau-vector4")]
1559-
ffi::lua_pushvector(state, 0., 0., 0., 0.);
1564+
if lua.push_primitive_type::<T>() {
1565+
match metatable {
1566+
Some(metatable) => lua.push_ref(&metatable.0),
1567+
None => ffi::lua_pushnil(state),
15601568
}
1561-
ffi::LUA_TSTRING => {
1562-
ffi::lua_pushstring(state, b"0円" as *const u8 as *const _);
1563-
}
1564-
ffi::LUA_TFUNCTION => match self.load("function() end").eval::<Function>() {
1565-
Ok(func) => lua.push_ref(&func.0),
1566-
Err(_) => return,
1567-
},
1568-
ffi::LUA_TTHREAD => {
1569-
ffi::lua_pushthread(state);
1570-
}
1571-
#[cfg(feature = "luau")]
1572-
ffi::LUA_TBUFFER => {
1573-
ffi::lua_newbuffer(state, 0);
1574-
}
1575-
_ => return,
1576-
}
1577-
match metatable {
1578-
Some(metatable) => lua.push_ref(&metatable.0),
1579-
None => ffi::lua_pushnil(state),
1569+
ffi::lua_setmetatable(state, -2);
15801570
}
1581-
ffi::lua_setmetatable(state, -2);
15821571
}
15831572
}
15841573

‎src/state/raw.rs‎

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::thread::Thread;
1919
use crate::traits::IntoLua;
2020
use crate::types::{
2121
AppDataRef, AppDataRefMut, Callback, CallbackUpvalue, DestructedUserdata, Integer, LightUserData,
22-
MaybeSend, ReentrantMutex, RegistryKey, ValueRef, XRc,
22+
LuaType,MaybeSend, ReentrantMutex, RegistryKey, ValueRef, XRc,
2323
};
2424
use crate::userdata::{
2525
init_userdata_metatable, AnyUserData, MetaMethod, RawUserDataRegistry, UserData, UserDataRegistry,
@@ -665,6 +665,46 @@ impl RawLua {
665665
}
666666
}
667667

668+
/// Pushes a primitive type value onto the Lua stack.
669+
pub(crate) unsafe fn push_primitive_type<T: LuaType>(&self) -> bool {
670+
match T::TYPE_ID {
671+
ffi::LUA_TBOOLEAN => {
672+
ffi::lua_pushboolean(self.state(), 0);
673+
}
674+
ffi::LUA_TLIGHTUSERDATA => {
675+
ffi::lua_pushlightuserdata(self.state(), ptr::null_mut());
676+
}
677+
ffi::LUA_TNUMBER => {
678+
ffi::lua_pushnumber(self.state(), 0.);
679+
}
680+
#[cfg(feature = "luau")]
681+
ffi::LUA_TVECTOR => {
682+
#[cfg(not(feature = "luau-vector4"))]
683+
ffi::lua_pushvector(self.state(), 0., 0., 0.);
684+
#[cfg(feature = "luau-vector4")]
685+
ffi::lua_pushvector(self.state(), 0., 0., 0., 0.);
686+
}
687+
ffi::LUA_TSTRING => {
688+
ffi::lua_pushstring(self.state(), b"0円" as *const u8 as *const _);
689+
}
690+
ffi::LUA_TFUNCTION => {
691+
unsafe extern "C-unwind" fn func(_state: *mut ffi::lua_State) -> c_int {
692+
0
693+
}
694+
ffi::lua_pushcfunction(self.state(), func);
695+
}
696+
ffi::LUA_TTHREAD => {
697+
ffi::lua_pushthread(self.state());
698+
}
699+
#[cfg(feature = "luau")]
700+
ffi::LUA_TBUFFER => {
701+
ffi::lua_newbuffer(self.state(), 0);
702+
}
703+
_ => return false,
704+
}
705+
true
706+
}
707+
668708
/// Pushes a value that implements `IntoLua` onto the Lua stack.
669709
///
670710
/// Uses up to 2 stack spaces to push a single value, does not call `checkstack`.

‎src/table.rs‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use std::collections::HashSet;
22
use std::fmt;
33
use std::marker::PhantomData;
4-
use std::os::raw::{c_int,c_void};
4+
use std::os::raw::c_void;
55
use std::string::String as StdString;
66

77
use crate::error::{Error, Result};
88
use crate::function::Function;
99
use crate::state::{LuaGuard, RawLua, WeakLua};
1010
use crate::traits::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, ObjectLike};
11-
use crate::types::{Integer, LuaType,ValueRef};
11+
use crate::types::{Integer, ValueRef};
1212
use crate::util::{assert_stack, check_stack, get_metatable_ptr, StackGuard};
1313
use crate::value::{Nil, Value};
1414

@@ -935,10 +935,6 @@ where
935935
}
936936
}
937937

938-
impl LuaType for Table {
939-
const TYPE_ID: c_int = ffi::LUA_TTABLE;
940-
}
941-
942938
impl ObjectLike for Table {
943939
#[inline]
944940
fn get<V: FromLua>(&self, key: impl IntoLua) -> Result<V> {

‎tests/types.rs‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ fn test_boolean_type_metatable() -> Result<()> {
3131

3232
let mt = lua.create_table()?;
3333
mt.set("__add", Function::wrap(|a, b| Ok(a || b)))?;
34-
lua.set_type_metatable::<bool>(Some(mt));
34+
assert_eq!(lua.type_metatable::<bool>(), None);
35+
lua.set_type_metatable::<bool>(Some(mt.clone()));
36+
assert_eq!(lua.type_metatable::<bool>().unwrap(), mt);
3537

3638
lua.load(r#"assert(true + true == true)"#).exec().unwrap();
3739
lua.load(r#"assert(true + false == true)"#).exec().unwrap();
@@ -52,7 +54,8 @@ fn test_lightuserdata_type_metatable() -> Result<()> {
5254
Ok(LightUserData((a.0 as usize + b.0 as usize) as *mut c_void))
5355
}),
5456
)?;
55-
lua.set_type_metatable::<LightUserData>(Some(mt));
57+
lua.set_type_metatable::<LightUserData>(Some(mt.clone()));
58+
assert_eq!(lua.type_metatable::<LightUserData>().unwrap(), mt);
5659

5760
let res = lua
5861
.load(
@@ -77,7 +80,9 @@ fn test_number_type_metatable() -> Result<()> {
7780

7881
let mt = lua.create_table()?;
7982
mt.set("__call", Function::wrap(|n1: f64, n2: f64| Ok(n1 * n2)))?;
80-
lua.set_type_metatable::<Number>(Some(mt));
83+
lua.set_type_metatable::<Number>(Some(mt.clone()));
84+
assert_eq!(lua.type_metatable::<Number>().unwrap(), mt);
85+
8186
lua.load(r#"assert((1.5)(3.0) == 4.5)"#).exec().unwrap();
8287
lua.load(r#"assert((5)(5) == 25)"#).exec().unwrap();
8388

@@ -93,7 +98,8 @@ fn test_string_type_metatable() -> Result<()> {
9398
"__add",
9499
Function::wrap(|a: String, b: String| Ok(format!("{a}{b}"))),
95100
)?;
96-
lua.set_type_metatable::<LuaString>(Some(mt));
101+
lua.set_type_metatable::<LuaString>(Some(mt.clone()));
102+
assert_eq!(lua.type_metatable::<LuaString>().unwrap(), mt);
97103

98104
lua.load(r#"assert(("foo" + "bar") == "foobar")"#).exec().unwrap();
99105

@@ -109,7 +115,8 @@ fn test_function_type_metatable() -> Result<()> {
109115
"__index",
110116
Function::wrap(|_: Function, key: String| Ok(format!("function.{key}"))),
111117
)?;
112-
lua.set_type_metatable::<Function>(Some(mt));
118+
lua.set_type_metatable::<Function>(Some(mt.clone()));
119+
assert_eq!(lua.type_metatable::<Function>(), Some(mt));
113120

114121
lua.load(r#"assert((function() end).foo == "function.foo")"#)
115122
.exec()
@@ -127,7 +134,8 @@ fn test_thread_type_metatable() -> Result<()> {
127134
"__index",
128135
Function::wrap(|_: Thread, key: String| Ok(format!("thread.{key}"))),
129136
)?;
130-
lua.set_type_metatable::<Thread>(Some(mt));
137+
lua.set_type_metatable::<Thread>(Some(mt.clone()));
138+
assert_eq!(lua.type_metatable::<Thread>(), Some(mt));
131139

132140
lua.load(r#"assert((coroutine.create(function() end)).foo == "thread.foo")"#)
133141
.exec()

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /