From bcf2cbea3798504471d88345327671bf2da7e8e1 Mon Sep 17 00:00:00 2001 From: Alex Orlenko Date: Wed, 18 May 2022 13:15:08 +0100 Subject: [PATCH] Add `Value::to_pointer()` function. Closes #165 and #166. --- src/value.rs | 27 ++++++++++++++++++++++++++- tests/value.rs | 16 ++++++++++++---- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/value.rs b/src/value.rs index 9351c1d..96f36fc 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,5 +1,6 @@ use std::iter::{self, FromIterator}; -use std::{slice, str, vec}; +use std::os::raw::c_void; +use std::{ptr, slice, str, vec}; #[cfg(feature = "serialize")] use { @@ -9,6 +10,7 @@ use { }; use crate::error::{Error, Result}; +use crate::ffi; use crate::function::Function; use crate::lua::Lua; use crate::string::String; @@ -93,6 +95,29 @@ impl<'lua> Value<'lua> { _ => Ok(self == other.as_ref()), } } + + /// Converts the value to a generic C pointer. + /// + /// The value can be a userdata, a table, a thread, a string, or a function; otherwise it returns NULL. + /// Different objects will give different pointers. + /// There is no way to convert the pointer back to its original value. + /// + /// Typically this function is used only for hashing and debug information. + pub fn to_pointer(&self) -> *const c_void { + unsafe { + match self { + Value::LightUserData(ud) => ud.0, + Value::String(String(v)) + | Value::Table(Table(v)) + | Value::Function(Function(v)) + | Value::Thread(Thread(v)) + | Value::UserData(AnyUserData(v)) => v + .lua + .ref_thread_exec(|refthr| ffi::lua_topointer(refthr, v.index)), + _ => ptr::null(), + } + } + } } impl<'lua> PartialEq for Value<'lua> { diff --git a/tests/value.rs b/tests/value.rs index 9beb68c..2f9c1e7 100644 --- a/tests/value.rs +++ b/tests/value.rs @@ -1,3 +1,5 @@ +use std::ptr; + use mlua::{Lua, Result, Value}; #[test] @@ -41,17 +43,23 @@ fn test_value_eq() -> Result<()> { let thread2: Value = globals.get("thread2")?; assert!(table1 != table2); - assert!(table1.equals(table2)?); + assert!(table1.equals(&table2)?); assert!(string1 == string2); - assert!(string1.equals(string2)?); + assert!(string1.equals(&string2)?); assert!(num1 == num2); assert!(num1.equals(num2)?); assert!(num1 != num3); assert!(func1 == func2); assert!(func1 != func3); - assert!(!func1.equals(func3)?); + assert!(!func1.equals(&func3)?); assert!(thread1 == thread2); - assert!(thread1.equals(thread2)?); + assert!(thread1.equals(&thread2)?); + + assert!(!table1.to_pointer().is_null()); + assert!(!ptr::eq(table1.to_pointer(), table2.to_pointer())); + assert!(ptr::eq(string1.to_pointer(), string2.to_pointer())); + assert!(ptr::eq(func1.to_pointer(), func2.to_pointer())); + assert!(num1.to_pointer().is_null()); Ok(()) }