Skip to content

Commit 04d8106

Browse files
committed
Remove SubtypeId from AnyUserData and instead add Value::Other variant that will cover any unknown types (eg. LuaJIT CData)
1 parent b6cdf32 commit 04d8106

File tree

9 files changed

+31
-52
lines changed

9 files changed

+31
-52
lines changed

Diff for: src/scope.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::os::raw::c_void;
66
use crate::error::{Error, Result};
77
use crate::function::Function;
88
use crate::state::{Lua, LuaGuard, RawLua};
9-
use crate::types::{Callback, CallbackUpvalue, ScopedCallback, SubtypeId, ValueRef};
9+
use crate::types::{Callback, CallbackUpvalue, ScopedCallback, ValueRef};
1010
use crate::userdata::{AnyUserData, UserData, UserDataRegistry, UserDataStorage};
1111
use crate::util::{self, assert_stack, check_stack, get_userdata, take_userdata, StackGuard};
1212
use crate::value::{FromLuaMulti, IntoLuaMulti};
@@ -186,7 +186,7 @@ impl<'scope, 'env: 'scope> Scope<'scope, 'env> {
186186
std::ptr::write(ud_ptr, UserDataStorage::new_scoped(data));
187187
ffi::lua_setmetatable(state, -2);
188188

189-
let ud = AnyUserData(self.lua.pop_ref(), SubtypeId::None);
189+
let ud = AnyUserData(self.lua.pop_ref());
190190

191191
let destructor: DestructorCallback = Box::new(|rawlua, vref| {
192192
let state = rawlua.state();

Diff for: src/serde/de.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ impl<'de> serde::Deserializer<'de> for Deserializer {
150150
| Value::Thread(_)
151151
| Value::UserData(_)
152152
| Value::LightUserData(_)
153-
| Value::Error(_) => {
153+
| Value::Error(_)
154+
| Value::Other(_) => {
154155
if self.options.deny_unsupported_types {
155156
let msg = format!("unsupported value type `{}`", self.value.type_name());
156157
Err(de::Error::custom(msg))

Diff for: src/state/raw.rs

+6-9
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::table::Table;
1818
use crate::thread::Thread;
1919
use crate::types::{
2020
AppDataRef, AppDataRefMut, Callback, CallbackUpvalue, DestructedUserdata, Integer, LightUserData,
21-
MaybeSend, ReentrantMutex, RegistryKey, SubtypeId, ValueRef, XRc,
21+
MaybeSend, ReentrantMutex, RegistryKey, ValueRef, XRc,
2222
};
2323
use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataRegistry, UserDataStorage};
2424
use crate::util::{
@@ -560,6 +560,7 @@ impl RawLua {
560560
let protect = !self.unlikely_memory_error();
561561
push_internal_userdata(state, WrappedFailure::Error(*err.clone()), protect)?;
562562
}
563+
Value::Other(vref) => self.push_ref(vref),
563564
}
564565
Ok(())
565566
}
@@ -644,7 +645,7 @@ impl RawLua {
644645
}
645646
_ => {
646647
ffi::lua_xpush(state, self.ref_thread(), idx);
647-
Value::UserData(AnyUserData(self.pop_ref_thread(), SubtypeId::None))
648+
Value::UserData(AnyUserData(self.pop_ref_thread()))
648649
}
649650
}
650651
}
@@ -661,14 +662,10 @@ impl RawLua {
661662
Value::Buffer(crate::Buffer(self.pop_ref_thread()))
662663
}
663664

664-
#[cfg(feature = "luajit")]
665-
ffi::LUA_TCDATA => {
666-
// CData is represented as a userdata type
665+
_ => {
667666
ffi::lua_xpush(state, self.ref_thread(), idx);
668-
Value::UserData(AnyUserData(self.pop_ref_thread(), SubtypeId::CData))
667+
Value::Other(self.pop_ref_thread())
669668
}
670-
671-
_ => mlua_panic!("unexpected value type on stack"),
672669
}
673670
}
674671

@@ -806,7 +803,7 @@ impl RawLua {
806803
ffi::lua_setuservalue(state, -2);
807804
}
808805

809-
Ok(AnyUserData(self.pop_ref(), SubtypeId::None))
806+
Ok(AnyUserData(self.pop_ref()))
810807
}
811808

812809
pub(crate) unsafe fn create_userdata_metatable<T>(

Diff for: src/types.rs

-8
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,6 @@ pub type Integer = ffi::lua_Integer;
2828
/// Type of Lua floating point numbers.
2929
pub type Number = ffi::lua_Number;
3030

31-
// Represents different subtypes wrapped in AnyUserData
32-
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
33-
pub(crate) enum SubtypeId {
34-
None,
35-
#[cfg(feature = "luajit")]
36-
CData,
37-
}
38-
3931
/// A "light" userdata value. Equivalent to an unmanaged raw pointer.
4032
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
4133
pub struct LightUserData(pub *mut c_void);

Diff for: src/userdata.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::function::Function;
1919
use crate::state::Lua;
2020
use crate::string::String;
2121
use crate::table::{Table, TablePairs};
22-
use crate::types::{MaybeSend, SubtypeId, ValueRef};
22+
use crate::types::{MaybeSend, ValueRef};
2323
use crate::util::{check_stack, get_userdata, take_userdata, StackGuard};
2424
use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Value};
2525

@@ -643,7 +643,7 @@ pub trait UserData: Sized {
643643
/// [`is`]: crate::AnyUserData::is
644644
/// [`borrow`]: crate::AnyUserData::borrow
645645
#[derive(Clone, Debug)]
646-
pub struct AnyUserData(pub(crate) ValueRef, pub(crate) SubtypeId);
646+
pub struct AnyUserData(pub(crate) ValueRef);
647647

648648
impl AnyUserData {
649649
/// Checks whether the type of this userdata is `T`.
@@ -935,12 +935,6 @@ impl AnyUserData {
935935

936936
/// Returns a type name of this `UserData` (from a metatable field).
937937
pub(crate) fn type_name(&self) -> Result<Option<StdString>> {
938-
match self.1 {
939-
SubtypeId::None => {}
940-
#[cfg(feature = "luajit")]
941-
SubtypeId::CData => return Ok(Some("cdata".to_owned())),
942-
}
943-
944938
let lua = self.0.lua.lock();
945939
let state = lua.state();
946940
unsafe {

Diff for: src/userdata/object.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,6 @@ impl ObjectLike for AnyUserData {
8888

8989
#[inline]
9090
fn to_string(&self) -> Result<StdString> {
91-
Value::UserData(AnyUserData(self.0.copy(), self.1)).to_string()
91+
Value::UserData(AnyUserData(self.0.copy())).to_string()
9292
}
9393
}

Diff for: src/util/mod.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,10 @@ pub(crate) unsafe fn to_string(state: *mut ffi::lua_State, index: c_int) -> Stri
275275
ffi::LUA_TTHREAD => format!("<thread {:?}>", ffi::lua_topointer(state, index)),
276276
#[cfg(feature = "luau")]
277277
ffi::LUA_TBUFFER => format!("<buffer {:?}>", ffi::lua_topointer(state, index)),
278-
#[cfg(feature = "luajit")]
279-
ffi::LUA_TCDATA => format!("<cdata {:?}>", ffi::lua_topointer(state, index)),
280-
_ => "<unknown>".to_string(),
278+
type_id => {
279+
let type_name = CStr::from_ptr(ffi::lua_typename(state, type_id)).to_string_lossy();
280+
format!("<{type_name} {:?}>", ffi::lua_topointer(state, index))
281+
}
281282
}
282283
}
283284

Diff for: src/value.rs

+13-18
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::state::{Lua, RawLua};
1414
use crate::string::{BorrowedStr, String};
1515
use crate::table::Table;
1616
use crate::thread::Thread;
17-
use crate::types::{Integer, LightUserData, Number, SubtypeId, ValueRef};
17+
use crate::types::{Integer, LightUserData, Number, ValueRef};
1818
use crate::userdata::AnyUserData;
1919
use crate::util::{check_stack, StackGuard};
2020

@@ -28,7 +28,7 @@ use {
2828

2929
/// A dynamically typed Lua value.
3030
///
31-
/// The `String`, `Table`, `Function`, `Thread`, and `UserData` variants contain handle types
31+
/// The non-primitive variants (eg. string/table/function/thread/userdata) contain handle types
3232
/// into the internal Lua state. It is a logic error to mix handle types between separate
3333
/// `Lua` instances, and doing so will result in a panic.
3434
#[derive(Clone)]
@@ -69,6 +69,9 @@ pub enum Value {
6969
Buffer(crate::Buffer),
7070
/// `Error` is a special builtin userdata type. When received from Lua it is implicitly cloned.
7171
Error(Box<Error>),
72+
/// Any other value not known to mlua (eg. LuaJIT CData).
73+
#[allow(private_interfaces)]
74+
Other(ValueRef),
7275
}
7376

7477
pub use self::Value::Nil;
@@ -93,12 +96,11 @@ impl Value {
9396
Value::Table(_) => "table",
9497
Value::Function(_) => "function",
9598
Value::Thread(_) => "thread",
96-
Value::UserData(AnyUserData(_, SubtypeId::None)) => "userdata",
97-
#[cfg(feature = "luajit")]
98-
Value::UserData(AnyUserData(_, SubtypeId::CData)) => "cdata",
99+
Value::UserData(_) => "userdata",
99100
#[cfg(feature = "luau")]
100101
Value::Buffer(_) => "buffer",
101102
Value::Error(_) => "error",
103+
Value::Other(_) => "other",
102104
}
103105
}
104106

@@ -173,7 +175,8 @@ impl Value {
173175
Value::Table(Table(vref))
174176
| Value::Function(Function(vref))
175177
| Value::Thread(Thread(vref, ..))
176-
| Value::UserData(AnyUserData(vref, ..)) => unsafe { invoke_to_string(vref) },
178+
| Value::UserData(AnyUserData(vref))
179+
| Value::Other(vref) => unsafe { invoke_to_string(vref) },
177180
#[cfg(feature = "luau")]
178181
Value::Buffer(crate::Buffer(vref)) => unsafe { invoke_to_string(vref) },
179182
Value::Error(err) => Ok(err.to_string()),
@@ -448,17 +451,6 @@ impl Value {
448451
self.as_buffer().is_some()
449452
}
450453

451-
/// Returns `true` if the value is a CData wrapped in [`AnyUserData`].
452-
#[cfg(any(feature = "luajit", doc))]
453-
#[cfg_attr(docsrs, doc(cfg(feature = "luajit")))]
454-
#[doc(hidden)]
455-
#[inline]
456-
pub fn is_cdata(&self) -> bool {
457-
self.as_userdata()
458-
.map(|ud| ud.1 == SubtypeId::CData)
459-
.unwrap_or_default()
460-
}
461-
462454
/// Wrap reference to this Value into [`SerializableValue`].
463455
///
464456
/// This allows customizing serialization behavior using serde.
@@ -548,6 +540,7 @@ impl Value {
548540
buf @ Value::Buffer(_) => write!(fmt, "buffer: {:?}", buf.to_pointer()),
549541
Value::Error(e) if recursive => write!(fmt, "{e:?}"),
550542
Value::Error(_) => write!(fmt, "error"),
543+
Value::Other(v) => write!(fmt, "other: {:?}", v.to_pointer()),
551544
}
552545
}
553546
}
@@ -574,6 +567,7 @@ impl fmt::Debug for Value {
574567
#[cfg(feature = "luau")]
575568
Value::Buffer(buf) => write!(fmt, "{buf:?}"),
576569
Value::Error(e) => write!(fmt, "Error({e:?})"),
570+
Value::Other(v) => write!(fmt, "Other({v:?})"),
577571
}
578572
}
579573
}
@@ -711,7 +705,8 @@ impl<'a> Serialize for SerializableValue<'a> {
711705
| Value::Thread(_)
712706
| Value::UserData(_)
713707
| Value::LightUserData(_)
714-
| Value::Error(_) => {
708+
| Value::Error(_)
709+
| Value::Other(_) => {
715710
if self.options.deny_unsupported_types {
716711
let msg = format!("cannot serialize <{}>", self.value.type_name());
717712
Err(ser::Error::custom(msg))

Diff for: tests/tests.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1256,8 +1256,7 @@ fn test_luajit_cdata() -> Result<()> {
12561256
"#,
12571257
)
12581258
.eval::<Value>()?;
1259-
assert!(cdata.is_userdata() && cdata.is_cdata());
1260-
assert_eq!(cdata.type_name(), "cdata");
1259+
assert_eq!(cdata.type_name(), "other");
12611260
assert!(cdata.to_string()?.starts_with("cdata<void *>:"));
12621261

12631262
Ok(())

0 commit comments

Comments
 (0)