diff options
-rw-r--r-- | src/lua.rs | 23 | ||||
-rw-r--r-- | src/scope.rs | 4 | ||||
-rw-r--r-- | src/types.rs | 12 | ||||
-rw-r--r-- | src/userdata.rs | 15 | ||||
-rw-r--r-- | src/value.rs | 21 | ||||
-rw-r--r-- | tests/tests.rs | 13 |
6 files changed, 57 insertions, 31 deletions
@@ -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"))] diff --git a/src/scope.rs b/src/scope.rs index bad966b..350650e 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -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"))] diff --git a/src/types.rs b/src/types.rs index c8775b7..f21af2d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -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)] diff --git a/src/userdata.rs b/src/userdata.rs index ac68b1a..15e2134 100644 --- a/src/userdata.rs +++ b/src/userdata.rs @@ -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; diff --git a/src/value.rs b/src/value.rs index 5575d82..9ec4e04 100644 --- a/src/value.rs +++ b/src/value.rs @@ -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() } diff --git a/tests/tests.rs b/tests/tests.rs index cd7ca10..0b7a0a6 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -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] |