diff --git a/hlua/src/any.rs b/hlua/src/any.rs index cddb39e..1044742 100644 --- a/hlua/src/any.rs +++ b/hlua/src/any.rs @@ -64,7 +64,7 @@ impl<'lua, L> Push for AnyLuaValue // We also need to destroy and recreate the push guard, otherwise the type parameter // doesn't match. - let size = val.push_no_err(&mut lua as &mut AsMutLua<'lua>).forget(); + let size = val.push_no_err(&mut lua as &mut AsMutLua<'lua>).forget_internal(); Ok(PushGuard { lua: lua, @@ -149,7 +149,7 @@ impl<'lua, L> Push for AnyHashableLuaValue // We also need to destroy and recreate the push guard, otherwise the type parameter // doesn't match. - let size = val.push_no_err(&mut lua as &mut AsMutLua<'lua>).forget(); + let size = val.push_no_err(&mut lua as &mut AsMutLua<'lua>).forget_internal(); Ok(PushGuard { lua: lua, diff --git a/hlua/src/functions_write.rs b/hlua/src/functions_write.rs index 47bf84d..a8e9145 100644 --- a/hlua/src/functions_write.rs +++ b/hlua/src/functions_write.rs @@ -69,7 +69,7 @@ impl_function!(function10, A, B, C, D, E, F, G, H, I, J); /// ``` /// use hlua::Lua; /// let mut lua = Lua::new(); -/// +/// /// lua.set("foo", hlua::function1(move |a: i32| -> i32 { /// a * 5 /// })); @@ -106,7 +106,7 @@ impl_function!(function10, A, B, C, D, E, F, G, H, I, J); /// ``` /// use hlua::Lua; /// let mut lua = Lua::new(); -/// +/// /// lua.set("values", hlua::function0(move || -> (i32, i32, i32) { /// (12, 24, 48) /// })); @@ -130,7 +130,7 @@ impl_function!(function10, A, B, C, D, E, F, G, H, I, J); /// use hlua::Lua; /// let mut lua = Lua::new(); /// lua.openlibs(); -/// +/// /// lua.set("err", hlua::function0(move || -> Result { /// Err("something wrong happened") /// })); @@ -287,7 +287,7 @@ macro_rules! impl_function_ext { // without going through the RFC process. { match "__gc".push_to_lua(&mut lua) { - Ok(p) => p.forget(), + Ok(p) => p.forget_internal(), Err(_) => unreachable!(), }; @@ -399,7 +399,7 @@ extern "C" fn wrapper(lua: *mut ffi::lua_State) -> libc::c_int Err(_) => { let err_msg = format!("wrong parameter types for callback function"); match err_msg.push_to_lua(&mut tmp_lua) { - Ok(p) => p.forget(), + Ok(p) => p.forget_internal(), Err(_) => unreachable!(), }; unsafe { @@ -414,7 +414,7 @@ extern "C" fn wrapper(lua: *mut ffi::lua_State) -> libc::c_int // pushing back the result of the function on the stack let nb = match ret_value.push_to_lua(&mut tmp_lua) { - Ok(p) => p.forget(), + Ok(p) => p.forget_internal(), Err(_) => panic!(), // TODO: wrong }; nb as libc::c_int diff --git a/hlua/src/lib.rs b/hlua/src/lib.rs index 9e07c5f..46a7f5b 100644 --- a/hlua/src/lib.rs +++ b/hlua/src/lib.rs @@ -170,16 +170,45 @@ pub struct PushGuard { impl<'lua, L> PushGuard where L: AsMutLua<'lua> { + /// Creates a new `PushGuard` from this Lua context representing `size` items on the stack. + /// When this `PushGuard` is destroyed, `size` items will be popped. + /// + /// This is unsafe because the Lua stack can be corrupted if this is misused. + #[inline] + pub unsafe fn new(mut lua: L, size: i32) -> Self { + let raw_lua = lua.as_mut_lua(); + PushGuard { + lua, + size, + raw_lua, + } + } + #[inline] fn assert_one_and_forget(self) -> i32 { assert_eq!(self.size, 1); - self.forget() + self.forget_internal() } - /// Prevents the value from being poped when the `PushGuard` is destroyed, and returns the - /// number of elements on the stack. + /// Returns the number of elements managed by this `PushGuard`. #[inline] - fn forget(mut self) -> i32 { + pub fn size(&self) -> i32 { + self.size + } + + /// Prevents the value from being popped when the `PushGuard` is destroyed, and returns the + /// number of elements on the Lua stack. + /// + /// This is unsafe because the Lua stack can be corrupted if this is misused. + #[inline] + pub unsafe fn forget(self) -> i32 { + self.forget_internal() + } + + /// Internal crate-only version of `forget`. It is generally assumed that code within this + /// crate that calls this method knows what it is doing. + #[inline] + fn forget_internal(mut self) -> i32 { let size = self.size; self.size = 0; size diff --git a/hlua/src/lua_functions.rs b/hlua/src/lua_functions.rs index 4d1e1dc..0bd28cf 100644 --- a/hlua/src/lua_functions.rs +++ b/hlua/src/lua_functions.rs @@ -264,7 +264,7 @@ impl<'lua, L> LuaFunction // lua_pcall pops the function, so we have to make a copy of it ffi::lua_pushvalue(self.variable.as_mut_lua().0, -1); let num_pushed = match args.push_to_lua(self) { - Ok(g) => g.forget(), + Ok(g) => g.forget_internal(), Err((err, _)) => return Err(LuaFunctionCallError::PushError(err)), }; let pcall_return_value = ffi::lua_pcall(self.variable.as_mut_lua().0, num_pushed, 1, 0); // TODO: num ret values diff --git a/hlua/src/rust_tables.rs b/hlua/src/rust_tables.rs index 07ccc63..5a38f26 100644 --- a/hlua/src/rust_tables.rs +++ b/hlua/src/rust_tables.rs @@ -23,7 +23,7 @@ fn push_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result, for (elem, index) in iterator.zip((1..)) { let size = match elem.push_to_lua(&mut lua) { - Ok(pushed) => pushed.forget(), + Ok(pushed) => pushed.forget_internal(), Err((_err, _lua)) => panic!(), // TODO: wrong return Err((err, lua)), // FIXME: destroy the temporary table }; @@ -32,7 +32,7 @@ fn push_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result, 1 => { let index = index as u32; match index.push_to_lua(&mut lua) { - Ok(pushed) => pushed.forget(), + Ok(pushed) => pushed.forget_internal(), Err(_) => unreachable!(), }; unsafe { ffi::lua_insert(lua.as_mut_lua().0, -2) } @@ -64,7 +64,7 @@ fn push_rec_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result pushed.forget(), + Ok(pushed) => pushed.forget_internal(), Err((_err, _lua)) => panic!(), // TODO: wrong return Err((err, lua)), // FIXME: destroy the temporary table }; diff --git a/hlua/src/tuples.rs b/hlua/src/tuples.rs index 2b78b60..95cab9e 100644 --- a/hlua/src/tuples.rs +++ b/hlua/src/tuples.rs @@ -45,7 +45,7 @@ macro_rules! tuple_impl { let mut total = 0; let first_err = match $first.push_to_lua(&mut lua) { - Ok(pushed) => { total += pushed.forget(); None }, + Ok(pushed) => { total += pushed.forget_internal(); None }, Err((err, _)) => Some(err), }; @@ -55,7 +55,7 @@ macro_rules! tuple_impl { let rest = ($($other,)+); let other_err = match rest.push_to_lua(&mut lua) { - Ok(pushed) => { total += pushed.forget(); None }, + Ok(pushed) => { total += pushed.forget_internal(); None }, Err((err, _)) => Some(err), };