mirror of
https://github.com/mlua-rs/mlua
synced 2026-06-08 16:05:43 +00:00
Support LuaJIT cdata type (produced by ffi module)
This commit is contained in:
+11
-12
@@ -26,7 +26,7 @@ use crate::table::Table;
|
||||
use crate::thread::Thread;
|
||||
use crate::types::{
|
||||
AppData, AppDataRef, AppDataRefMut, Callback, CallbackUpvalue, DestructedUserdata, Integer,
|
||||
LightUserData, LuaRef, MaybeSend, Number, RegistryKey,
|
||||
LightUserData, LuaRef, MaybeSend, Number, RegistryKey, SubtypeId,
|
||||
};
|
||||
use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataCell};
|
||||
use crate::userdata_impl::{UserDataProxy, UserDataRegistry};
|
||||
@@ -2419,7 +2419,7 @@ impl Lua {
|
||||
ffi::lua_pop(state, 1);
|
||||
Nil
|
||||
}
|
||||
_ => Value::UserData(AnyUserData(self.pop_ref(), 0)),
|
||||
_ => Value::UserData(AnyUserData(self.pop_ref(), SubtypeId::None)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2428,14 +2428,13 @@ impl Lua {
|
||||
#[cfg(feature = "luau")]
|
||||
ffi::LUA_TBUFFER => {
|
||||
// Buffer is represented as a userdata type
|
||||
Value::UserData(AnyUserData(self.pop_ref(), crate::types::BUFFER_SUBTYPE_ID))
|
||||
Value::UserData(AnyUserData(self.pop_ref(), SubtypeId::Buffer))
|
||||
}
|
||||
|
||||
#[cfg(feature = "luajit")]
|
||||
ffi::LUA_TCDATA => {
|
||||
ffi::lua_pop(state, 1);
|
||||
// TODO: Fix this in a next major release
|
||||
panic!("cdata objects cannot be handled by mlua yet");
|
||||
// CDATA is represented as a userdata type
|
||||
Value::UserData(AnyUserData(self.pop_ref(), SubtypeId::CData))
|
||||
}
|
||||
|
||||
_ => mlua_panic!("LUA_TNONE in pop_value"),
|
||||
@@ -2520,7 +2519,7 @@ impl Lua {
|
||||
}
|
||||
_ => {
|
||||
ffi::lua_xpush(state, self.ref_thread(), idx);
|
||||
Value::UserData(AnyUserData(self.pop_ref_thread(), 0))
|
||||
Value::UserData(AnyUserData(self.pop_ref_thread(), SubtypeId::None))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2534,14 +2533,14 @@ impl Lua {
|
||||
ffi::LUA_TBUFFER => {
|
||||
// Buffer is represented as a userdata type
|
||||
ffi::lua_xpush(state, self.ref_thread(), idx);
|
||||
let subtype_id = crate::types::BUFFER_SUBTYPE_ID;
|
||||
Value::UserData(AnyUserData(self.pop_ref_thread(), subtype_id))
|
||||
Value::UserData(AnyUserData(self.pop_ref_thread(), SubtypeId::Buffer))
|
||||
}
|
||||
|
||||
#[cfg(feature = "luajit")]
|
||||
ffi::LUA_TCDATA => {
|
||||
// TODO: Fix this in a next major release
|
||||
panic!("cdata objects cannot be handled by mlua yet");
|
||||
// CData is represented as a userdata type
|
||||
ffi::lua_xpush(state, self.ref_thread(), idx);
|
||||
Value::UserData(AnyUserData(self.pop_ref_thread(), SubtypeId::CData))
|
||||
}
|
||||
|
||||
_ => mlua_panic!("LUA_TNONE in pop_value"),
|
||||
@@ -3126,7 +3125,7 @@ impl Lua {
|
||||
ffi::lua_setuservalue(state, -2);
|
||||
}
|
||||
|
||||
Ok(AnyUserData(self.pop_ref(), 0))
|
||||
Ok(AnyUserData(self.pop_ref(), SubtypeId::None))
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ use serde::Serialize;
|
||||
use crate::error::{Error, Result};
|
||||
use crate::function::Function;
|
||||
use crate::lua::Lua;
|
||||
use crate::types::{Callback, CallbackUpvalue, LuaRef, MaybeSend};
|
||||
use crate::types::{Callback, CallbackUpvalue, LuaRef, MaybeSend, SubtypeId};
|
||||
use crate::userdata::{
|
||||
AnyUserData, MetaMethod, UserData, UserDataCell, UserDataFields, UserDataMethods,
|
||||
};
|
||||
@@ -511,7 +511,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
||||
#[cfg(not(feature = "luau"))]
|
||||
std::ptr::write(ud_ptr as _, UserDataCell::new(data));
|
||||
ffi::lua_setmetatable(state, -2);
|
||||
let ud = AnyUserData(lua.pop_ref(), 0);
|
||||
let ud = AnyUserData(lua.pop_ref(), SubtypeId::None);
|
||||
lua.register_raw_userdata_metatable(mt_ptr, None);
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
|
||||
+9
-3
@@ -29,9 +29,15 @@ pub type Integer = ffi::lua_Integer;
|
||||
/// Type of Lua floating point numbers.
|
||||
pub type Number = ffi::lua_Number;
|
||||
|
||||
// LUA_TBUFFER subtype
|
||||
#[cfg(feature = "luau")]
|
||||
pub(crate) const BUFFER_SUBTYPE_ID: u8 = 1;
|
||||
// Represents different subtypes wrapped to AnyUserData
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub(crate) enum SubtypeId {
|
||||
None,
|
||||
#[cfg(feature = "luau")]
|
||||
Buffer,
|
||||
#[cfg(feature = "luajit")]
|
||||
CData,
|
||||
}
|
||||
|
||||
/// A "light" userdata value. Equivalent to an unmanaged raw pointer.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
|
||||
+9
-6
@@ -22,7 +22,7 @@ use crate::function::Function;
|
||||
use crate::lua::Lua;
|
||||
use crate::string::String;
|
||||
use crate::table::{Table, TablePairs};
|
||||
use crate::types::{LuaRef, MaybeSend};
|
||||
use crate::types::{LuaRef, MaybeSend, SubtypeId};
|
||||
use crate::util::{check_stack, get_userdata, take_userdata, StackGuard};
|
||||
use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Value};
|
||||
use crate::UserDataRegistry;
|
||||
@@ -791,7 +791,7 @@ impl<T> Deref for UserDataVariant<T> {
|
||||
/// [`is`]: crate::AnyUserData::is
|
||||
/// [`borrow`]: crate::AnyUserData::borrow
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AnyUserData<'lua>(pub(crate) LuaRef<'lua>, pub(crate) u8);
|
||||
pub struct AnyUserData<'lua>(pub(crate) LuaRef<'lua>, pub(crate) SubtypeId);
|
||||
|
||||
/// Owned handle to an internal Lua userdata.
|
||||
///
|
||||
@@ -801,7 +801,7 @@ pub struct AnyUserData<'lua>(pub(crate) LuaRef<'lua>, pub(crate) u8);
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OwnedAnyUserData(pub(crate) crate::types::LuaOwnedRef, pub(crate) u8);
|
||||
pub struct OwnedAnyUserData(pub(crate) crate::types::LuaOwnedRef, pub(crate) SubtypeId);
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
impl OwnedAnyUserData {
|
||||
@@ -1112,9 +1112,12 @@ impl<'lua> AnyUserData<'lua> {
|
||||
|
||||
/// Returns a type name of this `UserData` (from a metatable field).
|
||||
pub(crate) fn type_name(&self) -> Result<Option<StdString>> {
|
||||
#[cfg(feature = "luau")]
|
||||
if self.1 == crate::types::BUFFER_SUBTYPE_ID {
|
||||
return Ok(Some("buffer".to_owned()));
|
||||
match self.1 {
|
||||
SubtypeId::None => {}
|
||||
#[cfg(feature = "luau")]
|
||||
SubtypeId::Buffer => return Ok(Some("buffer".to_owned())),
|
||||
#[cfg(feature = "luajit")]
|
||||
SubtypeId::CData => return Ok(Some("cdata".to_owned())),
|
||||
}
|
||||
|
||||
let lua = self.0.lua;
|
||||
|
||||
+17
-4
@@ -24,7 +24,7 @@ use crate::lua::Lua;
|
||||
use crate::string::String;
|
||||
use crate::table::Table;
|
||||
use crate::thread::Thread;
|
||||
use crate::types::{Integer, LightUserData, Number};
|
||||
use crate::types::{Integer, LightUserData, Number, SubtypeId};
|
||||
use crate::userdata::AnyUserData;
|
||||
use crate::util::{check_stack, StackGuard};
|
||||
|
||||
@@ -88,9 +88,11 @@ impl<'lua> Value<'lua> {
|
||||
Value::Table(_) => "table",
|
||||
Value::Function(_) => "function",
|
||||
Value::Thread(_) => "thread",
|
||||
Value::UserData(AnyUserData(_, SubtypeId::None)) => "userdata",
|
||||
#[cfg(feature = "luau")]
|
||||
Value::UserData(AnyUserData(_, crate::types::BUFFER_SUBTYPE_ID)) => "buffer",
|
||||
Value::UserData(_) => "userdata",
|
||||
Value::UserData(AnyUserData(_, SubtypeId::Buffer)) => "buffer",
|
||||
#[cfg(feature = "luajit")]
|
||||
Value::UserData(AnyUserData(_, SubtypeId::CData)) => "cdata",
|
||||
Value::Error(_) => "error",
|
||||
}
|
||||
}
|
||||
@@ -419,7 +421,18 @@ impl<'lua> Value<'lua> {
|
||||
#[inline]
|
||||
pub fn is_buffer(&self) -> bool {
|
||||
self.as_userdata()
|
||||
.map(|ud| ud.1 == crate::types::BUFFER_SUBTYPE_ID)
|
||||
.map(|ud| ud.1 == SubtypeId::Buffer)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Returns `true` if the value is a CData wrapped in [`AnyUserData`].
|
||||
#[cfg(any(feature = "luajit", doc))]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "luajit")))]
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn is_cdata(&self) -> bool {
|
||||
self.as_userdata()
|
||||
.map(|ud| ud.1 == SubtypeId::CData)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
|
||||
+9
-4
@@ -1325,10 +1325,10 @@ fn test_warnings() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "luajit")]
|
||||
#[should_panic]
|
||||
fn test_luajit_cdata() {
|
||||
fn test_luajit_cdata() -> Result<()> {
|
||||
let lua = unsafe { Lua::unsafe_new() };
|
||||
let _v: Result<Value> = lua
|
||||
|
||||
let cdata = lua
|
||||
.load(
|
||||
r#"
|
||||
local ffi = require("ffi")
|
||||
@@ -1341,7 +1341,12 @@ fn test_luajit_cdata() {
|
||||
return ptr
|
||||
"#,
|
||||
)
|
||||
.eval();
|
||||
.eval::<Value>()?;
|
||||
assert!(cdata.is_userdata() && cdata.is_cdata());
|
||||
assert_eq!(cdata.type_name(), "cdata");
|
||||
assert!(cdata.to_string()?.starts_with("cdata<void *>:"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user