diff options
author | kyren <kerriganw@gmail.com> | 2018-01-26 20:06:18 -0500 |
---|---|---|
committer | kyren <kerriganw@gmail.com> | 2018-01-26 20:06:18 -0500 |
commit | 8527266d3b91c17919a576ea3848fdec058afa85 (patch) | |
tree | a1d2176980f4680e55d1f28b2a3c61043b7d8cf9 | |
parent | 0801104762cda684e5728df386cd3962fb0fe3bc (diff) | |
download | mlua-8527266d3b91c17919a576ea3848fdec058afa85.zip |
Add an API that exposes the functionality of `lua_getuservalue` and `lua_setuservalue`
-rw-r--r-- | src/ffi.rs | 3 | ||||
-rw-r--r-- | src/userdata.rs | 50 |
2 files changed, 52 insertions, 1 deletions
@@ -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"); + } } |