Skip to content

Commit ee6fa80

Browse files
committed
Add Value::weak_lua helper
Close #714
1 parent 30b04f1 commit ee6fa80

8 files changed

Lines changed: 112 additions & 5 deletions

File tree

‎src/buffer.rs‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::io;
33
#[cfg(feature = "serde")]
44
use serde::ser::{Serialize, Serializer};
55

6-
use crate::state::RawLua;
6+
use crate::state::{RawLua, WeakLua};
77
use crate::types::ValueRef;
88

99
/// A Luau buffer type.
@@ -72,6 +72,13 @@ impl Buffer {
7272
BufferCursor(self, 0)
7373
}
7474

75+
/// Returns a weak reference to the Lua instance owning this value.
76+
#[doc(hidden)]
77+
#[inline]
78+
pub fn weak_lua(&self) -> &WeakLua {
79+
&self.0.lua
80+
}
81+
7582
pub(crate) fn as_slice(&self, lua: &RawLua) -> &[u8] {
7683
unsafe {
7784
let (buf, size) = self.as_raw_parts(lua);

‎src/function.rs‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ use std::result::Result as StdResult;
7979
use std::{mem, ptr, slice};
8080

8181
use crate::error::{Error, ExternalError, ExternalResult, Result};
82-
use crate::state::Lua;
82+
use crate::state::{Lua, WeakLua};
8383
use crate::table::Table;
8484
use crate::traits::{FromLuaMulti, IntoLua, IntoLuaMulti};
8585
use crate::types::{Callback, LuaType, MaybeSend, ValueRef};
@@ -607,6 +607,13 @@ impl Function {
607607
self.0.to_pointer()
608608
}
609609

610+
/// Returns a weak reference to the Lua instance owning this value.
611+
#[doc(hidden)]
612+
#[inline]
613+
pub fn weak_lua(&self) -> &WeakLua {
614+
&self.0.lua
615+
}
616+
610617
/// Creates a deep clone of the Lua function.
611618
///
612619
/// Copies the function prototype and all its upvalues to the

‎src/string.rs‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::os::raw::{c_int, c_void};
99
use std::{cmp, fmt, mem, slice, str};
1010

1111
use crate::error::{Error, Result};
12-
use crate::state::Lua;
12+
use crate::state::{Lua, WeakLua};
1313
use crate::traits::IntoLua;
1414
use crate::types::{LuaType, ValueRef};
1515
use crate::value::Value;
@@ -154,6 +154,13 @@ impl LuaString {
154154
let lua = self.0.lua.lock();
155155
unsafe { ffi::lua_tostring(lua.ref_thread(), self.0.index) as *const c_void }
156156
}
157+
158+
/// Returns a weak reference to the Lua instance owning this value.
159+
#[doc(hidden)]
160+
#[inline]
161+
pub fn weak_lua(&self) -> &WeakLua {
162+
&self.0.lua
163+
}
157164
}
158165

159166
impl fmt::Debug for LuaString {

‎src/table.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,13 @@ impl Table {
795795
self.0.to_pointer()
796796
}
797797

798+
/// Returns a weak reference to the Lua instance owning this value.
799+
#[doc(hidden)]
800+
#[inline]
801+
pub fn weak_lua(&self) -> &WeakLua {
802+
&self.0.lua
803+
}
804+
798805
/// Returns an iterator over the pairs of the table.
799806
///
800807
/// This works like the Lua `pairs` function, but does not invoke the `__pairs` metamethod.

‎src/thread.rs‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use std::os::raw::{c_int, c_void};
4040

4141
use crate::error::{Error, Result};
4242
use crate::function::Function;
43-
use crate::state::RawLua;
43+
use crate::state::{RawLua, WeakLua};
4444
use crate::traits::{FromLuaMulti, IntoLuaMulti};
4545
use crate::types::{LuaType, ValueRef};
4646
use crate::util::{StackGuard, check_stack, error_traceback_thread, pop_error};
@@ -774,6 +774,13 @@ impl Thread {
774774
pub fn to_pointer(&self) -> *const c_void {
775775
self.0.to_pointer()
776776
}
777+
778+
/// Returns a weak reference to the Lua instance owning this value.
779+
#[doc(hidden)]
780+
#[inline]
781+
pub fn weak_lua(&self) -> &WeakLua {
782+
&self.0.lua
783+
}
777784
}
778785

779786
impl fmt::Debug for Thread {

‎src/userdata.rs‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::os::raw::{c_char, c_void};
1111
use crate::Either;
1212
use crate::error::{Error, Result};
1313
use crate::function::Function;
14-
use crate::state::Lua;
14+
use crate::state::{Lua, WeakLua};
1515
use crate::string::LuaString;
1616
use crate::table::{Table, TablePairs};
1717
use crate::traits::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti};
@@ -1028,6 +1028,13 @@ impl AnyUserData {
10281028
self.0.to_pointer()
10291029
}
10301030

1031+
/// Returns a weak reference to the Lua instance owning this value.
1032+
#[doc(hidden)]
1033+
#[inline]
1034+
pub fn weak_lua(&self) -> &WeakLua {
1035+
&self.0.lua
1036+
}
1037+
10311038
/// Returns [`TypeId`] of this userdata if it is registered and `'static`.
10321039
///
10331040
/// This method is not available for scoped userdata.

‎src/value.rs‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use num_traits::FromPrimitive;
77

88
use crate::error::{Error, Result};
99
use crate::function::Function;
10+
use crate::state::WeakLua;
1011
use crate::string::LuaString;
1112
use crate::table::Table;
1213
use crate::thread::Thread;
@@ -178,6 +179,25 @@ impl Value {
178179
}
179180
}
180181

182+
/// Returns a weak reference to the Lua instance owning this value.
183+
///
184+
/// Returns `None` for values without an associated Lua instance, such as primitive values
185+
/// and [`Value::Error`].
186+
#[inline]
187+
pub fn weak_lua(&self) -> Option<&WeakLua> {
188+
match self {
189+
Value::String(s) => Some(s.weak_lua()),
190+
Value::Table(t) => Some(t.weak_lua()),
191+
Value::Function(f) => Some(f.weak_lua()),
192+
Value::Thread(t) => Some(t.weak_lua()),
193+
Value::UserData(ud) => Some(ud.weak_lua()),
194+
#[cfg(feature = "luau")]
195+
Value::Buffer(b) => Some(b.weak_lua()),
196+
Value::Other(vref) => Some(&vref.lua),
197+
_ => None,
198+
}
199+
}
200+
181201
/// Returns `true` if the value is a [`Nil`].
182202
#[inline]
183203
pub fn is_nil(&self) -> bool {

‎tests/value.rs‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,51 @@ fn test_value_to_string() -> Result<()> {
237237
Ok(())
238238
}
239239

240+
#[test]
241+
fn test_value_weak_lua() -> Result<()> {
242+
let lua = Lua::new();
243+
let values = [
244+
Value::String(lua.create_string("hello")?),
245+
Value::Table(lua.create_table()?),
246+
Value::Function(lua.create_function(|_, ()| Ok(()))?),
247+
Value::Thread(lua.create_thread(lua.create_function(|_, ()| Ok(()))?)?),
248+
Value::UserData(lua.create_any_userdata(())?),
249+
#[cfg(feature = "luau")]
250+
Value::Buffer(lua.create_buffer(b"hello")?),
251+
];
252+
253+
for value in &values {
254+
let weak = value.weak_lua().expect("reference value has a Lua instance");
255+
assert!(weak == &lua.weak());
256+
let upgraded = weak.try_upgrade().expect("Lua instance is alive");
257+
upgraded.globals().set("weak_lua_test", true)?;
258+
assert!(lua.globals().get::<bool>("weak_lua_test")?);
259+
}
260+
261+
drop(lua);
262+
for value in &values {
263+
let weak = value
264+
.weak_lua()
265+
.expect("destroyed instance still has a weak handle");
266+
assert!(weak.try_upgrade().is_none());
267+
}
268+
269+
for value in [
270+
Value::Nil,
271+
Value::Boolean(true),
272+
Value::NULL,
273+
Value::Integer(1),
274+
Value::Number(1.0),
275+
Value::Error(Box::new(Error::runtime("test"))),
276+
#[cfg(feature = "luau")]
277+
Value::Vector(mlua::Vector::default()),
278+
] {
279+
assert!(value.weak_lua().is_none());
280+
}
281+
282+
Ok(())
283+
}
284+
240285
#[test]
241286
fn test_debug_format() -> Result<()> {
242287
let lua = Lua::new();

0 commit comments

Comments
 (0)