diff --git a/mlua-sys/src/luau/compat.rs b/mlua-sys/src/luau/compat.rs index f08882d..192e812 100644 --- a/mlua-sys/src/luau/compat.rs +++ b/mlua-sys/src/luau/compat.rs @@ -397,6 +397,7 @@ pub unsafe fn luaL_len(L: *mut lua_State, idx: c_int) -> lua_Integer { res } +// TODO: why not just checkstack and concat all at the end? pub unsafe fn luaL_traceback( L: *mut lua_State, L1: *mut lua_State, diff --git a/src/conversion.rs b/src/conversion.rs index 98ba199..52c30d1 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -38,30 +38,45 @@ impl<'lua> FromLua<'lua> for Value<'lua> { } } +impl<'lua> From> for Value<'lua> { + #[inline] + fn from(value: String<'lua>) -> Self { + Value::String(value) + } +} + impl<'lua> IntoLua<'lua> for String<'lua> { #[inline] fn into_lua(self, _: &'lua Lua) -> Result> { - Ok(Value::String(self)) + Ok(self.into()) } } impl<'lua> FromLua<'lua> for String<'lua> { #[inline] - fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result> { - let ty = value.type_name(); - lua.coerce_string(value)? - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: "String", - message: Some("expected string or number".to_string()), + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result> { + match value { + Value::String(s) => Ok(s), + _ => Err(Error::FromLuaConversionError { + from: value.type_name(), + to: "string", + message: None, }) + } + } +} + +impl<'lua> From> for Value<'lua> { + #[inline] + fn from(value: Table<'lua>) -> Self { + Value::Table(value) } } impl<'lua> IntoLua<'lua> for Table<'lua> { #[inline] fn into_lua(self, _: &'lua Lua) -> Result> { - Ok(Value::Table(self)) + Ok(self.into()) } } @@ -97,10 +112,17 @@ impl<'lua> FromLua<'lua> for OwnedTable { } } +impl<'lua> From> for Value<'lua> { + #[inline] + fn from(value: Function<'lua>) -> Self { + Value::Function(value) + } +} + impl<'lua> IntoLua<'lua> for Function<'lua> { #[inline] fn into_lua(self, _: &'lua Lua) -> Result> { - Ok(Value::Function(self)) + Ok(self.into()) } } @@ -151,10 +173,17 @@ impl<'lua> IntoLua<'lua> for WrappedAsyncFunction<'lua> { } } +impl<'lua> From> for Value<'lua> { + #[inline] + fn from(value: Thread<'lua>) -> Self { + Value::Thread(value) + } +} + impl<'lua> IntoLua<'lua> for Thread<'lua> { #[inline] fn into_lua(self, _: &'lua Lua) -> Result> { - Ok(Value::Thread(self)) + Ok(self.into()) } } @@ -172,10 +201,17 @@ impl<'lua> FromLua<'lua> for Thread<'lua> { } } +impl<'lua> From> for Value<'lua> { + #[inline] + fn from(value: AnyUserData<'lua>) -> Self { + Value::UserData(value) + } +} + impl<'lua> IntoLua<'lua> for AnyUserData<'lua> { #[inline] fn into_lua(self, _: &'lua Lua) -> Result> { - Ok(Value::UserData(self)) + Ok(self.into()) } } @@ -232,49 +268,67 @@ impl<'lua, T: 'static> FromLua<'lua> for UserDataRefMut<'lua, T> { } } +impl<'lua> From for Value<'lua> { + #[inline] + fn from(value: Error) -> Self { + Value::Error(value) + } +} + impl<'lua> IntoLua<'lua> for Error { #[inline] fn into_lua(self, _: &'lua Lua) -> Result> { - Ok(Value::Error(self)) + Ok(self.into()) } } impl<'lua> FromLua<'lua> for Error { #[inline] - fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result { match value { Value::Error(err) => Ok(err), - val => Ok(Error::RuntimeError( - lua.coerce_string(val)? - .and_then(|s| Some(s.to_str().ok()?.to_owned())) - .unwrap_or_else(|| "".to_owned()), - )), + _ => Err(Error::FromLuaConversionError { from: value.type_name(), to: "error", message: None }), } } } +impl<'lua> From for Value<'lua> { + #[inline] + fn from(value: bool) -> Self { + Value::Boolean(value) + } +} + impl<'lua> IntoLua<'lua> for bool { #[inline] fn into_lua(self, _: &'lua Lua) -> Result> { - Ok(Value::Boolean(self)) + Ok(self.into()) } } impl<'lua> FromLua<'lua> for bool { #[inline] - fn from_lua(v: Value<'lua>, _: &'lua Lua) -> Result { - match v { + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result { + match value { Value::Nil => Ok(false), Value::Boolean(b) => Ok(b), - _ => Ok(true), + _ => Err(Error::FromLuaConversionError { from: value.type_name(), to: "boolean", message: None }), } } } +impl<'lua> From for Value<'lua> { + #[inline] + fn from(value: LightUserData) -> Self { + Value::LightUserData(value) + } +} + + impl<'lua> IntoLua<'lua> for LightUserData { #[inline] fn into_lua(self, _: &'lua Lua) -> Result> { - Ok(Value::LightUserData(self)) + Ok(self.into()) } } @@ -292,6 +346,15 @@ impl<'lua> FromLua<'lua> for LightUserData { } } +#[cfg(feature = "luau")] +impl<'lua> From for Value<'lua> { + #[inline] + fn from(value: crate::types::Vector) -> Self { + Value::Vector(value) + } +} + + #[cfg(feature = "luau")] impl<'lua> IntoLua<'lua> for crate::types::Vector { #[inline] @@ -325,16 +388,8 @@ impl<'lua> IntoLua<'lua> for StdString { impl<'lua> FromLua<'lua> for StdString { #[inline] fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { - let ty = value.type_name(); - Ok(lua - .coerce_string(value)? - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: "String", - message: Some("expected string or number".to_string()), - })? - .to_str()? - .to_owned()) + let s = String::from_lua(value, lua)?; + Ok(s.to_str()?.to_owned()) } } @@ -362,17 +417,7 @@ impl<'lua> IntoLua<'lua> for Box { impl<'lua> FromLua<'lua> for Box { #[inline] fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { - let ty = value.type_name(); - Ok(lua - .coerce_string(value)? - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: "Box", - message: Some("expected string or number".to_string()), - })? - .to_str()? - .to_owned() - .into_boxed_str()) + StdString::from_lua(value, lua).map(|s| s.into_boxed_str()) } } @@ -386,23 +431,15 @@ impl<'lua> IntoLua<'lua> for CString { impl<'lua> FromLua<'lua> for CString { #[inline] fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { - let ty = value.type_name(); - let string = lua - .coerce_string(value)? - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, + let s = String::from_lua(value, lua)?; + match CStr::from_bytes_with_nul(s.as_bytes_with_nul()) { + Ok(s) => Ok(s.to_owned()), + Err(e) => Err(Error::FromLuaConversionError { + from: "string", to: "CString", - message: Some("expected string or number".to_string()), - })?; - - match CStr::from_bytes_with_nul(string.as_bytes_with_nul()) { - Ok(s) => Ok(s.into()), - Err(_) => Err(Error::FromLuaConversionError { - from: ty, - to: "CString", - message: Some("invalid C-style string".to_string()), + message: Some(e.to_string()), }), - } + } } } @@ -430,17 +467,8 @@ impl<'lua> IntoLua<'lua> for BString { impl<'lua> FromLua<'lua> for BString { #[inline] fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { - let ty = value.type_name(); - Ok(BString::from( - lua.coerce_string(value)? - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: "String", - message: Some("expected string or number".to_string()), - })? - .as_bytes() - .to_vec(), - )) + let s = String::from_lua(value, lua)?; + Ok(BString::from(s.as_bytes().to_vec())) } } @@ -451,9 +479,20 @@ impl<'lua> IntoLua<'lua> for &BStr { } } +macro_rules! lua_convert_int_infallible { + ($($x:ty),*) => { + $(impl<'lua> From<$x> for Value<'lua> { + #[inline] + fn from(value: $x) -> Self { + Self::Integer(value.into()) + } + })* + } +} + macro_rules! lua_convert_int { - ($x:ty) => { - impl<'lua> IntoLua<'lua> for $x { + ($($x:ty),*) => { + $(impl<'lua> IntoLua<'lua> for $x { #[inline] fn into_lua(self, _: &'lua Lua) -> Result> { cast(self) @@ -470,53 +509,32 @@ macro_rules! lua_convert_int { impl<'lua> FromLua<'lua> for $x { #[inline] - fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { - let ty = value.type_name(); + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result { (match value { Value::Integer(i) => cast(i), Value::Number(n) => cast(n), - _ => { - if let Some(i) = lua.coerce_integer(value.clone())? { - cast(i) - } else { - cast(lua.coerce_number(value)?.ok_or_else(|| { - Error::FromLuaConversionError { - from: ty, - to: stringify!($x), - message: Some( - "expected number or string coercible to number".to_string(), - ), - } - })?) - } - } + _ => return Err(Error::FromLuaConversionError { + from: value.type_name(), + to: stringify!($x), + message: None, + }), }) .ok_or_else(|| Error::FromLuaConversionError { - from: ty, + from: value.type_name(), to: stringify!($x), message: Some("out of range".to_owned()), }) } - } + })* }; } -lua_convert_int!(i8); -lua_convert_int!(u8); -lua_convert_int!(i16); -lua_convert_int!(u16); -lua_convert_int!(i32); -lua_convert_int!(u32); -lua_convert_int!(i64); -lua_convert_int!(u64); -lua_convert_int!(i128); -lua_convert_int!(u128); -lua_convert_int!(isize); -lua_convert_int!(usize); +lua_convert_int!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize); +lua_convert_int_infallible!(i8, u8, i16, u16, i32); macro_rules! lua_convert_float { - ($x:ty) => { - impl<'lua> IntoLua<'lua> for $x { + ($($x:ty),*) => { + $(impl<'lua> IntoLua<'lua> for $x { #[inline] fn into_lua(self, _: &'lua Lua) -> Result> { cast(self) @@ -531,28 +549,27 @@ macro_rules! lua_convert_float { impl<'lua> FromLua<'lua> for $x { #[inline] - fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result { - let ty = value.type_name(); - lua.coerce_number(value)? - .ok_or_else(|| Error::FromLuaConversionError { - from: ty, + fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result { + (match value { + Value::Integer(i) => cast(i), + Value::Number(n) => cast(n), + _ => return Err(Error::FromLuaConversionError { + from: value.type_name(), to: stringify!($x), - message: Some("expected number or string coercible to number".to_string()), - }) - .and_then(|n| { - cast(n).ok_or_else(|| Error::FromLuaConversionError { - from: ty, - to: stringify!($x), - message: Some("number out of range".to_string()), - }) - }) + message: None, + }), + }) + .ok_or_else(|| Error::FromLuaConversionError { + from: value.type_name(), + to: stringify!($x), + message: Some("out of range".to_owned()), + }) } - } + })* }; } -lua_convert_float!(f32); -lua_convert_float!(f64); +lua_convert_float!(f32, f64); impl<'lua, T> IntoLua<'lua> for &[T] where diff --git a/src/ffi.rs b/src/ffi.rs new file mode 100644 index 0000000..29af8a4 --- /dev/null +++ b/src/ffi.rs @@ -0,0 +1,8 @@ +pub use ::ffi::*; + +use crate::util::{push_gc_userdata, WrappedFailure}; + +#[inline] +pub unsafe fn mlua_pusherror(state: *mut lua_State, err: crate::Error) -> crate::Result<()> { + push_gc_userdata(state, WrappedFailure::Error(err), false) +} diff --git a/src/function.rs b/src/function.rs index 0dac0e1..de20570 100644 --- a/src/function.rs +++ b/src/function.rs @@ -83,6 +83,10 @@ pub struct CoverageInfo { } impl<'lua> Function<'lua> { + pub fn as_raw_ref(&self) -> &LuaRef<'lua> { + &self.0 + } + /// Calls the function, passing `args` as function arguments. /// /// The function's return values are converted to the generic type `R`. diff --git a/src/lib.rs b/src/lib.rs index 023bd21..17d4cf0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,6 +82,7 @@ mod macros; mod chunk; mod conversion; mod error; +pub mod ffi; mod function; mod hook; mod lua; @@ -103,7 +104,7 @@ mod value; pub mod prelude; -pub use ffi::{lua_CFunction, lua_State}; +pub use self::ffi::{lua_CFunction, lua_State}; pub use crate::chunk::{AsChunk, Chunk, ChunkMode}; pub use crate::error::{Error, ErrorContext, ExternalError, ExternalResult, Result}; diff --git a/src/lua.rs b/src/lua.rs index 02c3fbd..0ed0cf1 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -1558,6 +1558,7 @@ impl Lua { /// /// # Safety /// This function is unsafe because provides a way to execute unsafe C function. + #[inline] pub unsafe fn create_c_function(&self, func: ffi::lua_CFunction) -> Result { let state = self.state(); check_stack(state, 1)?; @@ -2281,7 +2282,7 @@ impl Lua { extra.app_data.remove() } - // Uses 2 stack spaces, does not call checkstack + /// Uses 2 stack spaces, does not call checkstack pub(crate) unsafe fn push_value(&self, value: Value) -> Result<()> { let state = self.state(); match value { @@ -2342,7 +2343,7 @@ impl Lua { Ok(()) } - // Uses 2 stack spaces, does not call checkstack + /// Uses 2 stack spaces, does not call checkstack pub(crate) unsafe fn pop_value(&self) -> Value { let state = self.state(); match ffi::lua_type(state, -1) { @@ -2798,8 +2799,7 @@ impl Lua { ))] unsafe { if !(*self.extra.get()).libs.contains(StdLib::COROUTINE) { - load_from_std_lib(self.main_state, StdLib::COROUTINE)?; - (*self.extra.get()).libs |= StdLib::COROUTINE; + return Err(Error::RuntimeError("StdLib::COROUTINE is not loaded".to_owned())); } } diff --git a/src/macros.rs b/src/macros.rs index 38c7726..143a4c8 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -69,14 +69,23 @@ macro_rules! mlua_debug_assert { }; } +#[cfg(debug_assertions)] macro_rules! mlua_expect { - ($res:expr, $msg:expr) => { + ($res:expr, $msg:expr $(,)?) => { $res.expect(bug_msg!($msg)) }; +} - ($res:expr, $msg:expr,) => { - mlua_expect!($res, $msg) - }; +#[cfg(not(debug_assertions))] +macro_rules! mlua_expect { + ($res:expr, $msg:expr $(,)?) => {{ + let x; + #[allow(unused_unsafe)] + { + x = unsafe { $res.into_iter().next().unwrap_unchecked() }; + } + x + }}; } #[cfg(feature = "module")] diff --git a/src/string.rs b/src/string.rs index 9a75cf5..5ef5f0e 100644 --- a/src/string.rs +++ b/src/string.rs @@ -41,6 +41,10 @@ impl OwnedString { } impl<'lua> String<'lua> { + pub fn as_raw_ref(&self) -> &LuaRef<'lua> { + &self.0 + } + /// Get a `&str` slice if the Lua string is valid UTF-8. /// /// # Examples @@ -139,8 +143,7 @@ impl<'lua> String<'lua> { /// Typically this function is used only for hashing and debug information. #[inline] pub fn to_pointer(&self) -> *const c_void { - let ref_thread = self.0.lua.ref_thread(); - unsafe { ffi::lua_topointer(ref_thread, self.0.index) } + self.0.to_pointer() } /// Convert this handle to owned version. diff --git a/src/table.rs b/src/table.rs index 6faaae7..dd7bfc4 100644 --- a/src/table.rs +++ b/src/table.rs @@ -46,6 +46,10 @@ impl OwnedTable { } impl<'lua> Table<'lua> { + pub fn as_raw_ref(&self) -> &LuaRef<'lua> { + &self.0 + } + /// Sets a key-value pair in the table. /// /// If the value is `nil`, this will effectively remove the pair. @@ -588,6 +592,7 @@ impl<'lua> Table<'lua> { /// Requires `feature = "luau"` #[cfg(any(feature = "luau", doc))] #[cfg_attr(docsrs, doc(cfg(feature = "luau")))] + #[inline] pub fn set_readonly(&self, enabled: bool) { let ref_thread = self.0.lua.ref_thread(); unsafe { @@ -599,11 +604,22 @@ impl<'lua> Table<'lua> { } } + #[inline] + pub fn set_safe(&self, enabled: bool) { + let ref_thread = self.0.lua.ref_thread(); + let enabled = enabled as _; + unsafe { + ffi::lua_setreadonly(ref_thread, self.0.index, enabled); + ffi::lua_setsafeenv(ref_thread, self.0.index, enabled); + } + } + /// Returns `readonly` attribute of the table. /// /// Requires `feature = "luau"` #[cfg(any(feature = "luau", doc))] #[cfg_attr(docsrs, doc(cfg(feature = "luau")))] + #[inline] pub fn is_readonly(&self) -> bool { let ref_thread = self.0.lua.ref_thread(); unsafe { ffi::lua_getreadonly(ref_thread, self.0.index) != 0 } @@ -617,8 +633,7 @@ impl<'lua> Table<'lua> { /// Typically this function is used only for hashing and debug information. #[inline] pub fn to_pointer(&self) -> *const c_void { - let ref_thread = self.0.lua.ref_thread(); - unsafe { ffi::lua_topointer(ref_thread, self.0.index) } + self.0.to_pointer() } /// Convert this handle to owned version. diff --git a/src/thread.rs b/src/thread.rs index 44fa860..ccc38eb 100644 --- a/src/thread.rs +++ b/src/thread.rs @@ -73,6 +73,10 @@ pub struct AsyncThread<'lua, R> { } impl<'lua> Thread<'lua> { + pub fn as_raw_ref(&self) -> &LuaRef<'lua> { + &self.0 + } + /// Resumes execution of this thread. /// /// Equivalent to `coroutine.resume`. @@ -88,6 +92,8 @@ impl<'lua> Thread<'lua> { /// If the thread calls `coroutine.yield`, returns the values passed to `yield`. If the thread /// `return`s values from its main function, returns those. /// + /// Also returns `true` if the coroutine is yielded. + /// /// # Examples /// /// ``` @@ -114,7 +120,7 @@ impl<'lua> Thread<'lua> { /// # Ok(()) /// # } /// ``` - pub fn resume(&self, args: A) -> Result + pub fn resume(&self, args: A) -> Result<(bool, R)> where A: IntoLuaMulti<'lua>, R: FromLuaMulti<'lua>, @@ -124,7 +130,7 @@ impl<'lua> Thread<'lua> { let mut args = args.into_lua_multi(lua)?; let nargs = args.len() as c_int; - let results = unsafe { + let (yielded, results) = unsafe { let _sg = StackGuard::new(state); check_stack(state, cmp::max(nargs + 1, 3))?; @@ -164,9 +170,9 @@ impl<'lua> Thread<'lua> { for _ in 0..nresults { results.push_front(lua.pop_value()); } - results + (ret == ffi::LUA_YIELD, results) }; - R::from_lua_multi(results, lua) + R::from_lua_multi(results, lua).map(|result| (yielded, result)) } /// Gets the status of the thread. @@ -428,9 +434,9 @@ where // This is safe as we are not moving the whole struct let this = unsafe { self.get_unchecked_mut() }; let ret: MultiValue = if let Some(args) = this.args0.take() { - this.thread.resume(args?)? + this.thread.resume(args?)?.1 } else { - this.thread.resume(())? + this.thread.resume(())?.1 }; if is_poll_pending(&ret) { @@ -462,9 +468,9 @@ where // This is safe as we are not moving the whole struct let this = unsafe { self.get_unchecked_mut() }; let ret: MultiValue = if let Some(args) = this.args0.take() { - this.thread.resume(args?)? + this.thread.resume(args?)?.1 } else { - this.thread.resume(())? + this.thread.resume(())?.1 }; if is_poll_pending(&ret) { diff --git a/src/types.rs b/src/types.rs index a272249..7541c87 100644 --- a/src/types.rs +++ b/src/types.rs @@ -273,7 +273,7 @@ impl RegistryKey { } } -pub(crate) struct LuaRef<'lua> { +pub struct LuaRef<'lua> { pub(crate) lua: &'lua Lua, pub(crate) index: c_int, pub(crate) drop: bool, @@ -296,6 +296,12 @@ impl<'lua> LuaRef<'lua> { mem::forget(self); owned_ref } + + #[inline] + pub fn to_pointer(&self) -> *const std::os::raw::c_void { + let ref_thread = self.lua.ref_thread(); + unsafe { ffi::lua_topointer(ref_thread, self.index) } + } } impl<'lua> fmt::Debug for LuaRef<'lua> { diff --git a/src/userdata.rs b/src/userdata.rs index d2209ef..11f7d37 100644 --- a/src/userdata.rs +++ b/src/userdata.rs @@ -806,6 +806,10 @@ impl OwnedAnyUserData { } impl<'lua> AnyUserData<'lua> { + pub fn as_raw_ref(&self) -> &LuaRef<'lua> { + &self.0 + } + /// Checks whether the type of this userdata is `T`. pub fn is(&self) -> bool { match self.inspect(|_: &UserDataCell| Ok(())) { diff --git a/src/util/mod.rs b/src/util/mod.rs index b497032..e806cc7 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -360,6 +360,7 @@ pub unsafe fn take_userdata(state: *mut ffi::lua_State) -> T { // Pushes the userdata and attaches a metatable with __gc method. // Internally uses 3 stack spaces, does not call checkstack. +#[inline] pub unsafe fn push_gc_userdata( state: *mut ffi::lua_State, t: T, @@ -399,7 +400,7 @@ pub unsafe fn get_gc_userdata( } unsafe extern "C" fn lua_error_impl(state: *mut ffi::lua_State) -> c_int { - ffi::lua_error(state); + ffi::lua_error(state) } unsafe extern "C" fn lua_isfunction_impl(state: *mut ffi::lua_State) -> c_int { @@ -629,6 +630,7 @@ pub unsafe extern "C" fn userdata_destructor(state: *mut ffi::lua_State) -> c // This function uses some of the bottom of the stack for error handling, the given callback will be // given the number of arguments available as an argument, and should return the number of returns // as normal, but cannot assume that the arguments available start at 0. +#[inline] pub unsafe fn callback_error(state: *mut ffi::lua_State, f: F) -> R where F: FnOnce(c_int) -> Result, @@ -851,6 +853,7 @@ pub unsafe fn init_gc_metatable( Ok(()) } +#[inline] pub unsafe fn get_gc_metatable(state: *mut ffi::lua_State) { let type_id = TypeId::of::(); let ref_addr = diff --git a/src/value.rs b/src/value.rs index f363eb5..a1c8de4 100644 --- a/src/value.rs +++ b/src/value.rs @@ -116,18 +116,14 @@ impl<'lua> Value<'lua> { /// Typically this function is used only for hashing and debug information. #[inline] pub fn to_pointer(&self) -> *const c_void { - unsafe { - match self { - Value::LightUserData(ud) => ud.0, - Value::Table(t) => t.to_pointer(), - Value::String(s) => s.to_pointer(), - Value::Function(Function(r)) - | Value::Thread(Thread(r)) - | Value::UserData(AnyUserData(r)) => { - ffi::lua_topointer(r.lua.ref_thread(), r.index) - } - _ => ptr::null(), - } + match self { + Value::LightUserData(ud) => ud.0, + Value::Table(Table(r)) + | Value::String(String(r)) + | Value::Function(Function(r)) + | Value::Thread(Thread(r)) + | Value::UserData(AnyUserData(r)) => r.to_pointer(), + _ => ptr::null(), } }