summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkyren <kerriganw@gmail.com>2018-01-26 20:06:18 -0500
committerkyren <kerriganw@gmail.com>2018-01-26 20:06:18 -0500
commit8527266d3b91c17919a576ea3848fdec058afa85 (patch)
treea1d2176980f4680e55d1f28b2a3c61043b7d8cf9
parent0801104762cda684e5728df386cd3962fb0fe3bc (diff)
downloadmlua-8527266d3b91c17919a576ea3848fdec058afa85.zip
Add an API that exposes the functionality of `lua_getuservalue` and `lua_setuservalue`
-rw-r--r--src/ffi.rs3
-rw-r--r--src/userdata.rs50
2 files changed, 52 insertions, 1 deletions
diff --git a/src/ffi.rs b/src/ffi.rs
index 713413c..9130afd 100644
--- a/src/ffi.rs
+++ b/src/ffi.rs
@@ -121,6 +121,9 @@ extern "C" {
pub fn lua_newuserdata(state: *mut lua_State, size: usize) -> *mut c_void;
pub fn lua_newthread(state: *mut lua_State) -> *mut lua_State;
+ pub fn lua_setuservalue(state: *mut lua_State, index: c_int);
+ pub fn lua_getuservalue(state: *mut lua_State, index: c_int) -> c_int;
+
pub fn lua_settable(state: *mut lua_State, index: c_int);
pub fn lua_rawset(state: *mut lua_State, index: c_int);
pub fn lua_setmetatable(state: *mut lua_State, index: c_int);
diff --git a/src/userdata.rs b/src/userdata.rs
index 8474a6a..3a995c1 100644
--- a/src/userdata.rs
+++ b/src/userdata.rs
@@ -7,7 +7,7 @@ use ffi;
use error::*;
use util::*;
use types::{Callback, LuaRef};
-use value::{FromLua, FromLuaMulti, ToLuaMulti};
+use value::{FromLua, FromLuaMulti, ToLua, ToLuaMulti};
use lua::Lua;
/// Kinds of metamethods that can be overridden.
@@ -393,6 +393,42 @@ impl<'lua> AnyUserData<'lua> {
})
}
}
+
+ /// Sets an associated value to this `AnyUserData`.
+ ///
+ /// The value may be any Lua value whatsoever, and can be retrieved with [`get_user_value`].
+ ///
+ /// [`get_user_value`]: #method.get_user_value
+ pub fn set_user_value<V: ToLua<'lua>>(&self, v: V) -> Result<()> {
+ let lua = self.0.lua;
+ unsafe {
+ stack_guard(lua.state, 0, || {
+ check_stack(lua.state, 2);
+ lua.push_ref(lua.state, &self.0);
+ lua.push_value(lua.state, v.to_lua(lua)?);
+ ffi::lua_setuservalue(lua.state, -2);
+ ffi::lua_pop(lua.state, 1);
+ Ok(())
+ })
+ }
+ }
+
+ /// Returns an associated value set by [`set_user_value`].
+ ///
+ /// [`set_user_value`]: #method.set_user_value
+ pub fn get_user_value<V: FromLua<'lua>>(&self) -> Result<V> {
+ let lua = self.0.lua;
+ unsafe {
+ stack_guard(lua.state, 0, || {
+ check_stack(lua.state, 2);
+ lua.push_ref(lua.state, &self.0);
+ ffi::lua_getuservalue(lua.state, -1);
+ let res = V::from_lua(lua.pop_value(lua.state), lua)?;
+ ffi::lua_pop(lua.state, 1);
+ Ok(res)
+ })
+ }
+ }
}
#[cfg(test)]
@@ -582,4 +618,16 @@ mod tests {
drop(lua); // should destroy all objects
assert_eq!(DROPPED.load(Ordering::SeqCst), true);
}
+
+ #[test]
+ fn user_value() {
+ let lua = Lua::new();
+
+ struct MyUserData;
+ impl UserData for MyUserData {}
+
+ let ud = lua.create_userdata(MyUserData).unwrap();
+ ud.set_user_value("hello").unwrap();
+ assert_eq!(ud.get_user_value::<String>().unwrap(), "hello");
+ }
}