diff --git a/src/buffer.rs b/src/buffer.rs index d256c626..4552431e 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -4,6 +4,7 @@ use std::io; use serde::ser::{Serialize, Serializer}; use crate::state::RawLua; +use crate::traits::HasValueRef; use crate::types::ValueRef; /// A Luau buffer type. @@ -161,6 +162,12 @@ impl io::Seek for BufferCursor { } } +impl HasValueRef for Buffer { + fn to_vref(&self) -> &ValueRef { + &self.0 + } +} + #[cfg(feature = "serde")] impl Serialize for Buffer { fn serialize(&self, serializer: S) -> std::result::Result { diff --git a/src/function.rs b/src/function.rs index 8081ec9f..cb2118b5 100644 --- a/src/function.rs +++ b/src/function.rs @@ -81,7 +81,7 @@ use std::{mem, ptr, slice}; use crate::error::{Error, ExternalError, ExternalResult, Result}; use crate::state::Lua; use crate::table::Table; -use crate::traits::{FromLuaMulti, IntoLua, IntoLuaMulti}; +use crate::traits::{FromLuaMulti, HasValueRef, IntoLua, IntoLuaMulti}; use crate::types::{Callback, LuaType, MaybeSend, ValueRef}; use crate::util::{ StackGuard, assert_stack, check_stack, linenumber_to_usize, pop_error, ptr_to_lossy_str, ptr_to_str, @@ -749,6 +749,12 @@ impl IntoLua for WrappedAsyncFunction { } } +impl HasValueRef for Function { + fn to_vref(&self) -> &ValueRef { + &self.0 + } +} + impl LuaType for Function { const TYPE_ID: c_int = ffi::LUA_TFUNCTION; } diff --git a/src/string.rs b/src/string.rs index 18a40807..b40f9a0e 100644 --- a/src/string.rs +++ b/src/string.rs @@ -10,7 +10,7 @@ use std::{cmp, fmt, mem, slice, str}; use crate::error::{Error, Result}; use crate::state::Lua; -use crate::traits::IntoLua; +use crate::traits::{HasValueRef, IntoLua}; use crate::types::{LuaType, ValueRef}; use crate::value::Value; @@ -215,6 +215,12 @@ impl Hash for LuaString { } } +impl HasValueRef for LuaString { + fn to_vref(&self) -> &ValueRef { + &self.0 + } +} + #[cfg(feature = "serde")] impl Serialize for LuaString { fn serialize(&self, serializer: S) -> StdResult diff --git a/src/table.rs b/src/table.rs index e93610ff..59880ad9 100644 --- a/src/table.rs +++ b/src/table.rs @@ -159,7 +159,7 @@ use std::os::raw::c_void; use crate::error::{Error, Result}; use crate::function::Function; use crate::state::{LuaGuard, RawLua, WeakLua}; -use crate::traits::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, ObjectLike}; +use crate::traits::{FromLua, FromLuaMulti, HasValueRef, IntoLua, IntoLuaMulti, ObjectLike}; use crate::types::{Integer, ValueRef}; use crate::util::{StackGuard, assert_stack, check_stack, get_metatable_ptr}; use crate::value::{Nil, Value}; @@ -1226,6 +1226,12 @@ impl ObjectLike for Table { } } +impl HasValueRef for Table { + fn to_vref(&self) -> &ValueRef { + &self.0 + } +} + /// A wrapped [`Table`] with customized serialization behavior. #[cfg(feature = "serde")] pub(crate) struct SerializableTable<'a> { diff --git a/src/thread.rs b/src/thread.rs index 968be182..a9d61066 100644 --- a/src/thread.rs +++ b/src/thread.rs @@ -41,7 +41,7 @@ use std::os::raw::{c_int, c_void}; use crate::error::{Error, Result}; use crate::function::Function; use crate::state::RawLua; -use crate::traits::{FromLuaMulti, IntoLuaMulti}; +use crate::traits::{FromLuaMulti, HasValueRef, IntoLuaMulti}; use crate::types::{LuaType, ValueRef}; use crate::util::{StackGuard, check_stack, error_traceback_thread, pop_error}; @@ -769,6 +769,12 @@ impl fmt::Debug for Thread { } } +impl HasValueRef for Thread { + fn to_vref(&self) -> &ValueRef { + &self.0 + } +} + impl LuaType for Thread { const TYPE_ID: c_int = ffi::LUA_TTHREAD; } diff --git a/src/traits.rs b/src/traits.rs index 405a95f7..c3ae91a3 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -10,6 +10,7 @@ use crate::error::{Error, Result}; use crate::multi::MultiValue; use crate::private::Sealed; use crate::state::{Lua, RawLua, WeakLua}; +use crate::types::ValueRef; use crate::util::{check_stack, parse_lookup_path, short_type_name}; use crate::value::Value; @@ -249,6 +250,17 @@ pub trait ObjectLike: Sealed { fn weak_lua(&self) -> &WeakLua; } +/// A trait for types that have a [`ValueRef`]. +pub trait HasValueRef: Sized { + /// Convert to a [`ValueRef`]. + fn to_vref(&self) -> &ValueRef; +} + +pub trait MaybeHasValueRef: Sized { + /// Convert compatiable types to a [`ValueRef`]. + fn maybe_to_vref(&self) -> Option<&ValueRef>; +} + pub(crate) trait ShortTypeName { #[inline(always)] fn type_name() -> String { diff --git a/src/userdata.rs b/src/userdata.rs index 912efa22..3918c623 100644 --- a/src/userdata.rs +++ b/src/userdata.rs @@ -14,7 +14,7 @@ use crate::function::Function; use crate::state::Lua; use crate::string::LuaString; use crate::table::{Table, TablePairs}; -use crate::traits::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti}; +use crate::traits::{FromLua, FromLuaMulti, HasValueRef, IntoLua, IntoLuaMulti}; use crate::types::{MaybeSend, MaybeSync, ValueRef}; use crate::util::{StackGuard, check_stack, get_userdata, push_string, short_type_name, take_userdata}; use crate::value::Value; @@ -1121,6 +1121,12 @@ impl AnyUserData { } } +impl HasValueRef for AnyUserData { + fn to_vref(&self) -> &ValueRef { + &self.0 + } +} + impl fmt::Debug for AnyUserData { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { if fmt.alternate() { diff --git a/src/value.rs b/src/value.rs index d273dad7..3e3fe3f2 100644 --- a/src/value.rs +++ b/src/value.rs @@ -10,6 +10,7 @@ use crate::function::Function; use crate::string::LuaString; use crate::table::Table; use crate::thread::Thread; +use crate::traits::MaybeHasValueRef; use crate::types::{Integer, LightUserData, Number, ValueRef}; use crate::userdata::AnyUserData; use crate::util::{StackGuard, check_stack}; @@ -560,6 +561,33 @@ impl Value { } } +impl MaybeHasValueRef for Value { + fn maybe_to_vref(&self) -> Option<&ValueRef> { + #[cfg(feature = "luau")] + use crate::buffer::Buffer; + // Don't use the `_` pattern, as may be over looking in the future causing compatiable types to + // return `None`. + match self { + Self::Nil => None, + Self::Boolean(_) => None, + Self::LightUserData(_) => None, + Self::Error(_) => None, + Self::Function(Function(vref)) => Some(vref), + Self::Integer(_) => None, + Self::Number(_) => None, + Self::String(LuaString(vref)) => Some(vref), + Self::Table(Table(vref)) => Some(vref), + Self::Thread(Thread(vref, _)) => Some(vref), + #[cfg(feature = "luau")] + Self::Buffer(Buffer(vref)) => Some(vref), + #[cfg(feature = "luau")] + Self::Vector(_) => None, + Self::UserData(AnyUserData(vref)) => Some(vref), + Self::Other(vref) => Some(vref), + } + } +} + impl fmt::Debug for Value { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { if fmt.alternate() {