summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lua.rs23
-rw-r--r--src/scope.rs4
-rw-r--r--src/types.rs12
-rw-r--r--src/userdata.rs15
-rw-r--r--src/value.rs21
-rw-r--r--tests/tests.rs13
6 files changed, 57 insertions, 31 deletions
diff --git a/src/lua.rs b/src/lua.rs
index 7e1eb16..e4f88a1 100644
--- a/src/lua.rs
+++ b/src/lua.rs
@@ -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]