summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Orlenko <zxteam@protonmail.com>2024-06-02 00:51:24 +0100
committerAlex Orlenko <zxteam@protonmail.com>2024-06-24 22:46:59 +0100
commitdc12da49d6216fe280b1cf511172ffad508ac44d (patch)
tree0b53b66965f42b5c8e4cae8d7abb87844009408a
parentfc9475b4959ce23e3bb420b42a95543e4f55bac2 (diff)
downloadmlua-dc12da49d6216fe280b1cf511172ffad508ac44d.zip
Refactor: WIP
-rw-r--r--Cargo.toml4
-rw-r--r--benches/benchmark.rs6
-rw-r--r--examples/guided_tour.rs7
-rw-r--r--mlua_derive/src/from_lua.rs4
-rw-r--r--mlua_derive/src/lib.rs17
-rw-r--r--src/chunk.rs66
-rw-r--r--src/conversion.rs447
-rw-r--r--src/function.rs158
-rw-r--r--src/hook.rs25
-rw-r--r--src/lib.rs18
-rw-r--r--src/lua.rs1351
-rw-r--r--src/multi.rs79
-rw-r--r--src/prelude.rs7
-rw-r--r--src/serde/de.rs59
-rw-r--r--src/serde/mod.rs13
-rw-r--r--src/serde/ser.rs155
-rw-r--r--src/string.rs91
-rw-r--r--src/table.rs262
-rw-r--r--src/thread.rs172
-rw-r--r--src/types.rs137
-rw-r--r--src/userdata.rs550
-rw-r--r--src/userdata_cell.rs410
-rw-r--r--src/userdata_ext.rs50
-rw-r--r--src/userdata_impl.rs784
-rw-r--r--src/value.rs169
-rw-r--r--tests/async.rs22
-rw-r--r--tests/conversion.rs116
-rw-r--r--tests/function.rs42
-rw-r--r--tests/scope.rs.1 (renamed from tests/scope.rs)0
-rw-r--r--tests/serde.rs86
-rw-r--r--tests/static.rs4
-rw-r--r--tests/string.rs19
-rw-r--r--tests/table.rs14
-rw-r--r--tests/thread.rs31
-rw-r--r--tests/userdata.rs58
35 files changed, 2507 insertions, 2926 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 0a6aee7..2ab5540 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "mlua"
-version = "0.9.9" # remember to update mlua_derive
+version = "0.10.0" # remember to update mlua_derive
authors = ["Aleksandr Orlenko <zxteam@pm.me>", "kyren <catherine@kyju.org>"]
rust-version = "1.71"
edition = "2021"
@@ -53,7 +53,7 @@ futures-util = { version = "0.3", optional = true, default-features = false, fea
serde = { version = "1.0", optional = true }
erased-serde = { version = "0.4", optional = true }
serde-value = { version = "0.7", optional = true }
-parking_lot = { version = "0.12" }
+parking_lot = { version = "0.12", features = ["arc_lock"] }
ffi = { package = "mlua-sys", version = "0.6.1", path = "mlua-sys" }
diff --git a/benches/benchmark.rs b/benches/benchmark.rs
index f8352e0..b0a0fbb 100644
--- a/benches/benchmark.rs
+++ b/benches/benchmark.rs
@@ -305,7 +305,7 @@ fn userdata_create(c: &mut Criterion) {
fn userdata_call_index(c: &mut Criterion) {
struct UserData(#[allow(unused)] i64);
impl LuaUserData for UserData {
- fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: LuaUserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_meta_method(LuaMetaMethod::Index, move |_, _, key: LuaString| Ok(key));
}
}
@@ -331,7 +331,7 @@ fn userdata_call_index(c: &mut Criterion) {
fn userdata_call_method(c: &mut Criterion) {
struct UserData(i64);
impl LuaUserData for UserData {
- fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: LuaUserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_method("add", |_, this, i: i64| Ok(this.0 + i));
}
}
@@ -361,7 +361,7 @@ fn userdata_call_method(c: &mut Criterion) {
fn userdata_async_call_method(c: &mut Criterion) {
struct UserData(i64);
impl LuaUserData for UserData {
- fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: LuaUserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_async_method("add", |_, this, i: i64| async move {
task::yield_now().await;
Ok(this.0 + i)
diff --git a/examples/guided_tour.rs b/examples/guided_tour.rs
index 26b50ad..60ba159 100644
--- a/examples/guided_tour.rs
+++ b/examples/guided_tour.rs
@@ -154,8 +154,8 @@ fn main() -> Result<()> {
struct Vec2(f32, f32);
// We can implement `FromLua` trait for our `Vec2` to return a copy
- impl<'lua> FromLua<'lua> for Vec2 {
- fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Self> {
+ impl FromLua for Vec2 {
+ fn from_lua(value: Value, _: &Lua) -> Result<Self> {
match value {
Value::UserData(ud) => Ok(*ud.borrow::<Self>()?),
_ => unreachable!(),
@@ -192,6 +192,8 @@ fn main() -> Result<()> {
// requirement. You can call `Lua::scope` to create userdata and callbacks types that only live
// for as long as the call to scope, but do not have to be `'static` (and `Send`).
+ // TODO: Re-enable this
+ /*
{
let mut rust_val = 0;
@@ -213,6 +215,7 @@ fn main() -> Result<()> {
assert_eq!(rust_val, 42);
}
+ */
// We were able to run our 'sketchy' function inside the scope just fine. However, if we
// try to run our 'sketchy' function outside of the scope, the function we created will have
diff --git a/mlua_derive/src/from_lua.rs b/mlua_derive/src/from_lua.rs
index 3d4e4ed..8d0b683 100644
--- a/mlua_derive/src/from_lua.rs
+++ b/mlua_derive/src/from_lua.rs
@@ -15,9 +15,9 @@ pub fn from_lua(input: TokenStream) -> TokenStream {
};
quote! {
- impl #impl_generics ::mlua::FromLua<'_> for #ident #ty_generics #where_clause {
+ impl #impl_generics ::mlua::FromLua for #ident #ty_generics #where_clause {
#[inline]
- fn from_lua(value: ::mlua::Value<'_>, _: &'_ ::mlua::Lua) -> ::mlua::Result<Self> {
+ fn from_lua(value: ::mlua::Value, _: &::mlua::Lua) -> ::mlua::Result<Self> {
match value {
::mlua::Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
_ => Err(::mlua::Error::FromLuaConversionError {
diff --git a/mlua_derive/src/lib.rs b/mlua_derive/src/lib.rs
index 74605cb..07209be 100644
--- a/mlua_derive/src/lib.rs
+++ b/mlua_derive/src/lib.rs
@@ -99,15 +99,14 @@ pub fn chunk(input: TokenStream) -> TokenStream {
use ::std::borrow::Cow;
use ::std::cell::Cell;
use ::std::io::Result as IoResult;
- use ::std::marker::PhantomData;
- struct InnerChunk<'lua, F: FnOnce(&'lua Lua) -> Result<Table<'lua>>>(Cell<Option<F>>, PhantomData<&'lua ()>);
+ struct InnerChunk<F: FnOnce(&Lua) -> Result<Table>>(Cell<Option<F>>);
- impl<'lua, F> AsChunk<'lua, 'static> for InnerChunk<'lua, F>
+ impl<F> AsChunk<'static> for InnerChunk<F>
where
- F: FnOnce(&'lua Lua) -> Result<Table<'lua>>,
+ F: FnOnce(&Lua) -> Result<Table>,
{
- fn environment(&self, lua: &'lua Lua) -> Result<Option<Table<'lua>>> {
+ fn environment(&self, lua: &Lua) -> Result<Option<Table>> {
if #caps_len > 0 {
if let Some(make_env) = self.0.take() {
return make_env(lua).map(Some);
@@ -125,9 +124,7 @@ pub fn chunk(input: TokenStream) -> TokenStream {
}
}
- fn annotate<'a, F: FnOnce(&'a Lua) -> Result<Table<'a>>>(f: F) -> F { f }
-
- let make_env = annotate(move |lua: &Lua| -> Result<Table> {
+ let make_env = move |lua: &Lua| -> Result<Table> {
let globals = lua.globals();
let env = lua.create_table()?;
let meta = lua.create_table()?;
@@ -139,9 +136,9 @@ pub fn chunk(input: TokenStream) -> TokenStream {
env.set_metatable(Some(meta));
Ok(env)
- });
+ };
- InnerChunk(Cell::new(Some(make_env)), PhantomData)
+ InnerChunk(Cell::new(Some(make_env)))
}};
wrapped_code.into()
diff --git a/src/chunk.rs b/src/chunk.rs
index 9de6f47..a0a48e1 100644
--- a/src/chunk.rs
+++ b/src/chunk.rs
@@ -7,7 +7,7 @@ use std::string::String as StdString;
use crate::error::{Error, ErrorContext, Result};
use crate::function::Function;
-use crate::lua::Lua;
+use crate::lua::{Lua, WeakLua};
use crate::table::Table;
use crate::value::{FromLuaMulti, IntoLua, IntoLuaMulti};
@@ -15,7 +15,7 @@ use crate::value::{FromLuaMulti, IntoLua, IntoLuaMulti};
///
/// [loadable by Lua]: https://www.lua.org/manual/5.4/manual.html#3.3.2
/// [`Chunk`]: crate::Chunk
-pub trait AsChunk<'lua, 'a> {
+pub trait AsChunk<'a> {
/// Returns optional chunk name
fn name(&self) -> Option<StdString> {
None
@@ -24,7 +24,7 @@ pub trait AsChunk<'lua, 'a> {
/// Returns optional chunk [environment]
///
/// [environment]: https://www.lua.org/manual/5.4/manual.html#2.2
- fn environment(&self, lua: &'lua Lua) -> Result<Option<Table<'lua>>> {
+ fn environment(&self, lua: &Lua) -> Result<Option<Table>> {
let _lua = lua; // suppress warning
Ok(None)
}
@@ -38,43 +38,43 @@ pub trait AsChunk<'lua, 'a> {
fn source(self) -> IoResult<Cow<'a, [u8]>>;
}
-impl<'a> AsChunk<'_, 'a> for &'a str {
+impl<'a> AsChunk<'a> for &'a str {
fn source(self) -> IoResult<Cow<'a, [u8]>> {
Ok(Cow::Borrowed(self.as_ref()))
}
}
-impl AsChunk<'_, 'static> for StdString {
+impl AsChunk<'static> for StdString {
fn source(self) -> IoResult<Cow<'static, [u8]>> {
Ok(Cow::Owned(self.into_bytes()))
}
}
-impl<'a> AsChunk<'_, 'a> for &'a StdString {
+impl<'a> AsChunk<'a> for &'a StdString {
fn source(self) -> IoResult<Cow<'a, [u8]>> {
Ok(Cow::Borrowed(self.as_bytes()))
}
}
-impl<'a> AsChunk<'_, 'a> for &'a [u8] {
+impl<'a> AsChunk<'a> for &'a [u8] {
fn source(self) -> IoResult<Cow<'a, [u8]>> {
Ok(Cow::Borrowed(self))
}
}
-impl AsChunk<'_, 'static> for Vec<u8> {
+impl AsChunk<'static> for Vec<u8> {
fn source(self) -> IoResult<Cow<'static, [u8]>> {
Ok(Cow::Owned(self))
}
}
-impl<'a> AsChunk<'_, 'a> for &'a Vec<u8> {
+impl<'a> AsChunk<'a> for &'a Vec<u8> {
fn source(self) -> IoResult<Cow<'a, [u8]>> {
Ok(Cow::Borrowed(self.as_ref()))
}
}
-impl AsChunk<'_, 'static> for &Path {
+impl AsChunk<'static> for &Path {
fn name(&self) -> Option<StdString> {
Some(format!("@{}", self.display()))
}
@@ -84,7 +84,7 @@ impl AsChunk<'_, 'static> for &Path {
}
}
-impl AsChunk<'_, 'static> for PathBuf {
+impl AsChunk<'static> for PathBuf {
fn name(&self) -> Option<StdString> {
Some(format!("@{}", self.display()))
}
@@ -98,10 +98,10 @@ impl AsChunk<'_, 'static> for PathBuf {
///
/// [`Lua::load`]: crate::Lua::load
#[must_use = "`Chunk`s do nothing unless one of `exec`, `eval`, `call`, or `into_function` are called on them"]
-pub struct Chunk<'lua, 'a> {
- pub(crate) lua: &'lua Lua,
+pub struct Chunk<'a> {
+ pub(crate) lua: WeakLua,
pub(crate) name: StdString,
- pub(crate) env: Result<Option<Table<'lua>>>,
+ pub(crate) env: Result<Option<Table>>,
pub(crate) mode: Option<ChunkMode>,
pub(crate) source: IoResult<Cow<'a, [u8]>>,
#[cfg(feature = "luau")]
@@ -290,7 +290,7 @@ impl Compiler {
}
}
-impl<'lua, 'a> Chunk<'lua, 'a> {
+impl<'a> Chunk<'a> {
/// Sets the name of this chunk, which results in more informative error traces.
pub fn set_name(mut self, name: impl Into<String>) -> Self {
self.name = name.into();
@@ -309,9 +309,11 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
/// necessary to populate the environment in order for scripts using custom environments to be
/// useful.
pub fn set_environment<V: IntoLua>(mut self, env: V) -> Self {
+ let lua = self.lua.lock();
+ let lua = lua.lua();
self.env = env
- .into_lua(self.lua)
- .and_then(|val| self.lua.unpack(val))
+ .into_lua(lua)
+ .and_then(|val| lua.unpack(val))
.context("bad environment value");
self
}
@@ -363,7 +365,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
/// If the chunk can be parsed as an expression, this loads and executes the chunk and returns
/// the value that it evaluates to. Otherwise, the chunk is interpreted as a block as normal,
/// and this is equivalent to calling `exec`.
- pub fn eval<R: FromLuaMulti<'lua>>(self) -> Result<R> {
+ pub fn eval<R: FromLuaMulti>(self) -> Result<R> {
// Bytecode is always interpreted as a statement.
// For source code, first try interpreting the lua as an expression by adding
// "return", then as a statement. This is the same thing the
@@ -388,7 +390,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub async fn eval_async<R>(self) -> Result<R>
where
- R: FromLuaMulti<'lua> + 'lua,
+ R: FromLuaMulti,
{
if self.detect_mode() == ChunkMode::Binary {
self.call_async(()).await
@@ -402,7 +404,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
/// Load the chunk function and call it with the given arguments.
///
/// This is equivalent to `into_function` and calling the resulting function.
- pub fn call<A: IntoLuaMulti, R: FromLuaMulti<'lua>>(self, args: A) -> Result<R> {
+ pub fn call<A: IntoLuaMulti, R: FromLuaMulti>(self, args: A) -> Result<R> {
self.into_function()?.call(args)
}
@@ -418,7 +420,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
pub async fn call_async<A, R>(self, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua,
+ R: FromLuaMulti,
{
self.into_function()?.call_async(args).await
}
@@ -427,7 +429,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
///
/// This simply compiles the chunk without actually executing it.
#[cfg_attr(not(feature = "luau"), allow(unused_mut))]
- pub fn into_function(mut self) -> Result<Function<'lua>> {
+ pub fn into_function(mut self) -> Result<Function> {
#[cfg(feature = "luau")]
if self.compiler.is_some() {
// We don't need to compile source if no compiler set
@@ -436,6 +438,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
let name = Self::convert_name(self.name)?;
self.lua
+ .lock()
.load_chunk(Some(&name), self.env?, self.mode, self.source?.as_ref())
}
@@ -455,7 +458,11 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
self.mode = Some(ChunkMode::Binary);
}
#[cfg(not(feature = "luau"))]
- if let Ok(func) = self.lua.load_chunk(None, None, None, source.as_ref()) {
+ if let Ok(func) = self
+ .lua
+ .lock()
+ .load_chunk(None, None, None, source.as_ref())
+ {
let data = func.dump(false);
self.source = Ok(Cow::Owned(data));
self.mode = Some(ChunkMode::Binary);
@@ -474,7 +481,8 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
let mut text_source = None;
if let Ok(ref source) = self.source {
if self.detect_mode() == ChunkMode::Text {
- if let Some(cache) = self.lua.app_data_ref::<ChunksCache>() {
+ let lua = self.lua.lock();
+ if let Some(cache) = lua.app_data_ref::<ChunksCache>() {
if let Some(data) = cache.0.get(source.as_ref()) {
self.source = Ok(Cow::Owned(data.clone()));
self.mode = Some(ChunkMode::Binary);
@@ -490,13 +498,14 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
self.compile();
if let Ok(ref binary_source) = self.source {
if self.detect_mode() == ChunkMode::Binary {
- if let Some(mut cache) = self.lua.app_data_mut::<ChunksCache>() {
+ let lua = self.lua.lock();
+ if let Some(mut cache) = lua.app_data_mut::<ChunksCache>() {
cache.0.insert(text_source, binary_source.as_ref().to_vec());
} else {
let mut cache = ChunksCache(HashMap::new());
cache.0.insert(text_source, binary_source.as_ref().to_vec());
- let _ = self.lua.try_set_app_data(cache);
- }
+ let _ = lua.try_set_app_data(cache);
+ };
}
}
}
@@ -504,7 +513,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
self
}
- fn to_expression(&self) -> Result<Function<'lua>> {
+ fn to_expression(&self) -> Result<Function> {
// We assume that mode is Text
let source = self.source.as_ref();
let source = source.map_err(Error::runtime)?;
@@ -519,6 +528,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
let name = Self::convert_name(self.name.clone())?;
self.lua
+ .lock()
.load_chunk(Some(&name), self.env.clone()?, None, &source)
}
diff --git a/src/conversion.rs b/src/conversion.rs
index f521097..1194c63 100644
--- a/src/conversion.rs
+++ b/src/conversion.rs
@@ -12,69 +12,63 @@ use num_traits::cast;
use crate::error::{Error, Result};
use crate::function::Function;
-use crate::lua::Lua;
+use crate::lua::{Lua, LuaInner};
use crate::string::String;
use crate::table::Table;
use crate::thread::Thread;
use crate::types::{LightUserData, MaybeSend, RegistryKey};
-use crate::userdata::{AnyUserData, UserData, UserDataRef, UserDataRefMut};
+use crate::userdata::{AnyUserData, UserData};
use crate::value::{FromLua, IntoLua, Nil, Value};
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-use crate::{
- function::OwnedFunction, string::OwnedString, table::OwnedTable, thread::OwnedThread,
- userdata::OwnedAnyUserData,
-};
-
-impl IntoLua for Value<'_> {
+impl IntoLua for Value {
#[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
unsafe { Ok(transmute(self)) }
}
}
-impl IntoLua for &Value<'_> {
+impl IntoLua for &Value {
#[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
unsafe { Ok(transmute(self.clone())) }
}
#[inline]
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
lua.push_value(self)
}
}
-impl<'lua> FromLua<'lua> for Value<'lua> {
+impl FromLua for Value {
#[inline]
- fn from_lua(lua_value: Value<'lua>, _: &'lua Lua) -> Result<Self> {
+ fn from_lua(lua_value: Value, _: &Lua) -> Result<Self> {
Ok(lua_value)
}
}
-impl IntoLua for String<'_> {
+impl IntoLua for String {
#[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
unsafe { Ok(Value::String(transmute(self))) }
}
}
-impl IntoLua for &String<'_> {
+impl IntoLua for &String {
#[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
unsafe { Ok(Value::String(transmute(self.clone()))) }
}
#[inline]
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
lua.push_ref(&self.0);
Ok(())
}
}
-impl<'lua> FromLua<'lua> for String<'lua> {
+impl FromLua for String {
#[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<String<'lua>> {
+ fn from_lua(value: Value, lua: &Lua) -> Result<String> {
let ty = value.type_name();
lua.coerce_string(value)?
.ok_or_else(|| Error::FromLuaConversionError {
@@ -85,62 +79,29 @@ impl<'lua> FromLua<'lua> for String<'lua> {
}
}
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl IntoLua for OwnedString {
- #[inline]
- fn into_lua(self, lua: &'_ Lua) -> Result<Value<'_>> {
- Ok(Value::String(String(lua.adopt_owned_ref(self.0))))
- }
-}
-
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl IntoLua for &OwnedString {
- #[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
- OwnedString::into_lua(self.clone(), lua)
- }
-
+impl IntoLua for Table {
#[inline]
- unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
- lua.push_owned_ref(&self.0);
- Ok(())
- }
-}
-
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl<'lua> FromLua<'lua> for OwnedString {
- #[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<OwnedString> {
- String::from_lua(value, lua).map(|s| s.into_owned())
- }
-}
-
-impl IntoLua for Table<'_> {
- #[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
unsafe { Ok(Value::Table(transmute(self))) }
}
}
-impl IntoLua for &Table<'_> {
+impl IntoLua for &Table {
#[inline]
- fn into_lua(self, _: &'_ Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
unsafe { Ok(Value::Table(transmute(self.clone()))) }
}
#[inline]
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
lua.push_ref(&self.0);
Ok(())
}
}
-impl<'lua> FromLua<'lua> for Table<'lua> {
+impl FromLua for Table {
#[inline]
- fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Table<'lua>> {
+ fn from_lua(value: Value, _: &Lua) -> Result<Table> {
match value {
Value::Table(table) => Ok(table),
_ => Err(Error::FromLuaConversionError {
@@ -152,62 +113,29 @@ impl<'lua> FromLua<'lua> for Table<'lua> {
}
}
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl IntoLua for OwnedTable {
+impl IntoLua for Function {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
- Ok(Value::Table(Table(lua.adopt_owned_ref(self.0))))
- }
-}
-
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl IntoLua for &OwnedTable {
- #[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
- OwnedTable::into_lua(self.clone(), lua)
- }
-
- #[inline]
- unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
- lua.push_owned_ref(&self.0);
- Ok(())
- }
-}
-
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl<'lua> FromLua<'lua> for OwnedTable {
- #[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<OwnedTable> {
- Table::from_lua(value, lua).map(|s| s.into_owned())
- }
-}
-
-impl IntoLua for Function<'_> {
- #[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
unsafe { Ok(Value::Function(transmute(self))) }
}
}
-impl IntoLua for &Function<'_> {
+impl IntoLua for &Function {
#[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
unsafe { Ok(Value::Function(transmute(self.clone()))) }
}
#[inline]
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
lua.push_ref(&self.0);
Ok(())
}
}
-impl<'lua> FromLua<'lua> for Function<'lua> {
+impl FromLua for Function {
#[inline]
- fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Function<'lua>> {
+ fn from_lua(value: Value, _: &Lua) -> Result<Function> {
match value {
Value::Function(table) => Ok(table),
_ => Err(Error::FromLuaConversionError {
@@ -219,62 +147,29 @@ impl<'lua> FromLua<'lua> for Function<'lua> {
}
}
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl IntoLua for OwnedFunction {
- #[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
- Ok(Value::Function(Function(lua.adopt_owned_ref(self.0))))
- }
-}
-
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl IntoLua for &OwnedFunction {
- #[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
- OwnedFunction::into_lua(self.clone(), lua)
- }
-
- #[inline]
- unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
- lua.push_owned_ref(&self.0);
- Ok(())
- }
-}
-
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl<'lua> FromLua<'lua> for OwnedFunction {
+impl IntoLua for Thread {
#[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<OwnedFunction> {
- Function::from_lua(value, lua).map(|s| s.into_owned())
- }
-}
-
-impl IntoLua for Thread<'_> {
- #[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
unsafe { Ok(Value::Thread(transmute(self))) }
}
}
-impl IntoLua for &Thread<'_> {
+impl IntoLua for &Thread {
#[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
unsafe { Ok(Value::Thread(transmute(self.clone()))) }
}
#[inline]
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
lua.push_ref(&self.0);
Ok(())
}
}
-impl<'lua> FromLua<'lua> for Thread<'lua> {
+impl FromLua for Thread {
#[inline]
- fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Thread<'lua>> {
+ fn from_lua(value: Value, _: &Lua) -> Result<Thread> {
match value {
Value::Thread(t) => Ok(t),
_ => Err(Error::FromLuaConversionError {
@@ -286,62 +181,29 @@ impl<'lua> FromLua<'lua> for Thread<'lua> {
}
}
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl IntoLua for OwnedThread {
- #[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
- Ok(Value::Thread(Thread(lua.adopt_owned_ref(self.0), self.1)))
- }
-}
-
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl IntoLua for &OwnedThread {
- #[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
- OwnedThread::into_lua(self.clone(), lua)
- }
-
+impl IntoLua for AnyUserData {
#[inline]
- unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
- lua.push_owned_ref(&self.0);
- Ok(())
- }
-}
-
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl<'lua> FromLua<'lua> for OwnedThread {
- #[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<OwnedThread> {
- Thread::from_lua(value, lua).map(|s| s.into_owned())
- }
-}
-
-impl IntoLua for AnyUserData<'_> {
- #[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
unsafe { Ok(Value::UserData(transmute(self))) }
}
}
-impl IntoLua for &AnyUserData<'_> {
+impl IntoLua for &AnyUserData {
#[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
unsafe { Ok(Value::UserData(transmute(self.clone()))) }
}
#[inline]
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
lua.push_ref(&self.0);
Ok(())
}
}
-impl<'lua> FromLua<'lua> for AnyUserData<'lua> {
+impl FromLua for AnyUserData {
#[inline]
- fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<AnyUserData<'lua>> {
+ fn from_lua(value: Value, _: &Lua) -> Result<AnyUserData> {
match value {
Value::UserData(ud) => Ok(ud),
_ => Err(Error::FromLuaConversionError {
@@ -353,73 +215,23 @@ impl<'lua> FromLua<'lua> for AnyUserData<'lua> {
}
}
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl IntoLua for OwnedAnyUserData {
- #[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
- Ok(Value::UserData(AnyUserData(
- lua.adopt_owned_ref(self.0),
- self.1,
- )))
- }
-}
-
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl IntoLua for &OwnedAnyUserData {
- #[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
- OwnedAnyUserData::into_lua(self.clone(), lua)
- }
-
- #[inline]
- unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
- lua.push_owned_ref(&self.0);
- Ok(())
- }
-}
-
-#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
-impl<'lua> FromLua<'lua> for OwnedAnyUserData {
- #[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<OwnedAnyUserData> {
- AnyUserData::from_lua(value, lua).map(|s| s.into_owned())
- }
-}
-
impl<T: UserData + MaybeSend + 'static> IntoLua for T {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::UserData(lua.create_userdata(self)?))
}
}
-impl<'lua, T: 'static> FromLua<'lua> for UserDataRef<'lua, T> {
- #[inline]
- fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Self> {
- Self::from_value(value)
- }
-}
-
-impl<'lua, T: 'static> FromLua<'lua> for UserDataRefMut<'lua, T> {
- #[inline]
- fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Self> {
- Self::from_value(value)
- }
-}
-
impl IntoLua for Error {
#[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
Ok(Value::Error(Box::new(self)))
}
}
-impl<'lua> FromLua<'lua> for Error {
+impl FromLua for Error {
#[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Error> {
+ fn from_lua(value: Value, lua: &Lua) -> Result<Error> {
match value {
Value::Error(err) => Ok(*err),
val => Ok(Error::runtime(
@@ -433,23 +245,23 @@ impl<'lua> FromLua<'lua> for Error {
impl IntoLua for RegistryKey {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
lua.registry_value(&self)
}
#[inline]
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
<&RegistryKey>::push_into_stack(&self, lua)
}
}
impl IntoLua for &RegistryKey {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
lua.registry_value(self)
}
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
if !lua.owns_registry_value(self) {
return Err(Error::MismatchedRegistryKey);
}
@@ -464,29 +276,29 @@ impl IntoLua for &RegistryKey {
}
}
-impl<'lua> FromLua<'lua> for RegistryKey {
+impl FromLua for RegistryKey {
#[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<RegistryKey> {
+ fn from_lua(value: Value, lua: &Lua) -> Result<RegistryKey> {
lua.create_registry_value(value)
}
}
impl IntoLua for bool {
#[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
Ok(Value::Boolean(self))
}
#[inline]
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
ffi::lua_pushboolean(lua.state(), self as c_int);
Ok(())
}
}
-impl<'lua> FromLua<'lua> for bool {
+impl FromLua for bool {
#[inline]
- fn from_lua(v: Value<'lua>, _: &'lua Lua) -> Result<Self> {
+ fn from_lua(v: Value, _: &Lua) -> Result<Self> {
match v {
Value::Nil => Ok(false),
Value::Boolean(b) => Ok(b),
@@ -495,21 +307,21 @@ impl<'lua> FromLua<'lua> for bool {
}
#[inline]
- unsafe fn from_stack(idx: c_int, lua: &'lua Lua) -> Result<Self> {
+ unsafe fn from_stack(idx: c_int, lua: &LuaInner) -> Result<Self> {
Ok(ffi::lua_toboolean(lua.state(), idx) != 0)
}
}
impl IntoLua for LightUserData {
#[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
Ok(Value::LightUserData(self))
}
}
-impl<'lua> FromLua<'lua> for LightUserData {
+impl FromLua for LightUserData {
#[inline]
- fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, _: &Lua) -> Result<Self> {
match value {
Value::LightUserData(ud) => Ok(ud),
_ => Err(Error::FromLuaConversionError {
@@ -524,15 +336,15 @@ impl<'lua> FromLua<'lua> for LightUserData {
#[cfg(feature = "luau")]
impl IntoLua for crate::types::Vector {
#[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
Ok(Value::Vector(self))
}
}
#[cfg(feature = "luau")]
-impl<'lua> FromLua<'lua> for crate::types::Vector {
+impl FromLua for crate::types::Vector {
#[inline]
- fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, _: &Lua) -> Result<Self> {
match value {
Value::Vector(v) => Ok(v),
_ => Err(Error::FromLuaConversionError {
@@ -546,19 +358,19 @@ impl<'lua> FromLua<'lua> for crate::types::Vector {
impl IntoLua for StdString {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::String(lua.create_string(&self)?))
}
#[inline]
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
push_bytes_into_stack(self, lua)
}
}
-impl<'lua> FromLua<'lua> for StdString {
+impl FromLua for StdString {
#[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
let ty = value.type_name();
Ok(lua
.coerce_string(value)?
@@ -572,7 +384,7 @@ impl<'lua> FromLua<'lua> for StdString {
}
#[inline]
- unsafe fn from_stack(idx: c_int, lua: &'lua Lua) -> Result<Self> {
+ unsafe fn from_stack(idx: c_int, lua: &LuaInner) -> Result<Self> {
let state = lua.state();
if ffi::lua_type(state, idx) == ffi::LUA_TSTRING {
let mut size = 0;
@@ -587,39 +399,39 @@ impl<'lua> FromLua<'lua> for StdString {
});
}
// Fallback to default
- Self::from_lua(lua.stack_value(idx), lua)
+ Self::from_lua(lua.stack_value(idx), lua.lua())
}
}
impl IntoLua for &str {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::String(lua.create_string(self)?))
}
#[inline]
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
push_bytes_into_stack(self, lua)
}
}
impl IntoLua for Cow<'_, str> {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::String(lua.create_string(self.as_bytes())?))
}
}
impl IntoLua for Box<str> {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::String(lua.create_string(&*self)?))
}
}
-impl<'lua> FromLua<'lua> for Box<str> {
+impl FromLua for Box<str> {
#[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
let ty = value.type_name();
Ok(lua
.coerce_string(value)?
@@ -636,14 +448,14 @@ impl<'lua> FromLua<'lua> for Box<str> {
impl IntoLua for CString {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::String(lua.create_string(self.as_bytes())?))
}
}
-impl<'lua> FromLua<'lua> for CString {
+impl FromLua for CString {
#[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
let ty = value.type_name();
let string = lua
.coerce_string(value)?
@@ -666,34 +478,35 @@ impl<'lua> FromLua<'lua> for CString {
impl IntoLua for &CStr {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::String(lua.create_string(self.to_bytes())?))
}
}
impl IntoLua for Cow<'_, CStr> {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::String(lua.create_string(self.to_bytes())?))
}
}
impl IntoLua for BString {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::String(lua.create_string(&self)?))
}
}
-impl<'lua> FromLua<'lua> for BString {
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self> {
+impl FromLua for BString {
+ fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
let ty = value.type_name();
match value {
Value::String(s) => Ok(s.as_bytes().into()),
#[cfg(feature = "luau")]
Value::UserData(ud) if ud.1 == crate::types::SubtypeId::Buffer => unsafe {
+ let lua = ud.0.lua.lock();
let mut size = 0usize;
- let buf = ffi::lua_tobuffer(ud.0.lua.ref_thread(), ud.0.index, &mut size);
+ let buf = ffi::lua_tobuffer(lua.ref_thread(), ud.0.index, &mut size);
mlua_assert!(!buf.is_null(), "invalid Luau buffer");
Ok(slice::from_raw_parts(buf as *const u8, size).into())
},
@@ -709,7 +522,7 @@ impl<'lua> FromLua<'lua> for BString {
}
}
- unsafe fn from_stack(idx: c_int, lua: &'lua Lua) -> Result<Self> {
+ unsafe fn from_stack(idx: c_int, lua: &LuaInner) -> Result<Self> {
let state = lua.state();
match ffi::lua_type(state, idx) {
ffi::LUA_TSTRING => {
@@ -726,7 +539,7 @@ impl<'lua> FromLua<'lua> for BString {
}
_ => {
// Fallback to default
- Self::from_lua(lua.stack_value(idx), lua)
+ Self::from_lua(lua.stack_value(idx), lua.lua())
}
}
}
@@ -734,13 +547,13 @@ impl<'lua> FromLua<'lua> for BString {
impl IntoLua for &BStr {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::String(lua.create_string(self)?))
}
}
#[inline]
-unsafe fn push_bytes_into_stack<'lua, T>(this: T, lua: &'lua Lua) -> Result<()>
+unsafe fn push_bytes_into_stack<T>(this: T, lua: &LuaInner) -> Result<()>
where
T: IntoLua + AsRef<[u8]>,
{
@@ -751,14 +564,14 @@ where
return Ok(());
}
// Fallback to default
- lua.push_value(&T::into_lua(this, lua)?)
+ lua.push_value(&T::into_lua(this, lua.lua())?)
}
macro_rules! lua_convert_int {
($x:ty) => {
impl IntoLua for $x {
#[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
cast(self)
.map(Value::Integer)
.or_else(|| cast(self).map(Value::Number))
@@ -771,7 +584,7 @@ macro_rules! lua_convert_int {
}
#[inline]
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
match cast(self) {
Some(i) => ffi::lua_pushinteger(lua.state(), i),
None => ffi::lua_pushnumber(lua.state(), self as ffi::lua_Number),
@@ -780,9 +593,9 @@ macro_rules! lua_convert_int {
}
}
- impl<'lua> FromLua<'lua> for $x {
+ impl FromLua for $x {
#[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
let ty = value.type_name();
(match value {
Value::Integer(i) => cast(i),
@@ -830,7 +643,7 @@ macro_rules! lua_convert_float {
($x:ty) => {
impl IntoLua for $x {
#[inline]
- fn into_lua(self, _: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, _: &Lua) -> Result<Value> {
cast(self)
.ok_or_else(|| Error::ToLuaConversionError {
from: stringify!($x),
@@ -841,9 +654,9 @@ macro_rules! lua_convert_float {
}
}
- impl<'lua> FromLua<'lua> for $x {
+ impl FromLua for $x {
#[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
let ty = value.type_name();
lua.coerce_number(value)?
.ok_or_else(|| Error::FromLuaConversionError {
@@ -871,7 +684,7 @@ where
T: IntoLua + Clone,
{
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::Table(
lua.create_sequence_from(self.iter().cloned())?,
))
@@ -883,17 +696,17 @@ where
T: IntoLua,
{
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::Table(lua.create_sequence_from(self)?))
}
}
-impl<'lua, T, const N: usize> FromLua<'lua> for [T; N]
+impl<T, const N: usize> FromLua for [T; N]
where
- T: FromLua<'lua>,
+ T: FromLua,
{
#[inline]
- fn from_lua(value: Value<'lua>, _lua: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
match value {
#[cfg(feature = "luau")]
#[rustfmt::skip]
@@ -927,28 +740,28 @@ where
impl<T: IntoLua> IntoLua for Box<[T]> {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::Table(lua.create_sequence_from(self.into_vec())?))
}
}
-impl<'lua, T: FromLua<'lua>> FromLua<'lua> for Box<[T]> {
+impl<T: FromLua> FromLua for Box<[T]> {
#[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
Ok(Vec::<T>::from_lua(value, lua)?.into_boxed_slice())
}
}
impl<T: IntoLua> IntoLua for Vec<T> {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::Table(lua.create_sequence_from(self)?))
}
}
-impl<'lua, T: FromLua<'lua>> FromLua<'lua> for Vec<T> {
+impl<T: FromLua> FromLua for Vec<T> {
#[inline]
- fn from_lua(value: Value<'lua>, _lua: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
match value {
Value::Table(table) => table.sequence_values().collect(),
_ => Err(Error::FromLuaConversionError {
@@ -962,16 +775,14 @@ impl<'lua, T: FromLua<'lua>> FromLua<'lua> for Vec<T> {
impl<K: Eq + Hash + IntoLua, V: IntoLua, S: BuildHasher> IntoLua for HashMap<K, V, S> {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::Table(lua.create_table_from(self)?))
}
}
-impl<'lua, K: Eq + Hash + FromLua<'lua>, V: FromLua<'lua>, S: BuildHasher + Default> FromLua<'lua>
- for HashMap<K, V, S>
-{
+impl<K: Eq + Hash + FromLua, V: FromLua, S: BuildHasher + Default> FromLua for HashMap<K, V, S> {
#[inline]
- fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, _: &Lua) -> Result<Self> {
if let Value::Table(table) = value {
table.pairs().collect()
} else {
@@ -986,14 +797,14 @@ impl<'lua, K: Eq + Hash + FromLua<'lua>, V: FromLua<'lua>, S: BuildHasher + Defa
impl<K: Ord + IntoLua, V: IntoLua> IntoLua for BTreeMap<K, V> {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::Table(lua.create_table_from(self)?))
}
}
-impl<'lua, K: Ord + FromLua<'lua>, V: FromLua<'lua>> FromLua<'lua> for BTreeMap<K, V> {
+impl<K: Ord + FromLua, V: FromLua> FromLua for BTreeMap<K, V> {
#[inline]
- fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, _: &Lua) -> Result<Self> {
if let Value::Table(table) = value {
table.pairs().collect()
} else {
@@ -1008,20 +819,20 @@ impl<'lua, K: Ord + FromLua<'lua>, V: FromLua<'lua>> FromLua<'lua> for BTreeMap<
impl<T: Eq + Hash + IntoLua, S: BuildHasher> IntoLua for HashSet<T, S> {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::Table(lua.create_table_from(
self.into_iter().map(|val| (val, true)),
)?))
}
}
-impl<'lua, T: Eq + Hash + FromLua<'lua>, S: BuildHasher + Default> FromLua<'lua> for HashSet<T, S> {
+impl<T: Eq + Hash + FromLua, S: BuildHasher + Default> FromLua for HashSet<T, S> {
#[inline]
- fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, _: &Lua) -> Result<Self> {
match value {
Value::Table(table) if table.raw_len() > 0 => table.sequence_values().collect(),
Value::Table(table) => table
- .pairs::<T, Value<'lua>>()
+ .pairs::<T, Value>()
.map(|res| res.map(|(k, _)| k))
.collect(),
_ => Err(Error::FromLuaConversionError {
@@ -1035,20 +846,20 @@ impl<'lua, T: Eq + Hash + FromLua<'lua>, S: BuildHasher + Default> FromLua<'lua>
impl<T: Ord + IntoLua> IntoLua for BTreeSet<T> {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
Ok(Value::Table(lua.create_table_from(
self.into_iter().map(|val| (val, true)),
)?))
}
}
-impl<'lua, T: Ord + FromLua<'lua>> FromLua<'lua> for BTreeSet<T> {
+impl<T: Ord + FromLua> FromLua for BTreeSet<T> {
#[inline]
- fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, _: &Lua) -> Result<Self> {
match value {
Value::Table(table) if table.raw_len() > 0 => table.sequence_values().collect(),
Value::Table(table) => table
- .pairs::<T, Value<'lua>>()
+ .pairs::<T, Value>()
.map(|res| res.map(|(k, _)| k))
.collect(),
_ => Err(Error::FromLuaConversionError {
@@ -1062,7 +873,7 @@ impl<'lua, T: Ord + FromLua<'lua>> FromLua<'lua> for BTreeSet<T> {
impl<T: IntoLua> IntoLua for Option<T> {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
match self {
Some(val) => val.into_lua(lua),
None => Ok(Nil),
@@ -1070,7 +881,7 @@ impl<T: IntoLua> IntoLua for Option<T> {
}
#[inline]
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
match self {
Some(val) => val.push_into_stack(lua)?,
None => ffi::lua_pushnil(lua.state()),
@@ -1079,9 +890,9 @@ impl<T: IntoLua> IntoLua for Option<T> {
}
}
-impl<'lua, T: FromLua<'lua>> FromLua<'lua> for Option<T> {
+impl<T: FromLua> FromLua for Option<T> {
#[inline]
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self> {
+ fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
match value {
Nil => Ok(None),
value => Ok(Some(T::from_lua(value, lua)?)),
@@ -1089,7 +900,7 @@ impl<'lua, T: FromLua<'lua>> FromLua<'lua> for Option<T> {
}
#[inline]
- unsafe fn from_stack(idx: c_int, lua: &'lua Lua) -> Result<Self> {
+ unsafe fn from_stack(idx: c_int, lua: &LuaInner) -> Result<Self> {
if ffi::lua_isnil(lua.state(), idx) != 0 {
Ok(None)
} else {
diff --git a/src/function.rs b/src/function.rs
index 81a7cda..a27069e 100644
--- a/src/function.rs
+++ b/src/function.rs
@@ -22,28 +22,7 @@ use {
/// Handle to an internal Lua function.
#[derive(Clone, Debug)]
-pub struct Function<'lua>(pub(crate) ValueRef<'lua>);
-
-/// Owned handle to an internal Lua function.
-///
-/// The owned handle holds a *strong* reference to the current Lua instance.
-/// Be warned, if you place it into a Lua type (eg. [`UserData`] or a Rust callback), it is *very easy*
-/// to accidentally cause reference cycles that would prevent destroying Lua instance.
-///
-/// [`UserData`]: crate::UserData
-#[cfg(feature = "unstable")]
-#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
-#[derive(Clone, Debug)]
-pub struct OwnedFunction(pub(crate) crate::types::OwnedValueRef);
-
-#[cfg(feature = "unstable")]
-impl OwnedFunction {
- /// Get borrowed handle to the underlying Lua function.
- #[cfg_attr(feature = "send", allow(unused))]
- pub const fn to_ref(&self) -> Function {
- Function(self.0.to_ref())
- }
-}
+pub struct Function(pub(crate) ValueRef);
/// Contains information about a function.
///
@@ -81,7 +60,7 @@ pub struct CoverageInfo {
pub hits: Vec<i32>,
}
-impl<'lua> Function<'lua> {
+impl Function {
/// Calls the function, passing `args` as function arguments.
///
/// The function's return values are converted to the generic type `R`.
@@ -122,8 +101,8 @@ impl<'lua> Function<'lua> {
/// # Ok(())
/// # }
/// ```
- pub fn call<A: IntoLuaMulti, R: FromLuaMulti<'lua>>(&self, args: A) -> Result<R> {
- let lua = self.0.lua;
+ pub fn call<A: IntoLuaMulti, R: FromLuaMulti>(&self, args: A) -> Result<R> {
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -134,7 +113,7 @@ impl<'lua> Function<'lua> {
let stack_start = ffi::lua_gettop(state);
// Push function and the arguments
lua.push_ref(&self.0);
- let nargs = args.push_into_stack_multi(lua)?;
+ let nargs = args.push_into_stack_multi(&lua)?;
// Call the function
let ret = ffi::lua_pcall(state, nargs, ffi::LUA_MULTRET, stack_start);
if ret != ffi::LUA_OK {
@@ -142,7 +121,7 @@ impl<'lua> Function<'lua> {
}
// Get the results
let nresults = ffi::lua_gettop(state) - stack_start;
- R::from_stack_multi(nresults, lua)
+ R::from_stack_multi(nresults, &lua)
}
}
@@ -176,12 +155,12 @@ impl<'lua> Function<'lua> {
/// [`AsyncThread`]: crate::AsyncThread
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- pub fn call_async<A, R>(&self, args: A) -> impl Future<Output = Result<R>> + 'lua
+ pub fn call_async<A, R>(&self, args: A) -> impl Future<Output = Result<R>>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua,
+ R: FromLuaMulti,
{
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let thread_res = lua.create_recycled_thread(self).map(|th| {
let mut th = th.into_async(args);
th.set_recyclable(true);
@@ -217,7 +196,7 @@ impl<'lua> Function<'lua> {
/// # Ok(())
/// # }
/// ```
- pub fn bind<A: IntoLuaMulti>(&self, args: A) -> Result<Function<'lua>> {
+ pub fn bind<A: IntoLuaMulti>(&self, args: A) -> Result<Function> {
unsafe extern "C-unwind" fn args_wrapper_impl(state: *mut ffi::lua_State) -> c_int {
let nargs = ffi::lua_gettop(state);
let nbinds = ffi::lua_tointeger(state, ffi::lua_upvalueindex(1)) as c_int;
@@ -233,10 +212,10 @@ impl<'lua> Function<'lua> {
nargs + nbinds
}
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
- let args = args.into_lua_multi(lua)?;
+ let args = args.into_lua_multi(lua.lua())?;
let nargs = args.len() as c_int;
if nargs == 0 {
@@ -262,6 +241,7 @@ impl<'lua> Function<'lua> {
Function(lua.pop_ref())
};
+ let lua = lua.lua();
lua.load(
r#"
local func, args_wrapper = ...
@@ -281,7 +261,7 @@ impl<'lua> Function<'lua> {
///
/// This function always returns `None` for Rust/C functions.
pub fn environment(&self) -> Option<Table> {
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -318,7 +298,7 @@ impl<'lua> Function<'lua> {
///
/// This function does nothing for Rust/C functions.
pub fn set_environment(&self, env: Table) -> Result<bool> {
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -342,6 +322,7 @@ impl<'lua> Function<'lua> {
ffi::lua_pop(state, 1);
// Create an anonymous function with the new environment
let f_with_env = lua
+ .lua()
.load("return _ENV")
.set_environment(env)
.try_cache()
@@ -364,7 +345,7 @@ impl<'lua> Function<'lua> {
///
/// [`lua_getinfo`]: https://www.lua.org/manual/5.4/manual.html#lua_getinfo
pub fn info(&self) -> FunctionInfo {
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -425,7 +406,7 @@ impl<'lua> Function<'lua> {
0
}
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
let mut data: Vec<u8> = Vec::new();
unsafe {
@@ -482,7 +463,7 @@ impl<'lua> Function<'lua> {
});
}
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -514,80 +495,42 @@ impl<'lua> Function<'lua> {
#[cfg(feature = "luau")]
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
pub fn deep_clone(&self) -> Self {
- let ref_thread = self.0.lua.ref_thread();
+ let lua = self.0.lua.lock();
+ let ref_thread = lua.ref_thread();
unsafe {
if ffi::lua_iscfunction(ref_thread, self.0.index) != 0 {
return self.clone();
}
ffi::lua_clonefunction(ref_thread, self.0.index);
- Function(self.0.lua.pop_ref_thread())
+ Function(lua.pop_ref_thread())
}
}
-
- /// Convert this handle to owned version.
- #[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
- #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
- #[inline]
- pub fn into_owned(self) -> OwnedFunction {
- OwnedFunction(self.0.into_owned())
- }
}
-impl<'lua> PartialEq for Function<'lua> {
+impl PartialEq for Function {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
-// Additional shortcuts
-#[cfg(feature = "unstable")]
-impl OwnedFunction {
- /// Calls the function, passing `args` as function arguments.
- ///
- /// This is a shortcut for [`Function::call()`].
- #[inline]
- pub fn call<'lua, A, R>(&'lua self, args: A) -> Result<R>
- where
- A: IntoLuaMulti,
- R: FromLuaMulti<'lua>,
- {
- self.to_ref().call(args)
- }
-
- /// Returns a future that, when polled, calls `self`, passing `args` as function arguments,
- /// and drives the execution.
- ///
- /// This is a shortcut for [`Function::call_async()`].
- #[cfg(feature = "async")]
- #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- #[inline]
- pub async fn call_async<'lua, A, R>(&'lua self, args: A) -> Result<R>
- where
- A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua,
- {
- self.to_ref().call_async(args).await
- }
-}
-
-pub(crate) struct WrappedFunction<'lua>(pub(crate) Callback<'lua, 'static>);
+pub(crate) struct WrappedFunction(pub(crate) Callback<'static>);
#[cfg(feature = "async")]
-pub(crate) struct WrappedAsyncFunction<'lua>(pub(crate) AsyncCallback<'lua, 'static>);
+pub(crate) struct WrappedAsyncFunction(pub(crate) AsyncCallback<'static>);
-impl<'lua> Function<'lua> {
+impl Function {
/// Wraps a Rust function or closure, returning an opaque type that implements [`IntoLua`] trait.
#[inline]
pub fn wrap<A, R, F>(func: F) -> impl IntoLua
where
- A: FromLuaMulti<'lua>,
+ A: FromLuaMulti,
R: IntoLuaMulti,
- F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
+ F: Fn(&Lua, A) -> Result<R> + MaybeSend + 'static,
{
WrappedFunction(Box::new(move |lua, nargs| unsafe {
let args = A::from_stack_args(nargs, 1, None, lua)?;
- func(lua, args)?.push_into_stack_multi(lua)
+ func(lua.lua(), args)?.push_into_stack_multi(lua)
}))
}
@@ -595,9 +538,9 @@ impl<'lua> Function<'lua> {
#[inline]
pub fn wrap_mut<A, R, F>(func: F) -> impl IntoLua
where
- A: FromLuaMulti<'lua>,
+ A: FromLuaMulti,
R: IntoLuaMulti,
- F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
+ F: FnMut(&Lua, A) -> Result<R> + MaybeSend + 'static,
{
let func = RefCell::new(func);
WrappedFunction(Box::new(move |lua, nargs| unsafe {
@@ -605,7 +548,7 @@ impl<'lua> Function<'lua> {
.try_borrow_mut()
.map_err(|_| Error::RecursiveMutCallback)?;
let args = A::from_stack_args(nargs, 1, None, lua)?;
- func(lua, args)?.push_into_stack_multi(lua)
+ func(lua.lua(), args)?.push_into_stack_multi(lua)
}))
}
@@ -614,45 +557,44 @@ impl<'lua> Function<'lua> {
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub fn wrap_async<A, R, F, FR>(func: F) -> impl IntoLua
where
- A: FromLuaMulti<'lua>,
+ A: FromLuaMulti,
R: IntoLuaMulti,
- F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
+ F: Fn(&Lua, A) -> FR + MaybeSend + 'static,
FR: Future<Output = Result<R>> + 'static,
{
- WrappedAsyncFunction(Box::new(move |lua, args| unsafe {
+ WrappedAsyncFunction(Box::new(move |rawlua, args| unsafe {
+ let lua = rawlua.lua();
let args = match A::from_lua_args(args, 1, None, lua) {
Ok(args) => args,
Err(e) => return Box::pin(future::err(e)),
};
let fut = func(lua, args);
- Box::pin(async move { fut.await?.push_into_stack_multi(lua) })
+ let weak = rawlua.weak().clone();
+ Box::pin(async move { fut.await?.push_into_stack_multi(&weak.lock()) })
}))
}
}
-impl IntoLua for WrappedFunction<'_> {
+impl IntoLua for WrappedFunction {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
- lua.create_callback(unsafe { mem::transmute(self.0) })
- .map(Value::Function)
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
+ lua.lock().create_callback(self.0).map(Value::Function)
}
}
#[cfg(feature = "async")]
-impl IntoLua for WrappedAsyncFunction<'_> {
+impl IntoLua for WrappedAsyncFunction {
#[inline]
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
- lua.create_async_callback(unsafe { mem::transmute(self.0) })
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
+ lua.lock()
+ .create_async_callback(self.0)
.map(Value::Function)
}
}
-#[cfg(test)]
-mod assertions {
- use super::*;
+// #[cfg(test)]
+// mod assertions {
+// use super::*;
- static_assertions::assert_not_impl_any!(Function: Send);
-
- #[cfg(all(feature = "unstable", not(feature = "send")))]
- static_assertions::assert_not_impl_any!(OwnedFunction: Send);
-}
+// static_assertions::assert_not_impl_any!(Function: Send);
+// }
diff --git a/src/hook.rs b/src/hook.rs
index 950bc79..72f8b88 100644
--- a/src/hook.rs
+++ b/src/hook.rs
@@ -1,12 +1,14 @@
use std::borrow::Cow;
use std::cell::UnsafeCell;
+use std::mem::ManuallyDrop;
#[cfg(not(feature = "luau"))]
use std::ops::{BitOr, BitOrAssign};
use std::os::raw::c_int;
use ffi::lua_Debug;
+use parking_lot::ReentrantMutexGuard;
-use crate::lua::Lua;
+use crate::lua::{Lua, LuaInner};
use crate::util::{linenumber_to_usize, ptr_to_lossy_str, ptr_to_str};
/// Contains information about currently executing Lua code.
@@ -19,24 +21,37 @@ use crate::util::{linenumber_to_usize, ptr_to_lossy_str, ptr_to_str};
/// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#lua_Debug
/// [`Lua::set_hook`]: crate::Lua::set_hook
pub struct Debug<'lua> {
- lua: &'lua Lua,
+ lua: ManuallyDrop<ReentrantMutexGuard<'lua, LuaInner>>,
ar: ActivationRecord,
#[cfg(feature = "luau")]
level: c_int,
}
+impl<'lua> Drop for Debug<'lua> {
+ fn drop(&mut self) {
+ if let ActivationRecord::Owned(_) = self.ar {
+ unsafe { ManuallyDrop::drop(&mut self.lua) }
+ }
+ }
+}
+
impl<'lua> Debug<'lua> {
+ // We assume the lock is held when this function is called.
#[cfg(not(feature = "luau"))]
pub(crate) fn new(lua: &'lua Lua, ar: *mut lua_Debug) -> Self {
Debug {
- lua,
+ lua: unsafe { lua.guard_unchecked() },
ar: ActivationRecord::Borrowed(ar),
}
}
- pub(crate) fn new_owned(lua: &'lua Lua, _level: c_int, ar: lua_Debug) -> Self {
+ pub(crate) fn new_owned(
+ guard: ReentrantMutexGuard<'lua, LuaInner>,
+ _level: c_int,
+ ar: lua_Debug,
+ ) -> Self {
Debug {
- lua,
+ lua: ManuallyDrop::new(guard),
ar: ActivationRecord::Owned(UnsafeCell::new(ar)),
#[cfg(feature = "luau")]
level: _level,
diff --git a/src/lib.rs b/src/lib.rs
index 9345f5f..d1faffd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -89,13 +89,14 @@ mod lua;
mod luau;
mod memory;
mod multi;
-mod scope;
+// mod scope;
mod stdlib;
mod string;
mod table;
mod thread;
mod types;
mod userdata;
+mod userdata_cell;
mod userdata_ext;
mod userdata_impl;
mod util;
@@ -111,7 +112,7 @@ pub use crate::function::{Function, FunctionInfo};
pub use crate::hook::{Debug, DebugEvent, DebugNames, DebugSource, DebugStack};
pub use crate::lua::{GCMode, Lua, LuaOptions};
pub use crate::multi::Variadic;
-pub use crate::scope::Scope;
+// pub use crate::scope::Scope;
pub use crate::stdlib::StdLib;
pub use crate::string::String;
pub use crate::table::{Table, TableExt, TablePairs, TableSequence};
@@ -119,8 +120,8 @@ pub use crate::thread::{Thread, ThreadStatus};
pub use crate::types::{AppDataRef, AppDataRefMut, Integer, LightUserData, Number, RegistryKey};
pub use crate::userdata::{
AnyUserData, MetaMethod, UserData, UserDataFields, UserDataMetatable, UserDataMethods,
- UserDataRef, UserDataRefMut,
};
+pub use crate::userdata_cell::{UserDataRef, UserDataRefMut};
pub use crate::userdata_ext::AnyUserDataExt;
pub use crate::userdata_impl::UserDataRegistry;
pub use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, MultiValue, Nil, Value};
@@ -154,13 +155,6 @@ pub mod serde;
#[macro_use]
extern crate mlua_derive;
-// Unstable features
-#[cfg(feature = "unstable")]
-pub use crate::{
- function::OwnedFunction, string::OwnedString, table::OwnedTable, thread::OwnedThread,
- userdata::OwnedAnyUserData,
-};
-
/// Create a type that implements [`AsChunk`] and can capture Rust variables.
///
/// This macro allows to write Lua code directly in Rust code.
@@ -279,6 +273,6 @@ pub(crate) mod private {
impl Sealed for Error {}
impl<T> Sealed for std::result::Result<T, Error> {}
impl Sealed for Lua {}
- impl Sealed for Table<'_> {}
- impl Sealed for AnyUserData<'_> {}
+ impl Sealed for Table {}
+ impl Sealed for AnyUserData {}
}
diff --git a/src/lua.rs b/src/lua.rs
index df34c25..44472d5 100644
--- a/src/lua.rs
+++ b/src/lua.rs
@@ -1,17 +1,18 @@
use std::any::TypeId;
use std::cell::{Cell, RefCell, UnsafeCell};
-use std::collections::VecDeque;
+// use std::collections::VecDeque;
use std::ffi::{CStr, CString};
use std::fmt;
use std::marker::PhantomData;
-use std::mem::{self, MaybeUninit};
+use std::mem::{self, ManuallyDrop, MaybeUninit};
use std::ops::Deref;
use std::os::raw::{c_char, c_int, c_void};
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe, Location};
use std::ptr;
use std::result::Result as StdResult;
-use std::sync::{Arc, Mutex};
+use std::sync::{Arc, Weak};
+use parking_lot::{Mutex, ReentrantMutex, ReentrantMutexGuard};
use rustc_hash::FxHashMap;
use crate::chunk::{AsChunk, Chunk, ChunkMode};
@@ -19,16 +20,18 @@ use crate::error::{Error, Result};
use crate::function::Function;
use crate::hook::Debug;
use crate::memory::{MemoryState, ALLOCATOR};
-use crate::scope::Scope;
+// use crate::scope::Scope;
use crate::stdlib::StdLib;
use crate::string::String;
use crate::table::Table;
use crate::thread::Thread;
use crate::types::{
- AppData, AppDataRef, AppDataRefMut, Callback, CallbackUpvalue, DestructedUserdata, Integer,
- LightUserData, MaybeSend, Number, RegistryKey, SubtypeId, ValueRef,
+ AppData, AppDataRef, AppDataRefMut, ArcReentrantMutexGuard, Callback, CallbackUpvalue,
+ DestructedUserdata, Integer, LightUserData, MaybeSend, Number, RegistryKey, SubtypeId,
+ ValueRef,
};
-use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataCell};
+use crate::userdata::{AnyUserData, MetaMethod, UserData};
+use crate::userdata_cell::{UserDataRef, UserDataVariant};
use crate::userdata_impl::{UserDataProxy, UserDataRegistry};
use crate::util::{
self, assert_stack, check_stack, error_traceback, get_destructed_userdata_metatable,
@@ -66,8 +69,15 @@ use {
use serde::Serialize;
/// Top level Lua struct which represents an instance of Lua VM.
+#[derive(Clone)]
#[repr(transparent)]
-pub struct Lua(Arc<LuaInner>);
+pub struct Lua(Arc<ReentrantMutex<LuaInner>>);
+
+#[derive(Clone)]
+#[repr(transparent)]
+pub(crate) struct WeakLua(Weak<ReentrantMutex<LuaInner>>);
+
+pub(crate) struct LuaGuard(ArcReentrantMutexGuard<LuaInner>);
/// An inner Lua struct which holds a raw Lua state.
pub struct LuaInner {
@@ -80,7 +90,8 @@ pub struct LuaInner {
// Data associated with the Lua.
pub(crate) struct ExtraData {
// Same layout as `Lua`
- inner: MaybeUninit<Arc<LuaInner>>,
+ inner: MaybeUninit<Arc<ReentrantMutex<LuaInner>>>,
+ weak: MaybeUninit<Weak<ReentrantMutex<LuaInner>>>,
registered_userdata: FxHashMap<TypeId, c_int>,
registered_userdata_mt: FxHashMap<*const c_void, Option<TypeId>>,
@@ -106,7 +117,7 @@ pub(crate) struct ExtraData {
// Pool of `WrappedFailure` enums in the ref thread (as userdata)
wrapped_failure_pool: Vec<c_int>,
// Pool of `MultiValue` containers
- multivalue_pool: Vec<VecDeque<Value<'static>>>,
+ // multivalue_pool: Vec<VecDeque<Value>>,
// Pool of `Thread`s (coroutines) for async execution
#[cfg(feature = "async")]
thread_pool: Vec<c_int>,
@@ -225,7 +236,7 @@ pub(crate) static ASYNC_POLL_PENDING: u8 = 0;
pub(crate) static EXTRA_REGISTRY_KEY: u8 = 0;
const WRAPPED_FAILURE_POOL_SIZE: usize = 64;
-const MULTIVALUE_POOL_SIZE: usize = 64;
+// const MULTIVALUE_POOL_SIZE: usize = 64;
const REF_STACK_RESERVE: c_int = 1;
/// Requires `feature = "send"`
@@ -262,23 +273,14 @@ impl Drop for ExtraData {
unsafe {
self.inner.assume_init_drop();
}
-
- *mlua_expect!(self.registry_unref_list.lock(), "unref list poisoned") = None;
+ unsafe { self.weak.assume_init_drop() };
+ *self.registry_unref_list.lock() = None;
}
}
impl fmt::Debug for Lua {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "Lua({:p})", self.state())
- }
-}
-
-impl Deref for Lua {
- type Target = LuaInner;
-
- #[inline]
- fn deref(&self) -> &Self::Target {
- &self.0
+ write!(f, "Lua({:p})", self.lock().state())
}
}
@@ -344,7 +346,10 @@ impl Lua {
if libs.contains(StdLib::PACKAGE) {
mlua_expect!(lua.disable_c_modules(), "Error during disabling C modules");
}
- unsafe { (*lua.extra.get()).safe = true };
+ unsafe {
+ let rawlua = lua.lock();
+ (*rawlua.extra.get()).safe = true;
+ }
Ok(lua)
}
@@ -400,7 +405,7 @@ impl Lua {
}
let lua = Lua::init_from_ptr(state);
- let extra = lua.extra.get();
+ let extra = lua.lock().extra.get();
mlua_expect!(
load_from_std_lib(state, libs),
@@ -510,6 +515,7 @@ impl Lua {
// Create ExtraData
let extra = Arc::new(UnsafeCell::new(ExtraData {
inner: MaybeUninit::uninit(),
+ weak: MaybeUninit::uninit(),
registered_userdata: FxHashMap::default(),
registered_userdata_mt: FxHashMap::default(),
last_checked_userdata_mt: (ptr::null(), None),
@@ -525,7 +531,7 @@ impl Lua {
ref_stack_top: ffi::lua_gettop(ref_thread),
ref_free: Vec::new(),
wrapped_failure_pool: Vec::with_capacity(WRAPPED_FAILURE_POOL_SIZE),
- multivalue_pool: Vec::with_capacity(MULTIVALUE_POOL_SIZE),
+ // multivalue_pool: Vec::with_capacity(MULTIVALUE_POOL_SIZE),
#[cfg(feature = "async")]
thread_pool: Vec::new(),
wrapped_failure_mt_ptr,
@@ -568,15 +574,16 @@ impl Lua {
);
assert_stack(main_state, ffi::LUA_MINSTACK);
- let inner = Arc::new(LuaInner {
+ let inner = Arc::new(ReentrantMutex::new(LuaInner {
state: Cell::new(state),
main_state,
extra: Arc::clone(&extra),
- });
+ }));
(*extra.get()).inner.write(Arc::clone(&inner));
#[cfg(not(feature = "module"))]
Arc::decrement_strong_count(Arc::as_ptr(&inner));
+ (*extra.get()).weak.write(Arc::downgrade(&inner));
Lua(inner)
}
@@ -587,7 +594,8 @@ impl Lua {
///
/// [`StdLib`]: crate::StdLib
pub fn load_from_std_lib(&self, libs: StdLib) -> Result<()> {
- let is_safe = unsafe { (*self.extra.get()).safe };
+ let lua = self.lock();
+ let is_safe = unsafe { (*lua.extra.get()).safe };
#[cfg(not(feature = "luau"))]
if is_safe && libs.contains(StdLib::DEBUG) {
@@ -602,14 +610,14 @@ impl Lua {
));
}
- let res = unsafe { load_from_std_lib(self.main_state, libs) };
+ let res = unsafe { load_from_std_lib(lua.main_state, libs) };
// If `package` library loaded into a safe lua state then disable C modules
- let curr_libs = unsafe { (*self.extra.get()).libs };
+ let curr_libs = unsafe { (*lua.extra.get()).libs };
if is_safe && (curr_libs ^ (curr_libs | libs)).contains(StdLib::PACKAGE) {
mlua_expect!(self.disable_c_modules(), "Error during disabling C modules");
}
- unsafe { (*self.extra.get()).libs |= libs };
+ unsafe { (*lua.extra.get()).libs |= libs };
res
}
@@ -629,18 +637,19 @@ impl Lua {
/// Behavior is similar to Lua's [`require`] function.
///
/// [`require`]: https://www.lua.org/manual/5.4/manual.html#pdf-require
- pub fn load_from_function<'lua, T>(&'lua self, modname: &str, func: Function<'lua>) -> Result<T>
+ pub fn load_from_function<T>(&self, modname: &str, func: Function) -> Result<T>
where
- T: FromLua<'lua>,
+ T: FromLua,
{
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
let loaded = unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 2)?;
protect_lua!(state, 0, 1, fn(state) {
ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, cstr!("_LOADED"));
})?;
- Table(self.pop_ref())
+ Table(lua.pop_ref())
};
let modname = self.create_string(modname)?;
@@ -666,14 +675,15 @@ impl Lua {
///
/// [`package.loaded`]: https://www.lua.org/manual/5.4/manual.html#pdf-package.loaded
pub fn unload(&self, modname: &str) -> Result<()> {
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
let loaded = unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 2)?;
protect_lua!(state, 0, 1, fn(state) {
ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, cstr!("_LOADED"));
})?;
- Table(self.pop_ref())
+ Table(lua.pop_ref())
};
let modname = self.create_string(modname)?;
@@ -709,22 +719,23 @@ impl Lua {
// The returned value then pushed onto the stack.
#[doc(hidden)]
#[cfg(not(tarpaulin_include))]
- pub unsafe fn entrypoint<'lua, A, R, F>(self, state: *mut ffi::lua_State, func: F) -> c_int
+ pub unsafe fn entrypoint<A, R, F>(self, state: *mut ffi::lua_State, func: F) -> c_int
where
- A: FromLuaMulti<'lua>,
+ A: FromLuaMulti,
R: IntoLua,
- F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
+ F: Fn(&Lua, A) -> Result<R> + MaybeSend + 'static,
{
- let extra = self.extra.get();
+ let extra = self.lock().extra.get();
// `self` is no longer needed and must be dropped at this point to avoid possible memory leak
// in case of possible longjmp (lua_error) below
drop(self);
callback_error_ext(state, extra, move |nargs| {
- let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
- let _guard = StateGuard::new(&lua.0, state);
- let args = A::from_stack_args(nargs, 1, None, lua)?;
- func(lua, args)?.push_into_stack(lua)?;
+ let lua = (*extra).lua();
+ let rawlua = lua.lock();
+ let _guard = StateGuard::new(&rawlua, state);
+ let args = A::from_stack_args(nargs, 1, None, &rawlua)?;
+ func(lua, args)?.push_into_stack(&rawlua)?;
Ok(1)
})
}
@@ -732,10 +743,10 @@ impl Lua {
// A simple module entrypoint without arguments
#[doc(hidden)]
#[cfg(not(tarpaulin_include))]
- pub unsafe fn entrypoint1<'lua, R, F>(self, state: *mut ffi::lua_State, func: F) -> c_int
+ pub unsafe fn entrypoint1<R, F>(self, state: *mut ffi::lua_State, func: F) -> c_int
where
R: IntoLua,
- F: Fn(&'lua Lua) -> Result<R> + MaybeSend + 'static,
+ F: Fn(&Lua) -> Result<R> + MaybeSend + 'static,
{
self.entrypoint(state, move |lua, _: ()| func(lua))
}
@@ -778,9 +789,10 @@ impl Lua {
#[cfg(any(feature = "luau", docsrs))]
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
pub fn sandbox(&self, enabled: bool) -> Result<()> {
+ let lua = self.lock();
unsafe {
- if (*self.extra.get()).sandboxed != enabled {
- let state = self.main_state;
+ if (*lua.extra.get()).sandboxed != enabled {
+ let state = lua.main_state;
check_stack(state, 3)?;
protect_lua!(state, 0, 0, |state| {
if enabled {
@@ -788,12 +800,12 @@ impl Lua {
ffi::luaL_sandboxthread(state);
} else {
// Restore original `LUA_GLOBALSINDEX`
- ffi::lua_xpush(self.ref_thread(), state, ffi::LUA_GLOBALSINDEX);
+ ffi::lua_xpush(lua.ref_thread(), state, ffi::LUA_GLOBALSINDEX);
ffi::lua_replace(state, ffi::LUA_GLOBALSINDEX);
ffi::luaL_sandbox(state, 0);
}
})?;
- (*self.extra.get()).sandboxed = enabled;
+ (*lua.extra.get()).sandboxed = enabled;
}
Ok(())
}
@@ -843,42 +855,8 @@ impl Lua {
where
F: Fn(&Lua, Debug) -> Result<()> + MaybeSend + 'static,
{
- unsafe { self.set_thread_hook(self.state(), triggers, callback) };
- }
-
- /// Sets a 'hook' function for a thread (coroutine).
- #[cfg(not(feature = "luau"))]
- pub(crate) unsafe fn set_thread_hook<F>(
- &self,
- state: *mut ffi::lua_State,
- triggers: HookTriggers,
- callback: F,
- ) where
- F: Fn(&Lua, Debug) -> Result<()> + MaybeSend + 'static,
- {
- unsafe extern "C-unwind" fn hook_proc(state: *mut ffi::lua_State, ar: *mut ffi::lua_Debug) {
- let extra = extra_data(state);
- if (*extra).hook_thread != state {
- // Hook was destined for a different thread, ignore
- ffi::lua_sethook(state, None, 0, 0);
- return;
- }
- callback_error_ext(state, extra, move |_| {
- let hook_cb = (*extra).hook_callback.clone();
- let hook_cb = mlua_expect!(hook_cb, "no hook callback set in hook_proc");
- if Arc::strong_count(&hook_cb) > 2 {
- return Ok(()); // Don't allow recursion
- }
- let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
- let _guard = StateGuard::new(&lua.0, state);
- let debug = Debug::new(lua, ar);
- hook_cb(lua, debug)
- })
- }
-
- (*self.extra.get()).hook_callback = Some(Arc::new(callback));
- (*self.extra.get()).hook_thread = state; // Mark for what thread the hook is set
- ffi::lua_sethook(state, Some(hook_proc), triggers.mask(), triggers.count());
+ let lua = self.lock();
+ unsafe { lua.set_thread_hook(lua.state(), triggers, callback) };
}
/// Removes any hook previously set by [`Lua::set_hook()`] or [`Thread::set_hook()`].
@@ -887,18 +865,19 @@ impl Lua {
#[cfg(not(feature = "luau"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
pub fn remove_hook(&self) {
+ let lua = self.lock();
unsafe {
- let state = self.state();
+ let state = lua.state();
ffi::lua_sethook(state, None, 0, 0);
- match get_main_state(self.main_state) {
+ match get_main_state(lua.main_state) {
Some(main_state) if !ptr::eq(state, main_state) => {
// If main_state is different from state, remove hook from it too
ffi::lua_sethook(main_state, None, 0, 0);
}
_ => {}
};
- (*self.extra.get()).hook_callback = None;
- (*self.extra.get()).hook_thread = ptr::null_mut();
+ (*lua.extra.get()).hook_callback = None;
+ (*lua.extra.get()).hook_thread = ptr::null_mut();
}
}
@@ -963,8 +942,9 @@ impl Lua {
if Arc::strong_count(&interrupt_cb) > 2 {
return Ok(VmState::Continue); // Don't allow recursion
}
- let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
- let _guard = StateGuard::new(&lua.0, state);
+ let lua = (*extra).lua();
+ let rawlua = lua.lock();
+ let _guard = StateGuard::new(&rawlua, state);
interrupt_cb(lua)
});
match result {
@@ -975,9 +955,10 @@ impl Lua {
}
}
+ let lua = self.lock();
unsafe {
- (*self.extra.get()).interrupt_callback = Some(Arc::new(callback));
- (*ffi::lua_callbacks(self.main_state)).interrupt = Some(interrupt_proc);
+ (*lua.extra.get()).interrupt_callback = Some(Arc::new(callback));
+ (*ffi::lua_callbacks(lua.main_state)).interrupt = Some(interrupt_proc);
}
}
@@ -987,9 +968,10 @@ impl Lua {
#[cfg(any(feature = "luau", docsrs))]
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
pub fn remove_interrupt(&self) {
+ let lua = self.lock();
unsafe {
- (*self.extra.get()).interrupt_callback = None;
- (*ffi::lua_callbacks(self.main_state)).interrupt = None;
+ (*lua.extra.get()).interrupt_callback = None;
+ (*ffi::lua_callbacks(lua.main_state)).interrupt = None;
}
}
@@ -1004,8 +986,9 @@ impl Lua {
{
unsafe extern "C-unwind" fn warn_proc(ud: *mut c_void, msg: *const c_char, tocont: c_int) {
let extra = ud as *mut ExtraData;
- let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
- callback_error_ext(lua.state(), extra, |_| {
+ let lua = (*extra).lua();
+ let rawlua = lua.lock();
+ callback_error_ext(rawlua.state(), extra, |_| {
let cb = mlua_expect!(
(*extra).warn_callback.as_ref(),
"no warning callback set in warn_proc"
@@ -1015,10 +998,11 @@ impl Lua {
});
}
- let state = self.main_state;
+ let lua = self.lock();
+ let state = lua.main_state;
unsafe {
- (*self.extra.get()).warn_callback = Some(Box::new(callback));
- ffi::lua_setwarnf(state, Some(warn_proc), self.extra.get() as *mut c_void);
+ (*lua.extra.get()).warn_callback = Some(Box::new(callback));
+ ffi::lua_setwarnf(state, Some(warn_proc), lua.extra.get() as *mut c_void);
}
}
@@ -1030,9 +1014,10 @@ impl Lua {
#[cfg(feature = "lua54")]
#[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
pub fn remove_warning_function(&self) {
+ let lua = self.lock();
unsafe {
- (*self.extra.get()).warn_callback = None;
- ffi::lua_setwarnf(self.main_state, None, ptr::null_mut());
+ (*lua.extra.get()).warn_callback = None;
+ ffi::lua_setwarnf(lua.main_state, None, ptr::null_mut());
}
}
@@ -1050,9 +1035,10 @@ impl Lua {
bytes[..msg.len()].copy_from_slice(msg.as_bytes());
let real_len = bytes.iter().position(|&c| c == 0).unwrap();
bytes.truncate(real_len);
+ let lua = self.lock();
unsafe {
ffi::lua_warning(
- self.state(),
+ lua.state(),
bytes.as_ptr() as *const c_char,
incomplete as c_int,
);
@@ -1067,30 +1053,32 @@ impl Lua {
///
/// [`Debug`]: crate::hook::Debug
pub fn inspect_stack(&self, level: usize) -> Option<Debug> {
+ let lua = self.lock();
unsafe {
let mut ar: ffi::lua_Debug = mem::zeroed();
let level = level as c_int;
#[cfg(not(feature = "luau"))]
- if ffi::lua_getstack(self.state(), level, &mut ar) == 0 {
+ if ffi::lua_getstack(lua.state(), level, &mut ar) == 0 {
return None;
}
#[cfg(feature = "luau")]
- if ffi::lua_getinfo(self.state(), level, cstr!(""), &mut ar) == 0 {
+ if ffi::lua_getinfo(lua.state(), level, cstr!(""), &mut ar) == 0 {
return None;
}
- Some(Debug::new_owned(self, level, ar))
+ Some(Debug::new_owned(lua, level, ar))
}
}
/// Returns the amount of memory (in bytes) currently used inside this Lua state.
pub fn used_memory(&self) -> usize {
+ let lua = self.lock();
unsafe {
- match MemoryState::get(self.main_state) {
+ match MemoryState::get(lua.main_state) {
mem_state if !mem_state.is_null() => (*mem_state).used_memory(),
_ => {
// Get data from the Lua GC
- let used_kbytes = ffi::lua_gc(self.main_state, ffi::LUA_GCCOUNT, 0);
- let used_kbytes_rem = ffi::lua_gc(self.main_state, ffi::LUA_GCCOUNTB, 0);
+ let used_kbytes = ffi::lua_gc(lua.main_state, ffi::LUA_GCCOUNT, 0);
+ let used_kbytes_rem = ffi::lua_gc(lua.main_state, ffi::LUA_GCCOUNTB, 0);
(used_kbytes as usize) * 1024 + (used_kbytes_rem as usize)
}
}
@@ -1105,8 +1093,9 @@ impl Lua {
///
/// Does not work in module mode where Lua state is managed externally.
pub fn set_memory_limit(&self, limit: usize) -> Result<usize> {
+ let lua = self.lock();
unsafe {
- match MemoryState::get(self.main_state) {
+ match MemoryState::get(lua.main_state) {
mem_state if !mem_state.is_null() => Ok((*mem_state).set_memory_limit(limit)),
_ => Err(Error::MemoryLimitNotAvailable),
}
@@ -1123,17 +1112,20 @@ impl Lua {
feature = "luau"
))]
pub fn gc_is_running(&self) -> bool {
- unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCISRUNNING, 0) != 0 }
+ let lua = self.lock();
+ unsafe { ffi::lua_gc(lua.main_state, ffi::LUA_GCISRUNNING, 0) != 0 }
}
/// Stop the Lua GC from running
pub fn gc_stop(&self) {
- unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCSTOP, 0) };
+ let lua = self.lock();
+ unsafe { ffi::lua_gc(lua.main_state, ffi::LUA_GCSTOP, 0) };
}
/// Restarts the Lua GC if it is not running
pub fn gc_restart(&self) {
- unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCRESTART, 0) };
+ let lua = self.lock();
+ unsafe { ffi::lua_gc(lua.main_state, ffi::LUA_GCRESTART, 0) };
}
/// Perform a full garbage-collection cycle.
@@ -1141,9 +1133,10 @@ impl Lua {
/// It may be necessary to call this function twice to collect all currently unreachable
/// objects. Once to finish the current gc cycle, and once to start and finish the next cycle.
pub fn gc_collect(&self) -> Result<()> {
+ let lua = self.lock();
unsafe {
- check_stack(self.main_state, 2)?;
- protect_lua!(self.main_state, 0, 0, fn(state) ffi::lua_gc(state, ffi::LUA_GCCOLLECT, 0))
+ check_stack(lua.main_state, 2)?;
+ protect_lua!(lua.main_state, 0, 0, fn(state) ffi::lua_gc(state, ffi::LUA_GCCOLLECT, 0))
}
}
@@ -1159,9 +1152,10 @@ impl Lua {
/// if `kbytes` is 0, then this is the same as calling `gc_step`. Returns true if this step has
/// finished a collection cycle.
pub fn gc_step_kbytes(&self, kbytes: c_int) -> Result<bool> {
+ let lua = self.lock();
unsafe {
- check_stack(self.main_state, 3)?;
- protect_lua!(self.main_state, 0, 0, |state| {
+ check_stack(lua.main_state, 3)?;
+ protect_lua!(lua.main_state, 0, 0, |state| {
ffi::lua_gc(state, ffi::LUA_GCSTEP, kbytes) != 0
})
}
@@ -1176,11 +1170,12 @@ impl Lua {
///
/// [documentation]: https://www.lua.org/manual/5.4/manual.html#2.5
pub fn gc_set_pause(&self, pause: c_int) -> c_int {
+ let lua = self.lock();
unsafe {
#[cfg(not(feature = "luau"))]
- return ffi::lua_gc(self.main_state, ffi::LUA_GCSETPAUSE, pause);
+ return ffi::lua_gc(lua.main_state, ffi::LUA_GCSETPAUSE, pause);
#[cfg(feature = "luau")]
- return ffi::lua_gc(self.main_state, ffi::LUA_GCSETGOAL, pause);
+ return ffi::lua_gc(lua.main_state, ffi::LUA_GCSETGOAL, pause);
}
}
@@ -1191,7 +1186,8 @@ impl Lua {
///
/// [documentation]: https://www.lua.org/manual/5.4/manual.html#2.5
pub fn gc_set_step_multiplier(&self, step_multiplier: c_int) -> c_int {
- unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCSETSTEPMUL, step_multiplier) }
+ let lua = self.lock();
+ unsafe { ffi::lua_gc(lua.main_state, ffi::LUA_GCSETSTEPMUL, step_multiplier) }
}
/// Changes the collector to incremental mode with the given parameters.
@@ -1201,7 +1197,8 @@ impl Lua {
///
/// [documentation]: https://www.lua.org/manual/5.4/manual.html#2.5.1
pub fn gc_inc(&self, pause: c_int, step_multiplier: c_int, step_size: c_int) -> GCMode {
- let state = self.main_state;
+ let lua = self.lock();
+ let state = lua.main_state;
#[cfg(any(
feature = "lua53",
@@ -1254,7 +1251,8 @@ impl Lua {
#[cfg(feature = "lua54")]
#[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
pub fn gc_gen(&self, minor_multiplier: c_int, major_multiplier: c_int) -> GCMode {
- let state = self.main_state;
+ let lua = self.lock();
+ let state = lua.main_state;
let prev_mode =
unsafe { ffi::lua_gc(state, ffi::LUA_GCGEN, minor_multiplier, major_multiplier) };
match prev_mode {
@@ -1275,7 +1273,8 @@ impl Lua {
#[cfg(any(feature = "luau", doc))]
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
pub fn set_compiler(&self, compiler: Compiler) {
- unsafe { (*self.extra.get()).compiler = Some(compiler) };
+ let lua = self.lock();
+ unsafe { (*lua.extra.get()).compiler = Some(compiler) };
}
/// Toggles JIT compilation mode for new chunks of code.
@@ -1311,62 +1310,16 @@ impl Lua {
///
/// [`Chunk::exec`]: crate::Chunk::exec
#[track_caller]
- pub fn load<'lua, 'a>(&'lua self, chunk: impl AsChunk<'lua, 'a>) -> Chunk<'lua, 'a> {
+ pub fn load<'a>(&self, chunk: impl AsChunk<'a>) -> Chunk<'a> {
let caller = Location::caller();
Chunk {
- lua: self,
+ lua: self.weak(),
name: chunk.name().unwrap_or_else(|| caller.to_string()),
env: chunk.environment(self),
mode: chunk.mode(),
source: chunk.source(),
#[cfg(feature = "luau")]
- compiler: unsafe { (*self.extra.get()).compiler.clone() },
- }
- }
-
- pub(crate) fn load_chunk<'lua>(
- &'lua self,
- name: Option<&CStr>,
- env: Option<Table>,
- mode: Option<ChunkMode>,
- source: &[u8],
- ) -> Result<Function<'lua>> {
- let state = self.state();
- unsafe {
- let _sg = StackGuard::new(state);
- check_stack(state, 1)?;
-
- let mode_str = match mode {
- Some(ChunkMode::Binary) => cstr!("b"),
- Some(ChunkMode::Text) => cstr!("t"),
- None => cstr!("bt"),
- };
-
- match ffi::luaL_loadbufferx(
- state,
- source.as_ptr() as *const c_char,
- source.len(),
- name.map(|n| n.as_ptr()).unwrap_or_else(ptr::null),
- mode_str,
- ) {
- ffi::LUA_OK => {
- if let Some(env) = env {
- self.push_ref(&env.0);
- #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
- ffi::lua_setupvalue(state, -2, 1);
- #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
- ffi::lua_setfenv(state, -2);
- }
-
- #[cfg(feature = "luau-jit")]
- if (*self.extra.get()).enable_jit && ffi::luau_codegen_supported() != 0 {
- ffi::luau_codegen_compile(state, -1);
- }
-
- Ok(Function(self.pop_ref()))
- }
- err => Err(pop_error(state, err)),
- }
+ compiler: unsafe { (*self.lock().extra.get()).compiler.clone() },
}
}
@@ -1374,17 +1327,18 @@ impl Lua {
/// embedded nulls, so in addition to `&str` and `&String`, you can also pass plain `&[u8]`
/// here.
pub fn create_string(&self, s: impl AsRef<[u8]>) -> Result<String> {
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
unsafe {
- if self.unlikely_memory_error() {
- push_string(self.ref_thread(), s.as_ref(), false)?;
- return Ok(String(self.pop_ref_thread()));
+ if lua.unlikely_memory_error() {
+ push_string(lua.ref_thread(), s.as_ref(), false)?;
+ return Ok(String(lua.pop_ref_thread()));
}
let _sg = StackGuard::new(state);
check_stack(state, 3)?;
push_string(state, s.as_ref(), true)?;
- Ok(String(self.pop_ref()))
+ Ok(String(lua.pop_ref()))
}
}
@@ -1395,17 +1349,18 @@ impl Lua {
/// [buffer]: https://luau-lang.org/library#buffer-library
#[cfg(feature = "luau")]
pub fn create_buffer(&self, buf: impl AsRef<[u8]>) -> Result<AnyUserData> {
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
unsafe {
- if self.unlikely_memory_error() {
- crate::util::push_buffer(self.ref_thread(), buf.as_ref(), false)?;
- return Ok(AnyUserData(self.pop_ref_thread(), SubtypeId::Buffer));
+ if lua.unlikely_memory_error() {
+ crate::util::push_buffer(lua.ref_thread(), buf.as_ref(), false)?;
+ return Ok(AnyUserData(lua.pop_ref_thread(), SubtypeId::Buffer));
}
let _sg = StackGuard::new(state);
check_stack(state, 4)?;
crate::util::push_buffer(state, buf.as_ref(), true)?;
- Ok(AnyUserData(self.pop_ref(), SubtypeId::Buffer))
+ Ok(AnyUserData(lua.pop_ref(), SubtypeId::Buffer))
}
}
@@ -1419,39 +1374,41 @@ impl Lua {
/// `nrec` is a hint for how many other elements the table will have.
/// Lua may use these hints to preallocate memory for the new table.
pub fn create_table_with_capacity(&self, narr: usize, nrec: usize) -> Result<Table> {
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
unsafe {
- if self.unlikely_memory_error() {
- push_table(self.ref_thread(), narr, nrec, false)?;
- return Ok(Table(self.pop_ref_thread()));
+ if lua.unlikely_memory_error() {
+ push_table(lua.ref_thread(), narr, nrec, false)?;
+ return Ok(Table(lua.pop_ref_thread()));
}
let _sg = StackGuard::new(state);
check_stack(state, 3)?;
push_table(state, narr, nrec, true)?;
- Ok(Table(self.pop_ref()))
+ Ok(Table(lua.pop_ref()))
}
}
/// Creates a table and fills it with values from an iterator.
- pub fn create_table_from<'lua, K, V, I>(&'lua self, iter: I) -> Result<Table<'lua>>
+ pub fn create_table_from<K, V, I>(&self, iter: I) -> Result<Table>
where
K: IntoLua,
V: IntoLua,
I: IntoIterator<Item = (K, V)>,
{
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 6)?;
let iter = iter.into_iter();
let lower_bound = iter.size_hint().0;
- let protect = !self.unlikely_memory_error();
+ let protect = !lua.unlikely_memory_error();
push_table(state, 0, lower_bound, protect)?;
for (k, v) in iter {
- self.push(k)?;
- self.push(v)?;
+ lua.push(k)?;
+ lua.push(v)?;
if protect {
protect_lua!(state, 3, 1, fn(state) ffi::lua_rawset(state, -3))?;
} else {
@@ -1459,27 +1416,28 @@ impl Lua {
}
}
- Ok(Table(self.pop_ref()))
+ Ok(Table(lua.pop_ref()))
}
}
/// Creates a table from an iterator of values, using `1..` as the keys.
- pub fn create_sequence_from<'lua, T, I>(&'lua self, iter: I) -> Result<Table<'lua>>
+ pub fn create_sequence_from<T, I>(&self, iter: I) -> Result<Table>
where
T: IntoLua,
I: IntoIterator<Item = T>,
{
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 5)?;
let iter = iter.into_iter();
let lower_bound = iter.size_hint().0;
- let protect = !self.unlikely_memory_error();
+ let protect = !lua.unlikely_memory_error();
push_table(state, lower_bound, 0, protect)?;
for (i, v) in iter.enumerate() {
- self.push(v)?;
+ lua.push(v)?;
if protect {
protect_lua!(state, 2, 1, |state| {
ffi::lua_rawseti(state, -2, (i + 1) as Integer);
@@ -1489,7 +1447,7 @@ impl Lua {
}
}
- Ok(Table(self.pop_ref()))
+ Ok(Table(lua.pop_ref()))
}
}
@@ -1538,15 +1496,16 @@ impl Lua {
///
/// [`IntoLua`]: crate::IntoLua
/// [`IntoLuaMulti`]: crate::IntoLuaMulti
- pub fn create_function<'lua, A, R, F>(&'lua self, func: F) -> Result<Function<'lua>>
+ pub fn create_function<A, R, F>(&self, func: F) -> Result<Function>
where
- A: FromLuaMulti<'lua>,
+ A: FromLuaMulti,
R: IntoLuaMulti,
- F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
+ F: Fn(&Lua, A) -> Result<R> + MaybeSend + 'static,
{
- self.create_callback(Box::new(move |lua, nargs| unsafe {
+ let lua = self.lock();
+ lua.create_callback(Box::new(move |lua, nargs| unsafe {
let args = A::from_stack_args(nargs, 1, None, lua)?;
- func(lua, args)?.push_into_stack_multi(lua)
+ func(lua.lua(), args)?.push_into_stack_multi(lua)
}))
}
@@ -1556,11 +1515,11 @@ impl Lua {
/// [`create_function`] for more information about the implementation.
///
/// [`create_function`]: #method.create_function
- pub fn create_function_mut<'lua, A, R, F>(&'lua self, func: F) -> Result<Function<'lua>>
+ pub fn create_function_mut<A, R, F>(&self, func: F) -> Result<Function>
where
- A: FromLuaMulti<'lua>,
+ A: FromLuaMulti,
R: IntoLuaMulti,
- F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
+ F: FnMut(&Lua, A) -> Result<R> + MaybeSend + 'static,
{
let func = RefCell::new(func);
self.create_function(move |lua, args| {
@@ -1575,10 +1534,11 @@ impl Lua {
/// # Safety
/// This function is unsafe because provides a way to execute unsafe C function.
pub unsafe fn create_c_function(&self, func: ffi::lua_CFunction) -> Result<Function> {
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
check_stack(state, 1)?;
ffi::lua_pushcfunction(state, func);
- Ok(Function(self.pop_ref()))
+ Ok(Function(lua.pop_ref()))
}
/// Wraps a Rust async function or closure, creating a callable Lua function handle to it.
@@ -1622,104 +1582,32 @@ impl Lua {
/// [`AsyncThread`]: crate::AsyncThread
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- pub fn create_async_function<'lua, A, R, F, FR>(&'lua self, func: F) -> Result<Function<'lua>>
+ pub fn create_async_function<'lua, 'a, F, A, FR, R>(&'lua self, func: F) -> Result<Function>
where
- A: FromLuaMulti<'lua>,
+ 'lua: 'a,
+ F: Fn(&'a Lua, A) -> FR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ FR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti,
- F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
- FR: Future<Output = Result<R>> + 'lua,
{
- self.create_async_callback(Box::new(move |lua, args| unsafe {
+ let lua = self.lock();
+ lua.create_async_callback(Box::new(move |rawlua, args| unsafe {
+ // let rawlua = mem::transmute::<&LuaInner, &LuaInner>(rawlua);
+ let lua = rawlua.lua();
let args = match A::from_lua_args(args, 1, None, lua) {
Ok(args) => args,
Err(e) => return Box::pin(future::err(e)),
};
let fut = func(lua, args);
- Box::pin(async move { fut.await?.push_into_stack_multi(lua) })
+ Box::pin(async move { fut.await?.push_into_stack_multi(rawlua) })
}))
}
/// Wraps a Lua function into a new thread (or coroutine).
///
/// Equivalent to `coroutine.create`.
- pub fn create_thread<'lua>(&'lua self, func: Function) -> Result<Thread<'lua>> {
- self.create_thread_inner(&func)
- }
-
- /// Wraps a Lua function into a new thread (or coroutine).
- ///
- /// Takes function by reference.
- fn create_thread_inner<'lua>(&'lua self, func: &Function) -> Result<Thread<'lua>> {
- let state = self.state();
- unsafe {
- let _sg = StackGuard::new(state);
- check_stack(state, 3)?;
-
- let thread_state = if self.unlikely_memory_error() {
- ffi::lua_newthread(state)
- } else {
- protect_lua!(state, 0, 1, |state| ffi::lua_newthread(state))?
- };
- self.push_ref(&func.0);
- ffi::lua_xmove(state, thread_state, 1);
-
- Ok(Thread::new(self.pop_ref()))
- }
- }
-
- /// Wraps a Lua function into a new or recycled thread (coroutine).
- #[cfg(feature = "async")]
- pub(crate) fn create_recycled_thread<'lua>(
- &'lua self,
- func: &Function,
- ) -> Result<Thread<'lua>> {
- #[cfg(any(feature = "lua54", feature = "luau"))]
- unsafe {
- let state = self.state();
- let _sg = StackGuard::new(state);
- check_stack(state, 1)?;
-
- if let Some(index) = (*self.extra.get()).thread_pool.pop() {
- let thread_state = ffi::lua_tothread(self.ref_thread(), index);
- self.push_ref(&func.0);
- ffi::lua_xmove(state, thread_state, 1);
-
- #[cfg(feature = "luau")]
- {
- // Inherit `LUA_GLOBALSINDEX` from the caller
- ffi::lua_xpush(state, thread_state, ffi::LUA_GLOBALSINDEX);
- ffi::lua_replace(thread_state, ffi::LUA_GLOBALSINDEX);
- }
-
- return Ok(Thread::new(ValueRef::new(self, index)));
- }
- };
- self.create_thread_inner(func)
- }
-
- /// Resets thread (coroutine) and returns to the pool for later use.
- #[cfg(feature = "async")]
- #[cfg(any(feature = "lua54", feature = "luau"))]
- pub(crate) unsafe fn recycle_thread(&self, thread: &mut Thread) -> bool {
- let extra = &mut *self.extra.get();
- if extra.thread_pool.len() < extra.thread_pool.capacity() {
- let thread_state = ffi::lua_tothread(extra.ref_thread, thread.0.index);
- #[cfg(all(feature = "lua54", not(feature = "vendored")))]
- let status = ffi::lua_resetthread(thread_state);
- #[cfg(all(feature = "lua54", feature = "vendored"))]
- let status = ffi::lua_closethread(thread_state, self.state());
- #[cfg(feature = "lua54")]
- if status != ffi::LUA_OK {
- // Error object is on top, drop it
- ffi::lua_settop(thread_state, 0);
- }
- #[cfg(feature = "luau")]
- ffi::lua_resetthread(thread_state);
- extra.thread_pool.push(thread.0.index);
- thread.0.drop = false;
- return true;
- }
- false
+ pub fn create_thread(&self, func: Function) -> Result<Thread> {
+ self.lock().create_thread_inner(&func)
}
/// Creates a Lua userdata object from a custom userdata type.
@@ -1730,7 +1618,8 @@ impl Lua {
where
T: UserData + MaybeSend + 'static,
{
- unsafe { self.make_userdata(UserDataCell::new(data)) }
+ let lua = self.lock();
+ unsafe { lua.make_userdata(UserDataVariant::new(data)) }
}
/// Creates a Lua userdata object from a custom serializable userdata type.
@@ -1743,7 +1632,8 @@ impl Lua {
where
T: UserData + Serialize + MaybeSend + 'static,
{
- unsafe { self.make_userdata(UserDataCell::new_ser(data)) }
+ let lua = self.lock();
+ unsafe { lua.make_userdata(UserDataVariant::new_ser(data)) }
}
/// Creates a Lua userdata object from a custom Rust type.
@@ -1758,7 +1648,8 @@ impl Lua {
where
T: MaybeSend + 'static,
{
- unsafe { self.make_any_userdata(UserDataCell::new(data)) }
+ let lua = self.lock();
+ unsafe { lua.make_any_userdata(UserDataVariant::new(data)) }
}
/// Creates a Lua userdata object from a custom serializable Rust type.
@@ -1773,7 +1664,8 @@ impl Lua {
where
T: Serialize + MaybeSend + 'static,
{
- unsafe { self.make_any_userdata(UserDataCell::new_ser(data)) }
+ let lua = self.lock();
+ unsafe { lua.make_any_userdata(UserDataVariant::new_ser(data)) }
}
/// Registers a custom Rust type in Lua to use in userdata objects.
@@ -1786,17 +1678,18 @@ impl Lua {
let mut registry = UserDataRegistry::new();
f(&mut registry);
+ let lua = self.lock();
unsafe {
// Deregister the type if it already registered
let type_id = TypeId::of::<T>();
- if let Some(&table_id) = (*self.extra.get()).registered_userdata.get(&type_id) {
- ffi::luaL_unref(self.state(), ffi::LUA_REGISTRYINDEX, table_id);
+ if let Some(&table_id) = (*lua.extra.get()).registered_userdata.get(&type_id) {
+ ffi::luaL_unref(lua.state(), ffi::LUA_REGISTRYINDEX, table_id);
}
// Register the type
- self.register_userdata_metatable(registry)?;
- Ok(())
+ lua.register_userdata_metatable(registry)?;
}
+ Ok(())
}
/// Create a Lua userdata "proxy" object from a custom userdata type.
@@ -1816,11 +1709,11 @@ impl Lua {
/// struct MyUserData(i32);
///
/// impl UserData for MyUserData {
- /// fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
+ /// fn add_fields<'a, F: UserDataFields<'a, Self>>(fields: &mut F) {
/// fields.add_field_method_get("val", |_, this| Ok(this.0));
/// }
///
- /// fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ /// fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
/// methods.add_function("new", |_, value: i32| Ok(MyUserData(value)));
/// }
/// }
@@ -1836,7 +1729,8 @@ impl Lua {
where
T: UserData + 'static,
{
- unsafe { self.make_userdata(UserDataCell::new(UserDataProxy::<T>(PhantomData))) }
+ let lua = self.lock();
+ unsafe { lua.make_userdata(UserDataVariant::new(UserDataProxy::<T>(PhantomData))) }
}
/// Sets the metatable for a Luau builtin vector type.
@@ -1862,7 +1756,8 @@ impl Lua {
/// Returns a handle to the global environment.
pub fn globals(&self) -> Table {
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
assert_stack(state, 1);
@@ -1870,19 +1765,20 @@ impl Lua {
ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
ffi::lua_pushvalue(state, ffi::LUA_GLOBALSINDEX);
- Table(self.pop_ref())
+ Table(lua.pop_ref())
}
}
/// Returns a handle to the active `Thread`. For calls to `Lua` this will be the main Lua thread,
/// for parameters given to a callback, this will be whatever Lua thread called the callback.
pub fn current_thread(&self) -> Thread {
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
assert_stack(state, 1);
ffi::lua_pushthread(state);
- Thread::new(self.pop_ref())
+ Thread::new(&lua, lua.pop_ref())
}
}
@@ -1906,31 +1802,32 @@ impl Lua {
/// dropped. `Function` types will error when called, and `AnyUserData` will be typeless. It
/// would be impossible to prevent handles to scoped values from escaping anyway, since you
/// would always be able to smuggle them through Lua state.
- pub fn scope<'lua, 'scope, R>(
- &'lua self,
- f: impl FnOnce(&Scope<'lua, 'scope>) -> Result<R>,
- ) -> Result<R>
- where
- 'lua: 'scope,
- {
- f(&Scope::new(self))
- }
+ // pub fn scope<'lua, 'scope, R>(
+ // &'lua self,
+ // f: impl FnOnce(&Scope<'lua, 'scope>) -> Result<R>,
+ // ) -> Result<R>
+ // where
+ // 'lua: 'scope,
+ // {
+ // f(&Scope::new(self))
+ // }
/// Attempts to coerce a Lua value into a String in a manner consistent with Lua's internal
/// behavior.
///
/// To succeed, the value must be a string (in which case this is a no-op), an integer, or a
/// number.
- pub fn coerce_string<'lua>(&'lua self, v: Value<'lua>) -> Result<Option<String<'lua>>> {
+ pub fn coerce_string(&self, v: Value) -> Result<Option<String>> {
Ok(match v {
Value::String(s) => Some(s),
v => unsafe {
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
let _sg = StackGuard::new(state);
check_stack(state, 4)?;
- self.push_value(&v)?;
- let res = if self.unlikely_memory_error() {
+ lua.push_value(&v)?;
+ let res = if lua.unlikely_memory_error() {
ffi::lua_tolstring(state, -1, ptr::null_mut())
} else {
protect_lua!(state, 1, 1, |state| {
@@ -1938,7 +1835,7 @@ impl Lua {
})?
};
if !res.is_null() {
- Some(String(self.pop_ref()))
+ Some(String(lua.pop_ref()))
} else {
None
}
@@ -1956,11 +1853,12 @@ impl Lua {
Ok(match v {
Value::Integer(i) => Some(i),
v => unsafe {
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
let _sg = StackGuard::new(state);
check_stack(state, 2)?;
- self.push_value(&v)?;
+ lua.push_value(&v)?;
let mut isint = 0;
let i = ffi::lua_tointegerx(state, -1, &mut isint);
if isint == 0 {
@@ -1981,11 +1879,12 @@ impl Lua {
Ok(match v {
Value::Number(n) => Some(n),
v => unsafe {
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
let _sg = StackGuard::new(state);
check_stack(state, 2)?;
- self.push_value(&v)?;
+ lua.push_value(&v)?;
let mut isnum = 0;
let n = ffi::lua_tonumberx(state, -1, &mut isnum);
if isnum == 0 {
@@ -1998,25 +1897,22 @@ impl Lua {
}
/// Converts a value that implements `IntoLua` into a `Value` instance.
- pub fn pack<'lua, T: IntoLua>(&'lua self, t: T) -> Result<Value<'lua>> {
+ pub fn pack<T: IntoLua>(&self, t: T) -> Result<Value> {
t.into_lua(self)
}
/// Converts a `Value` instance into a value that implements `FromLua`.
- pub fn unpack<'lua, T: FromLua<'lua>>(&'lua self, value: Value<'lua>) -> Result<T> {
+ pub fn unpack<T: FromLua>(&self, value: Value) -> Result<T> {
T::from_lua(value, self)
}
/// Converts a value that implements `IntoLuaMulti` into a `MultiValue` instance.
- pub fn pack_multi<'lua, T: IntoLuaMulti>(&'lua self, t: T) -> Result<MultiValue<'lua>> {
+ pub fn pack_multi<T: IntoLuaMulti>(&self, t: T) -> Result<MultiValue> {
t.into_lua_multi(self)
}
/// Converts a `MultiValue` instance into a value that implements `FromLuaMulti`.
- pub fn unpack_multi<'lua, T: FromLuaMulti<'lua>>(
- &'lua self,
- value: MultiValue<'lua>,
- ) -> Result<T> {
+ pub fn unpack_multi<T: FromLuaMulti>(&self, value: MultiValue) -> Result<T> {
T::from_lua_multi(value, self)
}
@@ -2024,16 +1920,17 @@ impl Lua {
///
/// This value will be available to rust from all `Lua` instances which share the same main
/// state.
- pub fn set_named_registry_value<'lua, T>(&'lua self, name: &str, t: T) -> Result<()>
+ pub fn set_named_registry_value<T>(&self, name: &str, t: T) -> Result<()>
where
T: IntoLua,
{
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 5)?;
- self.push(t)?;
+ lua.push(t)?;
rawset_field(state, ffi::LUA_REGISTRYINDEX, name)
}
}
@@ -2044,20 +1941,21 @@ impl Lua {
/// get a value previously set by [`set_named_registry_value`].
///
/// [`set_named_registry_value`]: #method.set_named_registry_value
- pub fn named_registry_value<'lua, T>(&'lua self, name: &str) -> Result<T>
+ pub fn named_registry_value<T>(&self, name: &str) -> Result<T>
where
- T: FromLua<'lua>,
+ T: FromLua,
{
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 3)?;
- let protect = !self.unlikely_memory_error();
+ let protect = !lua.unlikely_memory_error();
push_string(state, name.as_bytes(), protect)?;
ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX);
- T::from_stack(-1, self)
+ T::from_stack(-1, &lua)
}
}
@@ -2081,14 +1979,15 @@ impl Lua {
///
/// [`RegistryKey`]: crate::RegistryKey
pub fn create_registry_value<T: IntoLua>(&self, t: T) -> Result<RegistryKey> {
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 4)?;
- self.push(t)?;
+ lua.push(t)?;
- let unref_list = (*self.extra.get()).registry_unref_list.clone();
+ let unref_list = (*lua.extra.get()).registry_unref_list.clone();
// Check if the value is nil (no need to store it in the registry)
if ffi::lua_isnil(state, -1) != 0 {
@@ -2096,9 +1995,7 @@ impl Lua {
}
// Try to reuse previously allocated slot
- let free_registry_id = mlua_expect!(unref_list.lock(), "unref list poisoned")
- .as_mut()
- .and_then(|x| x.pop());
+ let free_registry_id = unref_list.lock().as_mut().and_then(|x| x.pop());
if let Some(registry_id) = free_registry_id {
// It must be safe to replace the value without triggering memory error
ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
@@ -2106,7 +2003,7 @@ impl Lua {
}
// Allocate a new RegistryKey slot
- let registry_id = if self.unlikely_memory_error() {
+ let registry_id = if lua.unlikely_memory_error() {
ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
} else {
protect_lua!(state, 1, 0, |state| {
@@ -2123,12 +2020,13 @@ impl Lua {
/// previously placed by [`create_registry_value`].
///
/// [`create_registry_value`]: #method.create_registry_value
- pub fn registry_value<'lua, T: FromLua<'lua>>(&'lua self, key: &RegistryKey) -> Result<T> {
- if !self.owns_registry_value(key) {
+ pub fn registry_value<T: FromLua>(&self, key: &RegistryKey) -> Result<T> {
+ let lua = self.lock();
+ if !lua.owns_registry_value(key) {
return Err(Error::MismatchedRegistryKey);
}
- let state = self.state();
+ let state = lua.state();
match key.id() {
ffi::LUA_REFNIL => T::from_lua(Value::Nil, self),
registry_id => unsafe {
@@ -2136,7 +2034,7 @@ impl Lua {
check_stack(state, 1)?;
ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
- T::from_stack(-1, self)
+ T::from_stack(-1, &lua)
},
}
}
@@ -2151,12 +2049,13 @@ impl Lua {
/// [`create_registry_value`]: #method.create_registry_value
/// [`expire_registry_values`]: #method.expire_registry_values
pub fn remove_registry_value(&self, key: RegistryKey) -> Result<()> {
- if !self.owns_registry_value(&key) {
+ let lua = self.lock();
+ if !lua.owns_registry_value(&key) {
return Err(Error::MismatchedRegistryKey);
}
unsafe {
- ffi::luaL_unref(self.state(), ffi::LUA_REGISTRYINDEX, key.take());
+ ffi::luaL_unref(lua.state(), ffi::LUA_REGISTRYINDEX, key.take());
}
Ok(())
}
@@ -2166,18 +2065,15 @@ impl Lua {
/// See [`create_registry_value`] for more details.
///
/// [`create_registry_value`]: #method.create_registry_value
- pub fn replace_registry_value<'lua, T: IntoLua>(
- &'lua self,
- key: &RegistryKey,
- t: T,
- ) -> Result<()> {
- if !self.owns_registry_value(key) {
+ pub fn replace_registry_value<T: IntoLua>(&self, key: &RegistryKey, t: T) -> Result<()> {
+ let lua = self.lock();
+ if !lua.owns_registry_value(key) {
return Err(Error::MismatchedRegistryKey);
}
let t = t.into_lua(self)?;
- let state = self.state();
+ let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 2)?;
@@ -2198,7 +2094,7 @@ impl Lua {
}
(value, registry_id) => {
// It must be safe to replace the value without triggering memory error
- self.push_value(&value)?;
+ lua.push_value(&value)?;
ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
}
}
@@ -2213,8 +2109,7 @@ impl Lua {
/// `Error::MismatchedRegistryKey` if passed a `RegistryKey` that was not created with a
/// matching `Lua` state.
pub fn owns_registry_value(&self, key: &RegistryKey) -> bool {
- let registry_unref_list = unsafe { &(*self.extra.get()).registry_unref_list };
- Arc::ptr_eq(&key.unref_list, registry_unref_list)
+ self.lock().owns_registry_value(key)
}
/// Remove any registry values whose `RegistryKey`s have all been dropped.
@@ -2223,12 +2118,10 @@ impl Lua {
/// but you can call this method to remove any unreachable registry values not manually removed
/// by `Lua::remove_registry_value`.
pub fn expire_registry_values(&self) {
- let state = self.state();
+ let lua = self.lock();
+ let state = lua.state();
unsafe {
- let mut unref_list = mlua_expect!(
- (*self.extra.get()).registry_unref_list.lock(),
- "unref list poisoned"
- );
+ let mut unref_list = (*lua.extra.get()).registry_unref_list.lock();
let unref_list = mem::replace(&mut *unref_list, Some(Vec::new()));
for id in mlua_expect!(unref_list, "unref list not set") {
ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, id);
@@ -2268,7 +2161,8 @@ impl Lua {
/// ```
#[track_caller]
pub fn set_app_data<T: MaybeSend + 'static>(&self, data: T) -> Option<T> {
- let extra = unsafe { &*self.extra.get() };
+ let lua = self.lock();
+ let extra = unsafe { &*lua.extra.get() };
extra.app_data.insert(data)
}
@@ -2281,7 +2175,8 @@ impl Lua {
///
/// See [`Lua::set_app_data()`] for examples.
pub fn try_set_app_data<T: MaybeSend + 'static>(&self, data: T) -> StdResult<Option<T>, T> {
- let extra = unsafe { &*self.extra.get() };
+ let lua = self.lock();
+ let extra = unsafe { &*lua.extra.get() };
extra.app_data.try_insert(data)
}
@@ -2293,8 +2188,9 @@ impl Lua {
/// can be taken out at the same time.
#[track_caller]
pub fn app_data_ref<T: 'static>(&self) -> Option<AppDataRef<T>> {
- let extra = unsafe { &*self.extra.get() };
- extra.app_data.borrow()
+ let guard = self.lock_arc();
+ let extra = unsafe { &*guard.extra.get() };
+ extra.app_data.borrow(Some(guard))
}
/// Gets a mutable reference to an application data object stored by [`Lua::set_app_data()`] of type `T`.
@@ -2304,8 +2200,9 @@ impl Lua {
/// Panics if the data object of type `T` is currently borrowed.
#[track_caller]
pub fn app_data_mut<T: 'static>(&self) -> Option<AppDataRefMut<T>> {
- let extra = unsafe { &*self.extra.get() };
- extra.app_data.borrow_mut()
+ let guard = self.lock_arc();
+ let extra = unsafe { &*guard.extra.get() };
+ extra.app_data.borrow_mut(Some(guard))
}
/// Removes an application data of type `T`.
@@ -2315,16 +2212,322 @@ impl Lua {
/// Panics if the app data container is currently borrowed.
#[track_caller]
pub fn remove_app_data<T: 'static>(&self) -> Option<T> {
- let extra = unsafe { &*self.extra.get() };
+ let lua = self.lock();
+ let extra = unsafe { &*lua.extra.get() };
extra.app_data.remove()
}
+ // FIXME
+ // /// Pushes a value that implements `IntoLua` onto the Lua stack.
+ // ///
+ // /// Uses 2 stack spaces, does not call checkstack.
+ // #[doc(hidden)]
+ // #[inline(always)]
+ // pub unsafe fn push(&self, value: impl IntoLua) -> Result<()> {
+ // // value.push_into_stack(self)
+ // }
+
+ /// Returns internal `Poll::Pending` constant used for executing async callbacks.
+ #[cfg(feature = "async")]
+ #[doc(hidden)]
+ #[inline]
+ pub fn poll_pending() -> LightUserData {
+ LightUserData(&ASYNC_POLL_PENDING as *const u8 as *mut c_void)
+ }
+
+ // Luau version located in `luau/mod.rs`
+ #[cfg(not(feature = "luau"))]
+ fn disable_c_modules(&self) -> Result<()> {
+ let package: Table = self.globals().get("package")?;
+
+ package.set(
+ "loadlib",
+ self.create_function(|_, ()| -> Result<()> {
+ Err(Error::SafetyError(
+ "package.loadlib is disabled in safe mode".to_string(),
+ ))
+ })?,
+ )?;
+
+ #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
+ let searchers: Table = package.get("searchers")?;
+ #[cfg(any(feature = "lua51", feature = "luajit"))]
+ let searchers: Table = package.get("loaders")?;
+
+ let loader = self.create_function(|_, ()| Ok("\n\tcan't load C modules in safe mode"))?;
+
+ // The third and fourth searchers looks for a loader as a C library
+ searchers.raw_set(3, loader)?;
+ searchers.raw_remove(4)?;
+
+ Ok(())
+ }
+
+ pub(crate) unsafe fn try_from_ptr(state: *mut ffi::lua_State) -> Option<Self> {
+ let extra = extra_data(state);
+ if extra.is_null() {
+ return None;
+ }
+ Some(Lua(Arc::clone((*extra).inner.assume_init_ref())))
+ }
+
+ #[inline(always)]
+ pub(crate) fn lock(&self) -> ReentrantMutexGuard<LuaInner> {
+ self.0.lock()
+ }
+
+ #[inline(always)]
+ pub(crate) fn lock_arc(&self) -> LuaGuard {
+ LuaGuard(self.0.lock_arc())
+ }
+
+ #[inline(always)]
+ pub(crate) unsafe fn guard_unchecked(&self) -> ManuallyDrop<ReentrantMutexGuard<LuaInner>> {
+ ManuallyDrop::new(self.0.make_guard_unchecked())
+ }
+
+ #[inline(always)]
+ pub(crate) fn weak(&self) -> WeakLua {
+ WeakLua(Arc::downgrade(&self.0))
+ }
+}
+
+impl LuaInner {
+ #[inline(always)]
+ pub(crate) fn lua(&self) -> &Lua {
+ unsafe { (*self.extra.get()).lua() }
+ }
+
+ #[inline(always)]
+ pub(crate) fn weak(&self) -> &WeakLua {
+ unsafe { (*self.extra.get()).weak() }
+ }
+
+ #[inline(always)]
+ pub(crate) fn state(&self) -> *mut ffi::lua_State {
+ self.state.get()
+ }
+
+ #[cfg(feature = "luau")]
+ #[inline(always)]
+ pub(crate) fn main_state(&self) -> *mut ffi::lua_State {
+ self.main_state
+ }
+
+ #[inline(always)]
+ pub(crate) fn ref_thread(&self) -> *mut ffi::lua_State {
+ unsafe { (*self.extra.get()).ref_thread }
+ }
+
+ /// See [`Lua::try_set_app_data`]
+ pub(crate) fn try_set_app_data<T: MaybeSend + 'static>(
+ &self,
+ data: T,
+ ) -> StdResult<Option<T>, T> {
+ let extra = unsafe { &*self.extra.get() };
+ extra.app_data.try_insert(data)
+ }
+
+ /// See [`Lua::app_data_ref`]
+ #[track_caller]
+ pub(crate) fn app_data_ref<T: 'static>(&self) -> Option<AppDataRef<T>> {
+ let extra = unsafe { &*self.extra.get() };
+ extra.app_data.borrow(None)
+ }
+
+ /// See [`Lua::app_data_mut`]
+ #[track_caller]
+ pub(crate) fn app_data_mut<T: 'static>(&self) -> Option<AppDataRefMut<T>> {
+ let extra = unsafe { &*self.extra.get() };
+ extra.app_data.borrow_mut(None)
+ }
+
+ /// See [`Lua::create_registry_value`]
+ pub(crate) fn owns_registry_value(&self, key: &RegistryKey) -> bool {
+ let registry_unref_list = unsafe { &(*self.extra.get()).registry_unref_list };
+ Arc::ptr_eq(&key.unref_list, registry_unref_list)
+ }
+
+ pub(crate) fn load_chunk(
+ &self,
+ name: Option<&CStr>,
+ env: Option<Table>,
+ mode: Option<ChunkMode>,
+ source: &[u8],
+ ) -> Result<Function> {
+ let state = self.state();
+ unsafe {
+ let _sg = StackGuard::new(state);
+ check_stack(state, 1)?;
+
+ let mode_str = match mode {
+ Some(ChunkMode::Binary) => cstr!("b"),
+ Some(ChunkMode::Text) => cstr!("t"),
+ None => cstr!("bt"),
+ };
+
+ match ffi::luaL_loadbufferx(
+ state,
+ source.as_ptr() as *const c_char,
+ source.len(),
+ name.map(|n| n.as_ptr()).unwrap_or_else(ptr::null),
+ mode_str,
+ ) {
+ ffi::LUA_OK => {
+ if let Some(env) = env {
+ self.push_ref(&env.0);
+ #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
+ ffi::lua_setupvalue(state, -2, 1);
+ #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
+ ffi::lua_setfenv(state, -2);
+ }
+
+ #[cfg(feature = "luau-jit")]
+ if (*self.extra.get()).enable_jit && ffi::luau_codegen_supported() != 0 {
+ ffi::luau_codegen_compile(state, -1);
+ }
+
+ Ok(Function(self.pop_ref()))
+ }
+ err => Err(pop_error(state, err)),
+ }
+ }
+ }
+
+ /// Sets a 'hook' function for a thread (coroutine).
+ #[cfg(not(feature = "luau"))]
+ pub(crate) unsafe fn set_thread_hook<F>(
+ &self,
+ state: *mut ffi::lua_State,
+ triggers: HookTriggers,
+ callback: F,
+ ) where
+ F: Fn(&Lua, Debug) -> Result<()> + MaybeSend + 'static,
+ {
+ unsafe extern "C-unwind" fn hook_proc(state: *mut ffi::lua_State, ar: *mut ffi::lua_Debug) {
+ let extra = extra_data(state);
+ if (*extra).hook_thread != state {
+ // Hook was destined for a different thread, ignore
+ ffi::lua_sethook(state, None, 0, 0);
+ return;
+ }
+ callback_error_ext(state, extra, move |_| {
+ let hook_cb = (*extra).hook_callback.clone();
+ let hook_cb = mlua_expect!(hook_cb, "no hook callback set in hook_proc");
+ if Arc::strong_count(&hook_cb) > 2 {
+ return Ok(()); // Don't allow recursion
+ }
+ let lua = (*extra).lua();
+ let rawlua = lua.lock();
+ let _guard = StateGuard::new(&rawlua, state);
+ let debug = Debug::new(lua, ar);
+ hook_cb(lua, debug)
+ })
+ }
+
+ (*self.extra.get()).hook_callback = Some(Arc::new(callback));
+ (*self.extra.get()).hook_thread = state; // Mark for what thread the hook is set
+ ffi::lua_sethook(state, Some(hook_proc), triggers.mask(), triggers.count());
+ }
+
+ /// Wraps a Lua function into a new thread (or coroutine).
+ ///
+ /// Takes function by reference.
+ fn create_thread_inner(&self, func: &Function) -> Result<Thread> {
+ let state = self.state();
+ unsafe {
+ let _sg = StackGuard::new(state);
+ check_stack(state, 3)?;
+
+ let thread_state = if self.unlikely_memory_error() {
+ ffi::lua_newthread(state)
+ } else {
+ protect_lua!(state, 0, 1, |state| ffi::lua_newthread(state))?
+ };
+ self.push_ref(&func.0);
+ ffi::lua_xmove(state, thread_state, 1);
+
+ Ok(Thread::new(&self, self.pop_ref()))
+ }
+ }
+
+ /// Wraps a Lua function into a new or recycled thread (coroutine).
+ #[cfg(feature = "async")]
+ pub(crate) fn create_recycled_thread(&self, func: &Function) -> Result<Thread> {
+ #[cfg(any(feature = "lua54", feature = "luau"))]
+ unsafe {
+ let state = self.state();
+ let _sg = StackGuard::new(state);
+ check_stack(state, 1)?;
+
+ if let Some(index) = (*self.extra.get()).thread_pool.pop() {
+ let thread_state = ffi::lua_tothread(self.ref_thread(), index);
+ self.push_ref(&func.0);
+ ffi::lua_xmove(state, thread_state, 1);
+
+ #[cfg(feature = "luau")]
+ {
+ // Inherit `LUA_GLOBALSINDEX` from the caller
+ ffi::lua_xpush(state, thread_state, ffi::LUA_GLOBALSINDEX);
+ ffi::lua_replace(thread_state, ffi::LUA_GLOBALSINDEX);
+ }
+
+ return Ok(Thread::new(self, ValueRef::new(self, index)));
+ }
+ };
+ self.create_thread_inner(func)
+ }
+
+ /// Resets thread (coroutine) and returns to the pool for later use.
+ #[cfg(feature = "async")]
+ #[cfg(any(feature = "lua54", feature = "luau"))]
+ pub(crate) unsafe fn recycle_thread(&self, thread: &mut Thread) -> bool {
+ let extra = &mut *self.extra.get();
+ if extra.thread_pool.len() < extra.thread_pool.capacity() {
+ let thread_state = ffi::lua_tothread(extra.ref_thread, thread.0.index);
+ #[cfg(all(feature = "lua54", not(feature = "vendored")))]
+ let status = ffi::lua_resetthread(thread_state);
+ #[cfg(all(feature = "lua54", feature = "vendored"))]
+ let status = ffi::lua_closethread(thread_state, self.state());
+ #[cfg(feature = "lua54")]
+ if status != ffi::LUA_OK {
+ // Error object is on top, drop it
+ ffi::lua_settop(thread_state, 0);
+ }
+ #[cfg(feature = "luau")]
+ ffi::lua_resetthread(thread_state);
+ extra.thread_pool.push(thread.0.index);
+ thread.0.drop = false;
+ return true;
+ }
+ false
+ }
+
+ // FIXME
+ // #[inline]
+ // pub(crate) fn pop_multivalue_from_pool(&self) -> Option<VecDeque<Value>> {
+ // let extra = unsafe { &mut *self.extra.get() };
+ // extra.multivalue_pool.pop()
+ // }
+
+ // FIXME
+ // #[inline]
+ // pub(crate) fn push_multivalue_to_pool(&self, mut multivalue: VecDeque<Value>) {
+ // let extra = unsafe { &mut *self.extra.get() };
+ // if extra.multivalue_pool.len() < MULTIVALUE_POOL_SIZE {
+ // multivalue.clear();
+ // extra
+ // .multivalue_pool
+ // .push(unsafe { mem::transmute(multivalue) });
+ // }
+ // }
+
/// Pushes a value that implements `IntoLua` onto the Lua stack.
///
/// Uses 2 stack spaces, does not call checkstack.
#[doc(hidden)]
#[inline(always)]
- pub unsafe fn push<'lua>(&'lua self, value: impl IntoLua) -> Result<()> {
+ pub unsafe fn push(&self, value: impl IntoLua) -> Result<()> {
value.push_into_stack(self)
}
@@ -2363,7 +2566,7 @@ impl Lua {
///
/// Uses 2 stack spaces, does not call checkstack.
#[doc(hidden)]
- pub unsafe fn pop_value(&self) -> Value {
+ pub(crate) unsafe fn pop_value(&self) -> Value {
let state = self.state();
match ffi::lua_type(state, -1) {
ffi::LUA_TNIL => {
@@ -2451,7 +2654,7 @@ impl Lua {
}
}
- ffi::LUA_TTHREAD => Value::Thread(Thread::new(self.pop_ref())),
+ ffi::LUA_TTHREAD => Value::Thread(Thread::new(self, self.pop_ref())),
#[cfg(feature = "luau")]
ffi::LUA_TBUFFER => {
@@ -2554,7 +2757,7 @@ impl Lua {
ffi::LUA_TTHREAD => {
ffi::lua_xpush(state, self.ref_thread(), idx);
- Value::Thread(Thread::new(self.pop_ref_thread()))
+ Value::Thread(Thread::new(self, self.pop_ref_thread()))
}
#[cfg(feature = "luau")]
@@ -2576,21 +2779,12 @@ impl Lua {
}
// Pushes a ValueRef value onto the stack, uses 1 stack space, does not call checkstack
- pub(crate) unsafe fn push_ref(&self, vref: &ValueRef) {
- assert!(
- Arc::ptr_eq(&vref.lua.0, &self.0),
- "Lua instance passed Value created from a different main Lua state"
- );
- ffi::lua_xpush(self.ref_thread(), self.state(), vref.index);
- }
-
- #[cfg(all(feature = "unstable", not(feature = "send")))]
- pub(crate) unsafe fn push_owned_ref(&self, vref: &crate::types::OwnedValueRef) {
+ pub(crate) fn push_ref(&self, vref: &ValueRef) {
assert!(
- Arc::ptr_eq(&vref.inner, &self.0),
+ self.weak() == &vref.lua,
"Lua instance passed Value created from a different main Lua state"
);
- ffi::lua_xpush(self.ref_thread(), self.state(), vref.index);
+ unsafe { ffi::lua_xpush(self.ref_thread(), self.state(), vref.index) };
}
// Pops the topmost element of the stack and stores a reference to it. This pins the object,
@@ -2622,29 +2816,15 @@ impl Lua {
}
}
- pub(crate) fn drop_ref_index(&self, index: c_int) {
+ pub(crate) fn drop_ref(&self, vref: &ValueRef) {
unsafe {
let ref_thread = self.ref_thread();
ffi::lua_pushnil(ref_thread);
- ffi::lua_replace(ref_thread, index);
- (*self.extra.get()).ref_free.push(index);
+ ffi::lua_replace(ref_thread, vref.index);
+ (*self.extra.get()).ref_free.push(vref.index);
}
}
- #[cfg(all(feature = "unstable", not(feature = "send")))]
- pub(crate) fn adopt_owned_ref(&self, vref: crate::types::OwnedValueRef) -> ValueRef {
- assert!(
- Arc::ptr_eq(&vref.inner, &self.0),
- "Lua instance passed Value created from a different main Lua state"
- );
- let index = vref.index;
- unsafe {
- ptr::read(&vref.inner);
- mem::forget(vref);
- }
- ValueRef::new(self, index)
- }
-
#[inline]
pub(crate) unsafe fn push_error_traceback(&self) {
let state = self.state();
@@ -2655,9 +2835,95 @@ impl Lua {
ffi::lua_pushcfunction(state, error_traceback);
}
- unsafe fn register_userdata_metatable<'lua, T: 'static>(
- &'lua self,
- mut registry: UserDataRegistry<'lua, T>,
+ #[inline]
+ pub(crate) unsafe fn unlikely_memory_error(&self) -> bool {
+ // MemoryInfo is empty in module mode so we cannot predict memory limits
+ match MemoryState::get(self.main_state) {
+ mem_state if !mem_state.is_null() => (*mem_state).memory_limit() == 0,
+ #[cfg(feature = "module")]
+ _ => (*self.extra.get()).skip_memory_check, // Check the special flag (only for module mode)
+ #[cfg(not(feature = "module"))]
+ _ => false,
+ }
+ }
+
+ pub(crate) unsafe fn make_userdata<T>(&self, data: UserDataVariant<T>) -> Result<AnyUserData>
+ where
+ T: UserData + 'static,
+ {
+ self.make_userdata_with_metatable(data, || {
+ // Check if userdata/metatable is already registered
+ let type_id = TypeId::of::<T>();
+ if let Some(&table_id) = (*self.extra.get()).registered_userdata.get(&type_id) {
+ return Ok(table_id as Integer);
+ }
+
+ // Create new metatable from UserData definition
+ let mut registry = UserDataRegistry::new();
+ T::register(&mut registry);
+
+ self.register_userdata_metatable(registry)
+ })
+ }
+
+ pub(crate) unsafe fn make_any_userdata<T>(
+ &self,
+ data: UserDataVariant<T>,
+ ) -> Result<AnyUserData>
+ where
+ T: 'static,
+ {
+ self.make_userdata_with_metatable(data, || {
+ // Check if userdata/metatable is already registered
+ let type_id = TypeId::of::<T>();
+ if let Some(&table_id) = (*self.extra.get()).registered_userdata.get(&type_id) {
+ return Ok(table_id as Integer);
+ }
+
+ // Create empty metatable
+ let registry = UserDataRegistry::new();
+ self.register_userdata_metatable::<T>(registry)
+ })
+ }
+
+ unsafe fn make_userdata_with_metatable<T>(
+ &self,
+ data: UserDataVariant<T>,
+ get_metatable_id: impl FnOnce() -> Result<Integer>,
+ ) -> Result<AnyUserData> {
+ let state = self.state();
+ let _sg = StackGuard::new(state);
+ check_stack(state, 3)?;
+
+ // We push metatable first to ensure having correct metatable with `__gc` method
+ ffi::lua_pushnil(state);
+ ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, get_metatable_id()?);
+ let protect = !self.unlikely_memory_error();
+ #[cfg(not(feature = "lua54"))]
+ push_userdata(state, data, protect)?;
+ #[cfg(feature = "lua54")]
+ push_userdata_uv(state, data, USER_VALUE_MAXSLOT as c_int, protect)?;
+ ffi::lua_replace(state, -3);
+ ffi::lua_setmetatable(state, -2);
+
+ // Set empty environment for Lua 5.1
+ #[cfg(any(feature = "lua51", feature = "luajit"))]
+ if protect {
+ protect_lua!(state, 1, 1, fn(state) {
+ ffi::lua_newtable(state);
+ ffi::lua_setuservalue(state, -2);
+ })?;
+ } else {
+ ffi::lua_newtable(state);
+ ffi::lua_setuservalue(state, -2);
+ }
+
+ Ok(AnyUserData(self.pop_ref(), SubtypeId::None))
+ }
+
+ unsafe fn register_userdata_metatable<T: 'static>(
+ &self,
+ mut registry: UserDataRegistry<T>,
) -> Result<Integer> {
let state = self.state();
let _sg = StackGuard::new(state);
@@ -2680,7 +2946,8 @@ impl Lua {
let mut has_name = false;
for (k, f) in registry.meta_fields {
has_name = has_name || k == MetaMethod::Type;
- mlua_assert!(f(self, 0)? == 1, "field function must return one value");
+ let inner = mem::transmute::<&LuaInner, &LuaInner>(self);
+ mlua_assert!(f(inner, 0)? == 1, "field function must return one value");
rawset_field(state, -2, MetaMethod::validate(&k)?)?;
}
// Set `__name/__type` if not provided
@@ -2705,7 +2972,8 @@ impl Lua {
push_table(state, 0, fields_nrec, true)?;
}
for (k, f) in registry.fields {
- mlua_assert!(f(self, 0)? == 1, "field function must return one value");
+ let inner = mem::transmute::<&LuaInner, &LuaInner>(self);
+ mlua_assert!(f(inner, 0)? == 1, "field function must return one value");
rawset_field(state, -2, &k)?;
}
rawset_field(state, metatable_index, "__index")?;
@@ -2786,7 +3054,7 @@ impl Lua {
let extra_init = None;
#[cfg(not(feature = "luau"))]
let extra_init: Option<fn(*mut ffi::lua_State) -> Result<()>> = Some(|state| {
- ffi::lua_pushcfunction(state, util::userdata_destructor::<UserDataCell<T>>);
+ ffi::lua_pushcfunction(state, util::userdata_destructor::<UserDataVariant<T>>);
rawset_field(state, -2, "__gc")
});
@@ -2835,6 +3103,12 @@ impl Lua {
}
}
+ #[inline(always)]
+ pub(crate) unsafe fn get_userdata_ref<T: 'static>(&self, idx: c_int) -> Result<UserDataRef<T>> {
+ let guard = self.lua().lock_arc();
+ (*get_userdata::<UserDataVariant<T>>(self.state(), idx)).try_make_ref(guard)
+ }
+
// Returns `TypeId` for the userdata ref, checking that it's registered and not destructed.
//
// Returns `None` if the userdata is registered but non-static.
@@ -2887,18 +3161,8 @@ impl Lua {
Ok(type_id)
}
- // Creates a Function out of a Callback containing a 'static Fn. This is safe ONLY because the
- // Fn is 'static, otherwise it could capture 'lua arguments improperly. Without ATCs, we
- // cannot easily deal with the "correct" callback type of:
- //
- // Box<for<'lua> Fn(&'lua Lua, MultiValue<'lua>) -> Result<MultiValue<'lua>>)>
- //
- // So we instead use a caller provided lifetime, which without the 'static requirement would be
- // unsafe.
- pub(crate) fn create_callback<'lua>(
- &'lua self,
- func: Callback<'lua, 'static>,
- ) -> Result<Function<'lua>> {
+ // Creates a Function out of a Callback containing a 'static Fn.
+ pub(crate) fn create_callback(&self, func: Callback) -> Result<Function> {
unsafe extern "C-unwind" fn call_callback(state: *mut ffi::lua_State) -> c_int {
// Normal functions can be scoped and therefore destroyed,
// so we need to check that the first upvalue is valid
@@ -2915,11 +3179,11 @@ impl Lua {
return Err(Error::CallbackDestructed);
}
- let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
- let _guard = StateGuard::new(&lua.0, state);
+ let lua = (*extra).lua().lock();
+ let _guard = StateGuard::new(&lua, state);
let func = &*(*upvalue).data;
- func(lua, nargs)
+ func(mem::transmute::<&LuaInner, &LuaInner>(&lua), nargs)
})
}
@@ -2945,10 +3209,7 @@ impl Lua {
}
#[cfg(feature = "async")]
- pub(crate) fn create_async_callback<'lua>(
- &'lua self,
- func: AsyncCallback<'lua, 'static>,
- ) -> Result<Function<'lua>> {
+ pub(crate) fn create_async_callback(&self, func: AsyncCallback) -> Result<Function> {
#[cfg(any(
feature = "lua54",
feature = "lua53",
@@ -2969,14 +3230,17 @@ impl Lua {
let extra = (*upvalue).extra.get();
callback_error_ext(state, extra, |nargs| {
// Lua ensures that `LUA_MINSTACK` stack spaces are available (after pushing arguments)
- let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
- let _guard = StateGuard::new(&lua.0, state);
+ let lua = (*extra).lua();
+ // The lock must be already held as the callback is executed
+ let rawlua = lua.guard_unchecked();
+ let rawlua = mem::transmute::<&LuaInner, &LuaInner>(&rawlua);
+ let _guard = StateGuard::new(rawlua, state);
- let args = MultiValue::from_stack_multi(nargs, lua)?;
+ let args = MultiValue::from_stack_multi(nargs, rawlua)?;
let func = &*(*upvalue).data;
- let fut = func(lua, args);
+ let fut = func(rawlua, args);
let extra = Arc::clone(&(*upvalue).extra);
- let protect = !lua.unlikely_memory_error();
+ let protect = !rawlua.unlikely_memory_error();
push_gc_userdata(state, AsyncPollUpvalue { data: fut, extra }, protect)?;
if protect {
protect_lua!(state, 1, 1, fn(state) {
@@ -2995,11 +3259,13 @@ impl Lua {
let extra = (*upvalue).extra.get();
callback_error_ext(state, extra, |_| {
// Lua ensures that `LUA_MINSTACK` stack spaces are available (after pushing arguments)
- let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
- let _guard = StateGuard::new(&lua.0, state);
+ let lua = (*extra).lua();
+ // The lock must be already held as the future is polled
+ let rawlua = lua.guard_unchecked();
+ let _guard = StateGuard::new(&rawlua, state);
let fut = &mut (*upvalue).data;
- let mut ctx = Context::from_waker(lua.waker());
+ let mut ctx = Context::from_waker(rawlua.waker());
match fut.as_mut().poll(&mut ctx) {
Poll::Pending => {
ffi::lua_pushnil(state);
@@ -3017,9 +3283,9 @@ impl Lua {
Ok(nresults + 1)
}
nresults => {
- let results = MultiValue::from_stack_multi(nresults, lua)?;
+ let results = MultiValue::from_stack_multi(nresults, &rawlua)?;
ffi::lua_pushinteger(state, nresults as _);
- lua.push(lua.create_sequence_from(results)?)?;
+ rawlua.push(lua.create_sequence_from(results)?)?;
Ok(2)
}
}
@@ -3058,17 +3324,18 @@ impl Lua {
len as c_int
}
- let coroutine = self.globals().get::<_, Table>("coroutine")?;
+ let lua = self.lua();
+ let coroutine = lua.globals().get::<_, Table>("coroutine")?;
- let env = self.create_table_with_capacity(0, 3)?;
+ let env = lua.create_table_with_capacity(0, 3)?;
env.set("get_poll", get_poll)?;
// Cache `yield` function
env.set("yield", coroutine.get::<_, Function>("yield")?)?;
unsafe {
- env.set("unpack", self.create_c_function(unpack)?)?;
+ env.set("unpack", lua.create_c_function(unpack)?)?;
}
- self.load(
+ lua.load(
r#"
local poll = get_poll(...)
while true do
@@ -3105,181 +3372,51 @@ impl Lua {
pub(crate) unsafe fn set_waker(&self, waker: NonNull<Waker>) -> NonNull<Waker> {
mem::replace(&mut (*self.extra.get()).waker, waker)
}
+}
- /// Returns internal `Poll::Pending` constant used for executing async callbacks.
- #[cfg(feature = "async")]
- #[doc(hidden)]
- #[inline]
- pub fn poll_pending() -> LightUserData {
- LightUserData(&ASYNC_POLL_PENDING as *const u8 as *mut c_void)
- }
-
- pub(crate) unsafe fn make_userdata<T>(&self, data: UserDataCell<T>) -> Result<AnyUserData>
- where
- T: UserData + 'static,
- {
- self.make_userdata_with_metatable(data, || {
- // Check if userdata/metatable is already registered
- let type_id = TypeId::of::<T>();
- if let Some(&table_id) = (*self.extra.get()).registered_userdata.get(&type_id) {
- return Ok(table_id as Integer);
- }
-
- // Create new metatable from UserData definition
- let mut registry = UserDataRegistry::new();
- T::add_fields(&mut registry);
- T::add_methods(&mut registry);
-
- self.register_userdata_metatable(registry)
- })
- }
-
- pub(crate) unsafe fn make_any_userdata<T>(&self, data: UserDataCell<T>) -> Result<AnyUserData>
- where
- T: 'static,
- {
- self.make_userdata_with_metatable(data, || {
- // Check if userdata/metatable is already registered
- let type_id = TypeId::of::<T>();
- if let Some(&table_id) = (*self.extra.get()).registered_userdata.get(&type_id) {
- return Ok(table_id as Integer);
- }
-
- // Create empty metatable
- let registry = UserDataRegistry::new();
- self.register_userdata_metatable::<T>(registry)
- })
+impl WeakLua {
+ #[inline(always)]
+ pub(crate) fn lock(&self) -> LuaGuard {
+ LuaGuard::new(self.0.upgrade().unwrap())
}
+}
- unsafe fn make_userdata_with_metatable<T>(
- &self,
- data: UserDataCell<T>,
- get_metatable_id: impl FnOnce() -> Result<Integer>,
- ) -> Result<AnyUserData> {
- let state = self.state();
- let _sg = StackGuard::new(state);
- check_stack(state, 3)?;
-
- // We push metatable first to ensure having correct metatable with `__gc` method
- ffi::lua_pushnil(state);
- ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, get_metatable_id()?);
- let protect = !self.unlikely_memory_error();
- #[cfg(not(feature = "lua54"))]
- push_userdata(state, data, protect)?;
- #[cfg(feature = "lua54")]
- push_userdata_uv(state, data, USER_VALUE_MAXSLOT as c_int, protect)?;
- ffi::lua_replace(state, -3);
- ffi::lua_setmetatable(state, -2);
-
- // Set empty environment for Lua 5.1
- #[cfg(any(feature = "lua51", feature = "luajit"))]
- if protect {
- protect_lua!(state, 1, 1, fn(state) {
- ffi::lua_newtable(state);
- ffi::lua_setuservalue(state, -2);
- })?;
- } else {
- ffi::lua_newtable(state);
- ffi::lua_setuservalue(state, -2);
- }
-
- Ok(AnyUserData(self.pop_ref(), SubtypeId::None))
+impl PartialEq for WeakLua {
+ fn eq(&self, other: &Self) -> bool {
+ Weak::ptr_eq(&self.0, &other.0)
}
+}
- // Luau version located in `luau/mod.rs`
- #[cfg(not(feature = "luau"))]
- fn disable_c_modules(&self) -> Result<()> {
- let package: Table = self.globals().get("package")?;
-
- package.set(
- "loadlib",
- self.create_function(|_, ()| -> Result<()> {
- Err(Error::SafetyError(
- "package.loadlib is disabled in safe mode".to_string(),
- ))
- })?,
- )?;
-
- #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
- let searchers: Table = package.get("searchers")?;
- #[cfg(any(feature = "lua51", feature = "luajit"))]
- let searchers: Table = package.get("loaders")?;
-
- let loader = self.create_function(|_, ()| Ok("\n\tcan't load C modules in safe mode"))?;
-
- // The third and fourth searchers looks for a loader as a C library
- searchers.raw_set(3, loader)?;
- searchers.raw_remove(4)?;
-
- Ok(())
- }
+impl Eq for WeakLua {}
- pub(crate) unsafe fn try_from_ptr(state: *mut ffi::lua_State) -> Option<Self> {
- let extra = extra_data(state);
- if extra.is_null() {
- return None;
- }
- Some(Lua(Arc::clone((*extra).inner.assume_init_ref())))
+impl LuaGuard {
+ pub(crate) fn new(handle: Arc<ReentrantMutex<LuaInner>>) -> Self {
+ Self(handle.lock_arc())
}
+}
- #[inline]
- pub(crate) unsafe fn unlikely_memory_error(&self) -> bool {
- // MemoryInfo is empty in module mode so we cannot predict memory limits
- match MemoryState::get(self.main_state) {
- mem_state if !mem_state.is_null() => (*mem_state).memory_limit() == 0,
- #[cfg(feature = "module")]
- _ => (*self.extra.get()).skip_memory_check, // Check the special flag (only for module mode)
- #[cfg(not(feature = "module"))]
- _ => false,
- }
- }
+impl Deref for LuaGuard {
+ type Target = LuaInner;
- #[cfg(feature = "unstable")]
- #[inline]
- pub(crate) fn clone(&self) -> Arc<LuaInner> {
- Arc::clone(&self.0)
+ fn deref(&self) -> &Self::Target {
+ &*self.0
}
}
-impl LuaInner {
- #[inline(always)]
- pub(crate) fn state(&self) -> *mut ffi::lua_State {
- self.state.get()
- }
+impl ExtraData {
+ // Index of `error_traceback` function in auxiliary thread stack
+ #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
+ const ERROR_TRACEBACK_IDX: c_int = 1;
- #[cfg(feature = "luau")]
#[inline(always)]
- pub(crate) fn main_state(&self) -> *mut ffi::lua_State {
- self.main_state
+ const fn lua(&self) -> &Lua {
+ unsafe { mem::transmute(self.inner.assume_init_ref()) }
}
#[inline(always)]
- pub(crate) fn ref_thread(&self) -> *mut ffi::lua_State {
- unsafe { (*self.extra.get()).ref_thread }
- }
-
- #[inline]
- pub(crate) fn pop_multivalue_from_pool(&self) -> Option<VecDeque<Value>> {
- let extra = unsafe { &mut *self.extra.get() };
- extra.multivalue_pool.pop()
+ const fn weak(&self) -> &WeakLua {
+ unsafe { mem::transmute(self.weak.assume_init_ref()) }
}
-
- #[inline]
- pub(crate) fn push_multivalue_to_pool(&self, mut multivalue: VecDeque<Value>) {
- let extra = unsafe { &mut *self.extra.get() };
- if extra.multivalue_pool.len() < MULTIVALUE_POOL_SIZE {
- multivalue.clear();
- extra
- .multivalue_pool
- .push(unsafe { mem::transmute(multivalue) });
- }
- }
-}
-
-impl ExtraData {
- // Index of `error_traceback` function in auxiliary thread stack
- #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
- const ERROR_TRACEBACK_IDX: c_int = 1;
}
struct StateGuard<'a>(&'a LuaInner, *mut ffi::lua_State);
diff --git a/src/multi.rs b/src/multi.rs
index 00f9e62..e56aeb9 100644
--- a/src/multi.rs
+++ b/src/multi.rs
@@ -5,7 +5,7 @@ use std::os::raw::c_int;
use std::result::Result as StdResult;
use crate::error::Result;
-use crate::lua::Lua;
+use crate::lua::{Lua, LuaInner};
use crate::util::check_stack;
use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, MultiValue, Nil};
@@ -13,7 +13,7 @@ use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, MultiValue, Nil
/// on success, or in the case of an error, returning `nil` and an error message.
impl<T: IntoLua, E: IntoLua> IntoLuaMulti for StdResult<T, E> {
#[inline]
- fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue<'_>> {
+ fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
match self {
Ok(val) => (val,).into_lua_multi(lua),
Err(err) => (Nil, err).into_lua_multi(lua),
@@ -21,7 +21,7 @@ impl<T: IntoLua, E: IntoLua> IntoLuaMulti for StdResult<T, E> {
}
#[inline]
- unsafe fn push_into_stack_multi(self, lua: &Lua) -> Result<c_int> {
+ unsafe fn push_into_stack_multi(self, lua: &LuaInner) -> Result<c_int> {
match self {
Ok(val) => (val,).push_into_stack_multi(lua),
Err(err) => (Nil, err).push_into_stack_multi(lua),
@@ -31,7 +31,7 @@ impl<T: IntoLua, E: IntoLua> IntoLuaMulti for StdResult<T, E> {
impl<E: IntoLua> IntoLuaMulti for StdResult<(), E> {
#[inline]
- fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue<'_>> {
+ fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
match self {
Ok(_) => Ok(MultiValue::new()),
Err(err) => (Nil, err).into_lua_multi(lua),
@@ -39,7 +39,7 @@ impl<E: IntoLua> IntoLuaMulti for StdResult<(), E> {
}
#[inline]
- unsafe fn push_into_stack_multi(self, lua: &Lua) -> Result<c_int> {
+ unsafe fn push_into_stack_multi(self, lua: &LuaInner) -> Result<c_int> {
match self {
Ok(_) => Ok(0),
Err(err) => (Nil, err).push_into_stack_multi(lua),
@@ -49,39 +49,34 @@ impl<E: IntoLua> IntoLuaMulti for StdResult<(), E> {
impl<T: IntoLua> IntoLuaMulti for T {
#[inline]
- fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue<'_>> {
+ fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
let mut v = MultiValue::with_lua_and_capacity(lua, 1);
v.push_back(self.into_lua(lua)?);
Ok(v)
}
#[inline]
- unsafe fn push_into_stack_multi(self, lua: &Lua) -> Result<c_int> {
+ unsafe fn push_into_stack_multi(self, lua: &LuaInner) -> Result<c_int> {
self.push_into_stack(lua)?;
Ok(1)
}
}
-impl<'lua, T: FromLua<'lua>> FromLuaMulti<'lua> for T {
+impl<T: FromLua> FromLuaMulti for T {
#[inline]
- fn from_lua_multi(mut values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self> {
+ fn from_lua_multi(mut values: MultiValue, lua: &Lua) -> Result<Self> {
T::from_lua(values.pop_front().unwrap_or(Nil), lua)
}
#[inline]
- fn from_lua_args(
- mut args: MultiValue<'lua>,
- i: usize,
- to: Option<&str>,
- lua: &'lua Lua,
- ) -> Result<Self> {
+ fn from_lua_args(mut args: MultiValue, i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> {
T::from_lua_arg(args.pop_front().unwrap_or(Nil), i, to, lua)
}
#[inline]
- unsafe fn from_stack_multi(nvals: c_int, lua: &'lua Lua) -> Result<Self> {
+ unsafe fn from_stack_multi(nvals: c_int, lua: &LuaInner) -> Result<Self> {
if nvals == 0 {
- return T::from_lua(Nil, lua);
+ return T::from_lua(Nil, lua.lua());
}
T::from_stack(-nvals, lua)
}
@@ -91,25 +86,25 @@ impl<'lua, T: FromLua<'lua>> FromLuaMulti<'lua> for T {
nargs: c_int,
i: usize,
to: Option<&str>,
- lua: &'lua Lua,
+ lua: &LuaInner,
) -> Result<Self> {
if nargs == 0 {
- return T::from_lua_arg(Nil, i, to, lua);
+ return T::from_lua_arg(Nil, i, to, lua.lua());
}
T::from_stack_arg(-nargs, i, to, lua)
}
}
-impl IntoLuaMulti for MultiValue<'_> {
+impl IntoLuaMulti for MultiValue {
#[inline]
- fn into_lua_multi(self, _: &Lua) -> Result<MultiValue<'_>> {
+ fn into_lua_multi(self, _: &Lua) -> Result<MultiValue> {
unsafe { Ok(transmute(self)) }
}
}
-impl<'lua> FromLuaMulti<'lua> for MultiValue<'lua> {
+impl FromLuaMulti for MultiValue {
#[inline]
- fn from_lua_multi(values: MultiValue<'lua>, _: &'lua Lua) -> Result<Self> {
+ fn from_lua_multi(values: MultiValue, _: &Lua) -> Result<Self> {
Ok(values)
}
}
@@ -187,16 +182,16 @@ impl<T> DerefMut for Variadic<T> {
impl<T: IntoLua> IntoLuaMulti for Variadic<T> {
#[inline]
- fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue<'_>> {
+ fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
let mut values = MultiValue::with_lua_and_capacity(lua, self.0.len());
values.extend_from_values(self.0.into_iter().map(|val| val.into_lua(lua)))?;
Ok(values)
}
}
-impl<'lua, T: FromLua<'lua>> FromLuaMulti<'lua> for Variadic<T> {
+impl<T: FromLua> FromLuaMulti for Variadic<T> {
#[inline]
- fn from_lua_multi(mut values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self> {
+ fn from_lua_multi(mut values: MultiValue, lua: &Lua) -> Result<Self> {
values
.drain(..)
.map(|val| T::from_lua(val, lua))
@@ -209,24 +204,24 @@ macro_rules! impl_tuple {
() => (
impl IntoLuaMulti for () {
#[inline]
- fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue<'_>> {
+ fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
Ok(MultiValue::with_lua_and_capacity(lua, 0))
}
#[inline]
- unsafe fn push_into_stack_multi(self, _lua: &Lua) -> Result<c_int> {
+ unsafe fn push_into_stack_multi(self, _lua: &LuaInner) -> Result<c_int> {
Ok(0)
}
}
- impl<'lua> FromLuaMulti<'lua> for () {
+ impl FromLuaMulti for () {
#[inline]
- fn from_lua_multi(_values: MultiValue<'lua>, _lua: &'lua Lua) -> Result<Self> {
+ fn from_lua_multi(_values: MultiValue, _lua: &Lua) -> Result<Self> {
Ok(())
}
#[inline]
- unsafe fn from_stack_multi(nvals: c_int, lua: &'lua Lua) -> Result<Self> {
+ unsafe fn from_stack_multi(nvals: c_int, lua: &LuaInner) -> Result<Self> {
if nvals > 0 {
ffi::lua_pop(lua.state(), nvals);
}
@@ -242,7 +237,7 @@ macro_rules! impl_tuple {
{
#[allow(unused_mut, non_snake_case)]
#[inline]
- fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue<'_>> {
+ fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
let ($($name,)* $last,) = self;
let mut results = $last.into_lua_multi(lua)?;
@@ -252,7 +247,7 @@ macro_rules! impl_tuple {
#[allow(non_snake_case)]
#[inline]
- unsafe fn push_into_stack_multi(self, lua: &Lua) -> Result<c_int> {
+ unsafe fn push_into_stack_multi(self, lua: &LuaInner) -> Result<c_int> {
let ($($name,)* $last,) = self;
let mut nresults = 0;
$(
@@ -268,13 +263,13 @@ macro_rules! impl_tuple {
}
}
- impl<'lua, $($name,)* $last> FromLuaMulti<'lua> for ($($name,)* $last,)
- where $($name: FromLua<'lua>,)*
- $last: FromLuaMulti<'lua>
+ impl<$($name,)* $last> FromLuaMulti for ($($name,)* $last,)
+ where $($name: FromLua,)*
+ $last: FromLuaMulti
{
#[allow(unused_mut, non_snake_case)]
#[inline]
- fn from_lua_multi(mut values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self> {
+ fn from_lua_multi(mut values: MultiValue, lua: &Lua) -> Result<Self> {
$(let $name = FromLua::from_lua(values.pop_front().unwrap_or(Nil), lua)?;)*
let $last = FromLuaMulti::from_lua_multi(values, lua)?;
Ok(($($name,)* $last,))
@@ -282,7 +277,7 @@ macro_rules! impl_tuple {
#[allow(unused_mut, non_snake_case)]
#[inline]
- fn from_lua_args(mut args: MultiValue<'lua>, mut i: usize, to: Option<&str>, lua: &'lua Lua) -> Result<Self> {
+ fn from_lua_args(mut args: MultiValue, mut i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> {
$(
let $name = FromLua::from_lua_arg(args.pop_front().unwrap_or(Nil), i, to, lua)?;
i += 1;
@@ -293,13 +288,13 @@ macro_rules! impl_tuple {
#[allow(unused_mut, non_snake_case)]
#[inline]
- unsafe fn from_stack_multi(mut nvals: c_int, lua: &'lua Lua) -> Result<Self> {
+ unsafe fn from_stack_multi(mut nvals: c_int, lua: &LuaInner) -> Result<Self> {
$(
let $name = if nvals > 0 {
nvals -= 1;
FromLua::from_stack(-(nvals + 1), lua)
} else {
- FromLua::from_lua(Nil, lua)
+ FromLua::from_lua(Nil, lua.lua())
}?;
)*
let $last = FromLuaMulti::from_stack_multi(nvals, lua)?;
@@ -308,13 +303,13 @@ macro_rules! impl_tuple {
#[allow(unused_mut, non_snake_case)]
#[inline]
- unsafe fn from_stack_args(mut nargs: c_int, mut i: usize, to: Option<&str>, lua: &'lua Lua) -> Result<Self> {
+ unsafe fn from_stack_args(mut nargs: c_int, mut i: usize, to: Option<&str>, lua: &LuaInner) -> Result<Self> {
$(
let $name = if nargs > 0 {
nargs -= 1;
FromLua::from_stack_arg(-(nargs + 1), i, to, lua)
} else {
- FromLua::from_lua_arg(Nil, i, to, lua)
+ FromLua::from_lua_arg(Nil, i, to, lua.lua())
}?;
i += 1;
)*
diff --git a/src/prelude.rs b/src/prelude.rs
index e4459c2..c2929f7 100644
--- a/src/prelude.rs
+++ b/src/prelude.rs
@@ -35,10 +35,3 @@ pub use crate::{
DeserializeOptions as LuaDeserializeOptions, LuaSerdeExt,
SerializeOptions as LuaSerializeOptions,
};
-
-#[cfg(feature = "unstable")]
-#[doc(no_inline)]
-pub use crate::{
- OwnedAnyUserData as LuaOwnedAnyUserData, OwnedFunction as LuaOwnedFunction,
- OwnedString as LuaOwnedString, OwnedTable as LuaOwnedTable, OwnedThread as LuaOwnedThread,
-};
diff --git a/src/serde/de.rs b/src/serde/de.rs
index 3cc182d..542180f 100644
--- a/src/serde/de.rs
+++ b/src/serde/de.rs
@@ -14,8 +14,8 @@ use crate::value::Value;
/// A struct for deserializing Lua values into Rust values.
#[derive(Debug)]
-pub struct Deserializer<'lua> {
- value: Value<'lua>,
+pub struct Deserializer {
+ value: Value,
options: Options,
visited: Rc<RefCell<FxHashSet<*const c_void>>>,
}
@@ -93,14 +93,14 @@ impl Options {
}
}
-impl<'lua> Deserializer<'lua> {
+impl Deserializer {
/// Creates a new Lua Deserializer for the `Value`.
- pub fn new(value: Value<'lua>) -> Self {
+ pub fn new(value: Value) -> Self {
Self::new_with_options(value, Options::default())
}
/// Creates a new Lua Deserializer for the `Value` with custom options.
- pub fn new_with_options(value: Value<'lua>, options: Options) -> Self {
+ pub fn new_with_options(value: Value, options: Options) -> Self {
Deserializer {
value,
options,
@@ -109,7 +109,7 @@ impl<'lua> Deserializer<'lua> {
}
fn from_parts(
- value: Value<'lua>,
+ value: Value,
options: Options,
visited: Rc<RefCell<FxHashSet<*const c_void>>>,
) -> Self {
@@ -121,7 +121,7 @@ impl<'lua> Deserializer<'lua> {
}
}
-impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> {
+impl<'de> serde::Deserializer<'de> for Deserializer {
type Error = Error;
#[inline]
@@ -150,8 +150,9 @@ impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> {
}
#[cfg(feature = "luau")]
Value::UserData(ud) if ud.1 == crate::types::SubtypeId::Buffer => unsafe {
+ let lua = ud.0.lua.lock();
let mut size = 0usize;
- let buf = ffi::lua_tobuffer(ud.0.lua.ref_thread(), ud.0.index, &mut size);
+ let buf = ffi::lua_tobuffer(lua.ref_thread(), ud.0.index, &mut size);
mlua_assert!(!buf.is_null(), "invalid Luau buffer");
let buf = std::slice::from_raw_parts(buf as *const u8, size);
visitor.visit_bytes(buf)
@@ -394,13 +395,13 @@ impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> {
}
}
-struct SeqDeserializer<'lua> {
- seq: TableSequence<'lua, Value<'lua>>,
+struct SeqDeserializer {
+ seq: TableSequence<Value>,
options: Options,
visited: Rc<RefCell<FxHashSet<*const c_void>>>,
}
-impl<'lua, 'de> de::SeqAccess<'de> for SeqDeserializer<'lua> {
+impl<'de> de::SeqAccess<'de> for SeqDeserializer {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
@@ -466,13 +467,13 @@ impl<'de> de::SeqAccess<'de> for VecDeserializer {
}
}
-pub(crate) enum MapPairs<'lua> {
- Iter(TablePairs<'lua, Value<'lua>, Value<'lua>>),
- Vec(Vec<(Value<'lua>, Value<'lua>)>),
+pub(crate) enum MapPairs {
+ Iter(TablePairs<Value, Value>),
+ Vec(Vec<(Value, Value)>),
}
-impl<'lua> MapPairs<'lua> {
- pub(crate) fn new(t: Table<'lua>, sort_keys: bool) -> Result<Self> {
+impl MapPairs {
+ pub(crate) fn new(t: Table, sort_keys: bool) -> Result<Self> {
if sort_keys {
let mut pairs = t.pairs::<Value, Value>().collect::<Result<Vec<_>>>()?;
pairs.sort_by(|(a, _), (b, _)| b.cmp(a)); // reverse order as we pop values from the end
@@ -497,8 +498,8 @@ impl<'lua> MapPairs<'lua> {
}
}
-impl<'lua> Iterator for MapPairs<'lua> {
- type Item = Result<(Value<'lua>, Value<'lua>)>;
+impl Iterator for MapPairs {
+ type Item = Result<(Value, Value)>;
fn next(&mut self) -> Option<Self::Item> {
match self {
@@ -508,15 +509,15 @@ impl<'lua> Iterator for MapPairs<'lua> {
}
}
-struct MapDeserializer<'lua> {
- pairs: MapPairs<'lua>,
- value: Option<Value<'lua>>,
+struct MapDeserializer {
+ pairs: MapPairs,
+ value: Option<Value>,
options: Options,
visited: Rc<RefCell<FxHashSet<*const c_void>>>,
processed: usize,
}
-impl<'lua, 'de> de::MapAccess<'de> for MapDeserializer<'lua> {
+impl<'de> de::MapAccess<'de> for MapDeserializer {
type Error = Error;
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
@@ -566,16 +567,16 @@ impl<'lua, 'de> de::MapAccess<'de> for MapDeserializer<'lua> {
}
}
-struct EnumDeserializer<'lua> {
+struct EnumDeserializer {
variant: StdString,
- value: Option<Value<'lua>>,
+ value: Option<Value>,
options: Options,
visited: Rc<RefCell<FxHashSet<*const c_void>>>,
}
-impl<'lua, 'de> de::EnumAccess<'de> for EnumDeserializer<'lua> {
+impl<'de> de::EnumAccess<'de> for EnumDeserializer {
type Error = Error;
- type Variant = VariantDeserializer<'lua>;
+ type Variant = VariantDeserializer;
fn variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant)>
where
@@ -591,13 +592,13 @@ impl<'lua, 'de> de::EnumAccess<'de> for EnumDeserializer<'lua> {
}
}
-struct VariantDeserializer<'lua> {
- value: Option<Value<'lua>>,
+struct VariantDeserializer {
+ value: Option<Value>,
options: Options,
visited: Rc<RefCell<FxHashSet<*const c_void>>>,
}
-impl<'lua, 'de> de::VariantAccess<'de> for VariantDeserializer<'lua> {
+impl<'de> de::VariantAccess<'de> for VariantDeserializer {
type Error = Error;
fn unit_variant(self) -> Result<()> {
diff --git a/src/serde/mod.rs b/src/serde/mod.rs
index 877b889..9495281 100644
--- a/src/serde/mod.rs
+++ b/src/serde/mod.rs
@@ -99,7 +99,7 @@ pub trait LuaSerdeExt: Sealed {
/// "#).exec()
/// }
/// ```
- fn to_value<'lua, T: Serialize + ?Sized>(&'lua self, t: &T) -> Result<Value<'lua>>;
+ fn to_value<T: Serialize + ?Sized>(&self, t: &T) -> Result<Value>;
/// Converts `T` into a [`Value`] instance with options.
///
@@ -124,7 +124,7 @@ pub trait LuaSerdeExt: Sealed {
/// "#).exec()
/// }
/// ```
- fn to_value_with<'lua, T>(&'lua self, t: &T, options: ser::Options) -> Result<Value<'lua>>
+ fn to_value_with<T>(&self, t: &T, options: ser::Options) -> Result<Value>
where
T: Serialize + ?Sized;
@@ -199,20 +199,21 @@ impl LuaSerdeExt for Lua {
}
fn array_metatable(&self) -> Table {
+ let lua = self.lock();
unsafe {
- push_array_metatable(self.ref_thread());
- Table(self.pop_ref_thread())
+ push_array_metatable(lua.ref_thread());
+ Table(lua.pop_ref_thread())
}
}
- fn to_value<'lua, T>(&'lua self, t: &T) -> Result<Value<'lua>>
+ fn to_value<T>(&self, t: &T) -> Result<Value>
where
T: Serialize + ?Sized,
{
t.serialize(ser::Serializer::new(self))
}
- fn to_value_with<'lua, T>(&'lua self, t: &T, options: ser::Options) -> Result<Value<'lua>>
+ fn to_value_with<T>(&self, t: &T, options: ser::Options) -> Result<Value>
where
T: Serialize + ?Sized,
{
diff --git a/src/serde/ser.rs b/src/serde/ser.rs
index 6ee57a1..df3a16c 100644
--- a/src/serde/ser.rs
+++ b/src/serde/ser.rs
@@ -8,8 +8,8 @@ use crate::value::{IntoLua, Value};
/// A struct for serializing Rust values into Lua values.
#[derive(Debug)]
-pub struct Serializer<'lua> {
- lua: &'lua Lua,
+pub struct Serializer<'a> {
+ lua: &'a Lua,
options: Options,
}
@@ -109,14 +109,14 @@ impl Options {
}
}
-impl<'lua> Serializer<'lua> {
+impl<'a> Serializer<'a> {
/// Creates a new Lua Serializer with default options.
- pub fn new(lua: &'lua Lua) -> Self {
+ pub fn new(lua: &'a Lua) -> Self {
Self::new_with_options(lua, Options::default())
}
/// Creates a new Lua Serializer with custom options.
- pub fn new_with_options(lua: &'lua Lua, options: Options) -> Self {
+ pub fn new_with_options(lua: &'a Lua, options: Options) -> Self {
Serializer { lua, options }
}
}
@@ -124,28 +124,28 @@ impl<'lua> Serializer<'lua> {
macro_rules! lua_serialize_number {
($name:ident, $t:ty) => {
#[inline]
- fn $name(self, value: $t) -> Result<Value<'lua>> {
+ fn $name(self, value: $t) -> Result<Value> {
value.into_lua(self.lua)
}
};
}
-impl<'lua> ser::Serializer for Serializer<'lua> {
- type Ok = Value<'lua>;
+impl<'a> ser::Serializer for Serializer<'a> {
+ type Ok = Value;
type Error = Error;
// Associated types for keeping track of additional state while serializing
// compound data structures like sequences and maps.
- type SerializeSeq = SerializeSeq<'lua>;
- type SerializeTuple = SerializeSeq<'lua>;
- type SerializeTupleStruct = SerializeSeq<'lua>;
- type SerializeTupleVariant = SerializeTupleVariant<'lua>;
- type SerializeMap = SerializeMap<'lua>;
- type SerializeStruct = SerializeStruct<'lua>;
- type SerializeStructVariant = SerializeStructVariant<'lua>;
+ type SerializeSeq = SerializeSeq<'a>;
+ type SerializeTuple = SerializeSeq<'a>;
+ type SerializeTupleStruct = SerializeSeq<'a>;
+ type SerializeTupleVariant = SerializeTupleVariant<'a>;
+ type SerializeMap = SerializeMap<'a>;
+ type SerializeStruct = SerializeStruct<'a>;
+ type SerializeStructVariant = SerializeStructVariant<'a>;
#[inline]
- fn serialize_bool(self, value: bool) -> Result<Value<'lua>> {
+ fn serialize_bool(self, value: bool) -> Result<Value> {
Ok(Value::Boolean(value))
}
@@ -164,22 +164,22 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
lua_serialize_number!(serialize_f64, f64);
#[inline]
- fn serialize_char(self, value: char) -> Result<Value<'lua>> {
+ fn serialize_char(self, value: char) -> Result<Value> {
self.serialize_str(&value.to_string())
}
#[inline]
- fn serialize_str(self, value: &str) -> Result<Value<'lua>> {
+ fn serialize_str(self, value: &str) -> Result<Value> {
self.lua.create_string(value).map(Value::String)
}
#[inline]
- fn serialize_bytes(self, value: &[u8]) -> Result<Value<'lua>> {
+ fn serialize_bytes(self, value: &[u8]) -> Result<Value> {
self.lua.create_string(value).map(Value::String)
}
#[inline]
- fn serialize_none(self) -> Result<Value<'lua>> {
+ fn serialize_none(self) -> Result<Value> {
if self.options.serialize_none_to_null {
Ok(self.lua.null())
} else {
@@ -188,7 +188,7 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
}
#[inline]
- fn serialize_some<T>(self, value: &T) -> Result<Value<'lua>>
+ fn serialize_some<T>(self, value: &T) -> Result<Value>
where
T: Serialize + ?Sized,
{
@@ -196,7 +196,7 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
}
#[inline]
- fn serialize_unit(self) -> Result<Value<'lua>> {
+ fn serialize_unit(self) -> Result<Value> {
if self.options.serialize_unit_to_null {
Ok(self.lua.null())
} else {
@@ -205,7 +205,7 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
}
#[inline]
- fn serialize_unit_struct(self, _name: &'static str) -> Result<Value<'lua>> {
+ fn serialize_unit_struct(self, _name: &'static str) -> Result<Value> {
if self.options.serialize_unit_to_null {
Ok(self.lua.null())
} else {
@@ -219,12 +219,12 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
_name: &'static str,
_variant_index: u32,
variant: &'static str,
- ) -> Result<Value<'lua>> {
+ ) -> Result<Value> {
self.serialize_str(variant)
}
#[inline]
- fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<Value<'lua>>
+ fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<Value>
where
T: Serialize + ?Sized,
{
@@ -238,7 +238,7 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
_variant_index: u32,
variant: &'static str,
value: &T,
- ) -> Result<Value<'lua>>
+ ) -> Result<Value>
where
T: Serialize + ?Sized,
{
@@ -255,7 +255,7 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
if self.options.set_array_metatable {
table.set_metatable(Some(self.lua.array_metatable()));
}
- Ok(SerializeSeq::new(table, self.options))
+ Ok(SerializeSeq::new(self.lua, table, self.options))
}
#[inline]
@@ -286,6 +286,7 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
_len: usize,
) -> Result<Self::SerializeTupleVariant> {
Ok(SerializeTupleVariant {
+ lua: self.lua,
variant,
table: self.lua.create_table()?,
options: self.options,
@@ -295,6 +296,7 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
#[inline]
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
Ok(SerializeMap {
+ lua: self.lua,
key: None,
table: self.lua.create_table_with_capacity(0, len.unwrap_or(0))?,
options: self.options,
@@ -330,6 +332,7 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
len: usize,
) -> Result<Self::SerializeStructVariant> {
Ok(SerializeStructVariant {
+ lua: self.lua,
variant,
table: self.lua.create_table_with_capacity(0, len)?,
options: self.options,
@@ -338,19 +341,19 @@ impl<'lua> ser::Serializer for Serializer<'lua> {
}
#[doc(hidden)]
-pub struct SerializeSeq<'lua> {
- lua: &'lua Lua,
+pub struct SerializeSeq<'a> {
+ lua: &'a Lua,
#[cfg(feature = "luau")]
vector: Option<crate::types::Vector>,
- table: Option<Table<'lua>>,
+ table: Option<Table>,
next: usize,
options: Options,
}
-impl<'lua> SerializeSeq<'lua> {
- const fn new(table: Table<'lua>, options: Options) -> Self {
+impl<'a> SerializeSeq<'a> {
+ fn new(lua: &'a Lua, table: Table, options: Options) -> Self {
Self {
- lua: table.0.lua,
+ lua,
#[cfg(feature = "luau")]
vector: None,
table: Some(table),
@@ -360,7 +363,7 @@ impl<'lua> SerializeSeq<'lua> {
}
#[cfg(feature = "luau")]
- const fn new_vector(lua: &'lua Lua, options: Options) -> Self {
+ const fn new_vector(lua: &'a Lua, options: Options) -> Self {
Self {
lua,
vector: Some(crate::types::Vector::zero()),
@@ -371,8 +374,8 @@ impl<'lua> SerializeSeq<'lua> {
}
}
-impl<'lua> ser::SerializeSeq for SerializeSeq<'lua> {
- type Ok = Value<'lua>;
+impl ser::SerializeSeq for SerializeSeq<'_> {
+ type Ok = Value;
type Error = Error;
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
@@ -386,13 +389,13 @@ impl<'lua> ser::SerializeSeq for SerializeSeq<'lua> {
Ok(())
}
- fn end(self) -> Result<Value<'lua>> {
+ fn end(self) -> Result<Value> {
Ok(Value::Table(self.table.unwrap()))
}
}
-impl<'lua> ser::SerializeTuple for SerializeSeq<'lua> {
- type Ok = Value<'lua>;
+impl ser::SerializeTuple for SerializeSeq<'_> {
+ type Ok = Value;
type Error = Error;
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
@@ -402,13 +405,13 @@ impl<'lua> ser::SerializeTuple for SerializeSeq<'lua> {
ser::SerializeSeq::serialize_element(self, value)
}
- fn end(self) -> Result<Value<'lua>> {
+ fn end(self) -> Result<Value> {
ser::SerializeSeq::end(self)
}
}
-impl<'lua> ser::SerializeTupleStruct for SerializeSeq<'lua> {
- type Ok = Value<'lua>;
+impl ser::SerializeTupleStruct for SerializeSeq<'_> {
+ type Ok = Value;
type Error = Error;
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
@@ -426,7 +429,7 @@ impl<'lua> ser::SerializeTupleStruct for SerializeSeq<'lua> {
ser::SerializeSeq::serialize_element(self, value)
}
- fn end(self) -> Result<Value<'lua>> {
+ fn end(self) -> Result<Value> {
#[cfg(feature = "luau")]
if let Some(vector) = self.vector {
return Ok(Value::Vector(vector));
@@ -436,49 +439,49 @@ impl<'lua> ser::SerializeTupleStruct for SerializeSeq<'lua> {
}
#[doc(hidden)]
-pub struct SerializeTupleVariant<'lua> {
+pub struct SerializeTupleVariant<'a> {
+ lua: &'a Lua,
variant: &'static str,
- table: Table<'lua>,
+ table: Table,
options: Options,
}
-impl<'lua> ser::SerializeTupleVariant for SerializeTupleVariant<'lua> {
- type Ok = Value<'lua>;
+impl ser::SerializeTupleVariant for SerializeTupleVariant<'_> {
+ type Ok = Value;
type Error = Error;
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
where
T: Serialize + ?Sized,
{
- let lua = self.table.0.lua;
- self.table.raw_push(lua.to_value_with(value, self.options)?)
+ self.table
+ .raw_push(self.lua.to_value_with(value, self.options)?)
}
- fn end(self) -> Result<Value<'lua>> {
- let lua = self.table.0.lua;
- let table = lua.create_table()?;
+ fn end(self) -> Result<Value> {
+ let table = self.lua.create_table()?;
table.raw_set(self.variant, self.table)?;
Ok(Value::Table(table))
}
}
#[doc(hidden)]
-pub struct SerializeMap<'lua> {
- table: Table<'lua>,
- key: Option<Value<'lua>>,
+pub struct SerializeMap<'a> {
+ lua: &'a Lua,
+ table: Table,
+ key: Option<Value>,
options: Options,
}
-impl<'lua> ser::SerializeMap for SerializeMap<'lua> {
- type Ok = Value<'lua>;
+impl ser::SerializeMap for SerializeMap<'_> {
+ type Ok = Value;
type Error = Error;
fn serialize_key<T>(&mut self, key: &T) -> Result<()>
where
T: Serialize + ?Sized,
{
- let lua = self.table.0.lua;
- self.key = Some(lua.to_value_with(key, self.options)?);
+ self.key = Some(self.lua.to_value_with(key, self.options)?);
Ok(())
}
@@ -486,29 +489,28 @@ impl<'lua> ser::SerializeMap for SerializeMap<'lua> {
where
T: Serialize + ?Sized,
{
- let lua = self.table.0.lua;
let key = mlua_expect!(
self.key.take(),
"serialize_value called before serialize_key"
);
- let value = lua.to_value_with(value, self.options)?;
+ let value = self.lua.to_value_with(value, self.options)?;
self.table.raw_set(key, value)
}
- fn end(self) -> Result<Value<'lua>> {
+ fn end(self) -> Result<Value> {
Ok(Value::Table(self.table))
}
}
#[doc(hidden)]
-pub struct SerializeStruct<'lua> {
- lua: &'lua Lua,
- inner: Option<Value<'lua>>,
+pub struct SerializeStruct<'a> {
+ lua: &'a Lua,
+ inner: Option<Value>,
options: Options,
}
-impl<'lua> ser::SerializeStruct for SerializeStruct<'lua> {
- type Ok = Value<'lua>;
+impl ser::SerializeStruct for SerializeStruct<'_> {
+ type Ok = Value;
type Error = Error;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
@@ -529,7 +531,7 @@ impl<'lua> ser::SerializeStruct for SerializeStruct<'lua> {
Ok(())
}
- fn end(self) -> Result<Value<'lua>> {
+ fn end(self) -> Result<Value> {
match self.inner {
Some(table @ Value::Table(_)) => Ok(table),
Some(value) if self.options.detect_serde_json_arbitrary_precision => {
@@ -551,29 +553,28 @@ impl<'lua> ser::SerializeStruct for SerializeStruct<'lua> {
}
#[doc(hidden)]
-pub struct SerializeStructVariant<'lua> {
+pub struct SerializeStructVariant<'a> {
+ lua: &'a Lua,
variant: &'static str,
- table: Table<'lua>,
+ table: Table,
options: Options,
}
-impl<'lua> ser::SerializeStructVariant for SerializeStructVariant<'lua> {
- type Ok = Value<'lua>;
+impl ser::SerializeStructVariant for SerializeStructVariant<'_> {
+ type Ok = Value;
type Error = Error;
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where
T: Serialize + ?Sized,
{
- let lua = self.table.0.lua;
self.table
- .raw_set(key, lua.to_value_with(value, self.options)?)?;
+ .raw_set(key, self.lua.to_value_with(value, self.options)?)?;
Ok(())
}
- fn end(self) -> Result<Value<'lua>> {
- let lua = self.table.0.lua;
- let table = lua.create_table_with_capacity(0, 1)?;
+ fn end(self) -> Result<Value> {
+ let table = self.lua.create_table_with_capacity(0, 1)?;
table.raw_set(self.variant, self.table)?;
Ok(Value::Table(table))
}
diff --git a/src/string.rs b/src/string.rs
index add8bdc..cde30ee 100644
--- a/src/string.rs
+++ b/src/string.rs
@@ -17,30 +17,9 @@ use crate::types::ValueRef;
///
/// Unlike Rust strings, Lua strings may not be valid UTF-8.
#[derive(Clone)]
-pub struct String<'lua>(pub(crate) ValueRef<'lua>);
+pub struct String(pub(crate) ValueRef);
-/// Owned handle to an internal Lua string.
-///
-/// The owned handle holds a *strong* reference to the current Lua instance.
-/// Be warned, if you place it into a Lua type (eg. [`UserData`] or a Rust callback), it is *very easy*
-/// to accidentally cause reference cycles that would prevent destroying Lua instance.
-///
-/// [`UserData`]: crate::UserData
-#[cfg(feature = "unstable")]
-#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
-#[derive(Clone)]
-pub struct OwnedString(pub(crate) crate::types::OwnedValueRef);
-
-#[cfg(feature = "unstable")]
-impl OwnedString {
- /// Get borrowed handle to the underlying Lua string.
- #[cfg_attr(feature = "send", allow(unused))]
- pub const fn to_ref(&self) -> String {
- String(self.0.to_ref())
- }
-}
-
-impl<'lua> String<'lua> {
+impl String {
/// Get a `&str` slice if the Lua string is valid UTF-8.
///
/// # Examples
@@ -116,7 +95,8 @@ impl<'lua> String<'lua> {
/// Get the bytes that make up this string, including the trailing nul byte.
pub fn as_bytes_with_nul(&self) -> &[u8] {
- let ref_thread = self.0.lua.ref_thread();
+ let lua = self.0.lua.lock();
+ let ref_thread = lua.ref_thread();
unsafe {
mlua_debug_assert!(
ffi::lua_type(ref_thread, self.0.index) == ffi::LUA_TSTRING,
@@ -141,17 +121,9 @@ impl<'lua> String<'lua> {
pub fn to_pointer(&self) -> *const c_void {
self.0.to_pointer()
}
-
- /// Convert this handle to owned version.
- #[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
- #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
- #[inline]
- pub fn into_owned(self) -> OwnedString {
- OwnedString(self.0.into_owned())
- }
}
-impl<'lua> fmt::Debug for String<'lua> {
+impl fmt::Debug for String {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let bytes = self.as_bytes();
// Check if the string is valid utf8
@@ -180,13 +152,13 @@ impl<'lua> fmt::Debug for String<'lua> {
}
}
-impl<'lua> AsRef<[u8]> for String<'lua> {
+impl AsRef<[u8]> for String {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
-impl<'lua> Borrow<[u8]> for String<'lua> {
+impl Borrow<[u8]> for String {
fn borrow(&self) -> &[u8] {
self.as_bytes()
}
@@ -200,7 +172,7 @@ impl<'lua> Borrow<[u8]> for String<'lua> {
// The only downside is that this disallows a comparison with `Cow<str>`, as that only implements
// `AsRef<str>`, which collides with this impl. Requiring `AsRef<str>` would fix that, but limit us
// in other ways.
-impl<'lua, T> PartialEq<T> for String<'lua>
+impl<T> PartialEq<T> for String
where
T: AsRef<[u8]> + ?Sized,
{
@@ -209,16 +181,16 @@ where
}
}
-impl<'lua> Eq for String<'lua> {}
+impl Eq for String {}
-impl<'lua> Hash for String<'lua> {
+impl Hash for String {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_bytes().hash(state);
}
}
#[cfg(feature = "serialize")]
-impl<'lua> Serialize for String<'lua> {
+impl Serialize for String {
fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
where
S: Serializer,
@@ -230,40 +202,9 @@ impl<'lua> Serialize for String<'lua> {
}
}
-// Additional shortcuts
-#[cfg(feature = "unstable")]
-impl OwnedString {
- /// Get a `&str` slice if the Lua string is valid UTF-8.
- ///
- /// This is a shortcut for [`String::to_str()`].
- #[inline]
- pub fn to_str(&self) -> Result<&str> {
- let s = self.to_ref();
- // Reattach lifetime to &self
- unsafe { std::mem::transmute(s.to_str()) }
- }
-
- /// Get the bytes that make up this string.
- ///
- /// This is a shortcut for [`String::as_bytes()`].
- #[inline]
- pub fn as_bytes(&self) -> &[u8] {
- let s = self.to_ref();
- // Reattach lifetime to &self
- unsafe { std::mem::transmute(s.as_bytes()) }
- }
-}
-
-#[cfg(feature = "unstable")]
-impl fmt::Debug for OwnedString {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.to_ref().fmt(f)
- }
-}
-
-#[cfg(test)]
-mod assertions {
- use super::*;
+// #[cfg(test)]
+// mod assertions {
+// use super::*;
- static_assertions::assert_not_impl_any!(String: Send);
-}
+// static_assertions::assert_not_impl_any!(String: Send);
+// }
diff --git a/src/table.rs b/src/table.rs
index 9eca8d5..3e0edb5 100644
--- a/src/table.rs
+++ b/src/table.rs
@@ -22,30 +22,9 @@ use futures_util::future::{self, LocalBoxFuture};
/// Handle to an internal Lua table.
#[derive(Clone)]
-pub struct Table<'lua>(pub(crate) ValueRef<'lua>);
+pub struct Table(pub(crate) ValueRef);
-/// Owned handle to an internal Lua table.
-///
-/// The owned handle holds a *strong* reference to the current Lua instance.
-/// Be warned, if you place it into a Lua type (eg. [`UserData`] or a Rust callback), it is *very easy*
-/// to accidentally cause reference cycles that would prevent destroying Lua instance.
-///
-/// [`UserData`]: crate::UserData
-#[cfg(feature = "unstable")]
-#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
-#[derive(Clone, Debug)]
-pub struct OwnedTable(pub(crate) crate::types::OwnedValueRef);
-
-#[cfg(feature = "unstable")]
-impl OwnedTable {
- /// Get borrowed handle to the underlying Lua table.
- #[cfg_attr(feature = "send", allow(unused))]
- pub const fn to_ref(&self) -> Table {
- Table(self.0.to_ref())
- }
-}
-
-impl<'lua> Table<'lua> {
+impl Table {
/// Sets a key-value pair in the table.
///
/// If the value is `nil`, this will effectively remove the pair.
@@ -85,15 +64,15 @@ impl<'lua> Table<'lua> {
return self.raw_set(key, value);
}
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 5)?;
lua.push_ref(&self.0);
- key.push_into_stack(lua)?;
- value.push_into_stack(lua)?;
+ key.push_into_stack(&lua)?;
+ value.push_into_stack(&lua)?;
protect_lua!(state, 3, 0, fn(state) ffi::lua_settable(state, -3))
}
}
@@ -122,23 +101,23 @@ impl<'lua> Table<'lua> {
/// ```
///
/// [`raw_get`]: #method.raw_get
- pub fn get<K: IntoLua, V: FromLua<'lua>>(&self, key: K) -> Result<V> {
+ pub fn get<K: IntoLua, V: FromLua>(&self, key: K) -> Result<V> {
// Fast track
if !self.has_metatable() {
return self.raw_get(key);
}
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 4)?;
lua.push_ref(&self.0);
- key.push_into_stack(lua)?;
+ key.push_into_stack(&lua)?;
protect_lua!(state, 2, 1, fn(state) ffi::lua_gettable(state, -2))?;
- V::from_stack(-1, lua)
+ V::from_stack(-1, &lua)
}
}
@@ -158,14 +137,14 @@ impl<'lua> Table<'lua> {
return self.raw_push(value);
}
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 4)?;
lua.push_ref(&self.0);
- value.push_into_stack(lua)?;
+ value.push_into_stack(&lua)?;
protect_lua!(state, 2, 0, fn(state) {
let len = ffi::luaL_len(state, -2) as Integer;
ffi::lua_seti(state, -2, len + 1);
@@ -177,13 +156,13 @@ impl<'lua> Table<'lua> {
/// Removes the last element from the table and returns it.
///
/// This might invoke the `__len` and `__newindex` metamethods.
- pub fn pop<V: FromLua<'lua>>(&self) -> Result<V> {
+ pub fn pop<V: FromLua>(&self) -> Result<V> {
// Fast track
if !self.has_metatable() {
return self.raw_pop();
}
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -196,7 +175,7 @@ impl<'lua> Table<'lua> {
ffi::lua_pushnil(state);
ffi::lua_seti(state, -3, len);
})?;
- V::from_stack(-1, lua)
+ V::from_stack(-1, &lua)
}
}
@@ -257,15 +236,15 @@ impl<'lua> Table<'lua> {
#[cfg(feature = "luau")]
self.check_readonly_write()?;
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 5)?;
lua.push_ref(&self.0);
- key.push_into_stack(lua)?;
- value.push_into_stack(lua)?;
+ key.push_into_stack(&lua)?;
+ value.push_into_stack(&lua)?;
if lua.unlikely_memory_error() {
ffi::lua_rawset(state, -3);
@@ -278,18 +257,18 @@ impl<'lua> Table<'lua> {
}
/// Gets the value associated to `key` without invoking metamethods.
- pub fn raw_get<K: IntoLua, V: FromLua<'lua>>(&self, key: K) -> Result<V> {
- let lua = self.0.lua;
+ pub fn raw_get<K: IntoLua, V: FromLua>(&self, key: K) -> Result<V> {
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 3)?;
lua.push_ref(&self.0);
- key.push_into_stack(lua)?;
+ key.push_into_stack(&lua)?;
ffi::lua_rawget(state, -2);
- V::from_stack(-1, lua)
+ V::from_stack(-1, &lua)
}
}
@@ -301,14 +280,14 @@ impl<'lua> Table<'lua> {
return Err(Error::runtime("index out of bounds"));
}
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 5)?;
lua.push_ref(&self.0);
- value.push_into_stack(lua)?;
+ value.push_into_stack(&lua)?;
protect_lua!(state, 2, 0, |state| {
for i in (idx..=size).rev() {
// table[i+1] = table[i]
@@ -325,14 +304,14 @@ impl<'lua> Table<'lua> {
#[cfg(feature = "luau")]
self.check_readonly_write()?;
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 4)?;
lua.push_ref(&self.0);
- value.push_into_stack(lua)?;
+ value.push_into_stack(&lua)?;
unsafe fn callback(state: *mut ffi::lua_State) {
let len = ffi::lua_rawlen(state, -2) as Integer;
@@ -349,11 +328,11 @@ impl<'lua> Table<'lua> {
}
/// Removes the last element from the table and returns it, without invoking metamethods.
- pub fn raw_pop<V: FromLua<'lua>>(&self) -> Result<V> {
+ pub fn raw_pop<V: FromLua>(&self) -> Result<V> {
#[cfg(feature = "luau")]
self.check_readonly_write()?;
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -366,7 +345,7 @@ impl<'lua> Table<'lua> {
ffi::lua_pushnil(state);
ffi::lua_rawseti(state, -3, len);
- V::from_stack(-1, lua)
+ V::from_stack(-1, &lua)
}
}
@@ -378,9 +357,9 @@ impl<'lua> Table<'lua> {
///
/// For other key types this is equivalent to setting `table[key] = nil`.
pub fn raw_remove<K: IntoLua>(&self, key: K) -> Result<()> {
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
- let key = key.into_lua(lua)?;
+ let key = key.into_lua(lua.lua())?;
match key {
Value::Integer(idx) => {
let size = self.raw_len() as Integer;
@@ -414,7 +393,7 @@ impl<'lua> Table<'lua> {
#[cfg(feature = "luau")]
self.check_readonly_write()?;
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
unsafe {
#[cfg(feature = "luau")]
ffi::lua_cleartable(lua.ref_thread(), self.0.index);
@@ -458,7 +437,7 @@ impl<'lua> Table<'lua> {
return Ok(self.raw_len() as Integer);
}
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -471,8 +450,8 @@ impl<'lua> Table<'lua> {
/// Returns the result of the Lua `#` operator, without invoking the `__len` metamethod.
pub fn raw_len(&self) -> usize {
- let ref_thread = self.0.lua.ref_thread();
- unsafe { ffi::lua_rawlen(ref_thread, self.0.index) }
+ let lua = self.0.lua.lock();
+ unsafe { ffi::lua_rawlen(lua.ref_thread(), self.0.index) }
}
/// Returns `true` if the table is empty, without invoking metamethods.
@@ -485,7 +464,7 @@ impl<'lua> Table<'lua> {
}
// Check hash part
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -504,8 +483,8 @@ impl<'lua> Table<'lua> {
/// Returns a reference to the metatable of this table, or `None` if no metatable is set.
///
/// Unlike the `getmetatable` Lua function, this method ignores the `__metatable` field.
- pub fn get_metatable(&self) -> Option<Table<'lua>> {
- let lua = self.0.lua;
+ pub fn get_metatable(&self) -> Option<Table> {
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -524,14 +503,14 @@ impl<'lua> Table<'lua> {
///
/// If `metatable` is `None`, the metatable is removed (if no metatable is set, this does
/// nothing).
- pub fn set_metatable(&self, metatable: Option<Table<'lua>>) {
+ pub fn set_metatable(&self, metatable: Option<Table>) {
// Workaround to throw readonly error without returning Result
#[cfg(feature = "luau")]
if self.is_readonly() {
panic!("attempt to modify a readonly table");
}
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -551,7 +530,8 @@ impl<'lua> Table<'lua> {
#[doc(hidden)]
#[inline]
pub fn has_metatable(&self) -> bool {
- let ref_thread = self.0.lua.ref_thread();
+ let lua = self.0.lua.lock();
+ let ref_thread = lua.ref_thread();
unsafe {
if ffi::lua_getmetatable(ref_thread, self.0.index) != 0 {
ffi::lua_pop(ref_thread, 1);
@@ -567,7 +547,8 @@ impl<'lua> Table<'lua> {
#[cfg(any(feature = "luau", doc))]
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
pub fn set_readonly(&self, enabled: bool) {
- let ref_thread = self.0.lua.ref_thread();
+ let lua = self.0.lua.lock();
+ let ref_thread = lua.ref_thread();
unsafe {
ffi::lua_setreadonly(ref_thread, self.0.index, enabled as _);
if !enabled {
@@ -583,7 +564,8 @@ impl<'lua> Table<'lua> {
#[cfg(any(feature = "luau", doc))]
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
pub fn is_readonly(&self) -> bool {
- let ref_thread = self.0.lua.ref_thread();
+ let lua = self.0.lua.lock();
+ let ref_thread = lua.ref_thread();
unsafe { ffi::lua_getreadonly(ref_thread, self.0.index) != 0 }
}
@@ -598,14 +580,6 @@ impl<'lua> Table<'lua> {
self.0.to_pointer()
}
- /// Convert this handle to owned version.
- #[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
- #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
- #[inline]
- pub fn into_owned(self) -> OwnedTable {
- OwnedTable(self.0.into_owned())
- }
-
/// Consume this table and return an iterator over the pairs of the table.
///
/// This works like the Lua `pairs` function, but does not invoke the `__pairs` metamethod.
@@ -639,7 +613,7 @@ impl<'lua> Table<'lua> {
///
/// [`Result`]: crate::Result
/// [Lua manual]: http://www.lua.org/manual/5.4/manual.html#pdf-next
- pub fn pairs<K: FromLua<'lua>, V: FromLua<'lua>>(self) -> TablePairs<'lua, K, V> {
+ pub fn pairs<K: FromLua, V: FromLua>(self) -> TablePairs<K, V> {
TablePairs {
table: self.0,
key: Some(Nil),
@@ -653,10 +627,10 @@ impl<'lua> Table<'lua> {
/// It does not invoke the `__pairs` metamethod.
pub fn for_each<K, V>(&self, mut f: impl FnMut(K, V) -> Result<()>) -> Result<()>
where
- K: FromLua<'lua>,
- V: FromLua<'lua>,
+ K: FromLua,
+ V: FromLua,
{
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -665,8 +639,8 @@ impl<'lua> Table<'lua> {
lua.push_ref(&self.0);
ffi::lua_pushnil(state);
while ffi::lua_next(state, -2) != 0 {
- let k = K::from_stack(-2, lua)?;
- let v = V::from_stack(-1, lua)?;
+ let k = K::from_stack(-2, &lua)?;
+ let v = V::from_stack(-1, &lua)?;
f(k, v)?;
// Keep key for next iteration
ffi::lua_pop(state, 1);
@@ -713,7 +687,7 @@ impl<'lua> Table<'lua> {
/// [`pairs`]: #method.pairs
/// [`Result`]: crate::Result
/// [Lua manual]: http://www.lua.org/manual/5.4/manual.html#pdf-next
- pub fn sequence_values<V: FromLua<'lua>>(self) -> TableSequence<'lua, V> {
+ pub fn sequence_values<V: FromLua>(self) -> TableSequence<V> {
TableSequence {
table: self.0,
index: 1,
@@ -723,16 +697,16 @@ impl<'lua> Table<'lua> {
#[doc(hidden)]
#[deprecated(since = "0.9.0", note = "use `sequence_values` instead")]
- pub fn raw_sequence_values<V: FromLua<'lua>>(self) -> TableSequence<'lua, V> {
+ pub fn raw_sequence_values<V: FromLua>(self) -> TableSequence<V> {
self.sequence_values()
}
#[cfg(feature = "serialize")]
pub(crate) fn for_each_value<V>(&self, mut f: impl FnMut(V) -> Result<()>) -> Result<()>
where
- V: FromLua<'lua>,
+ V: FromLua,
{
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -742,7 +716,7 @@ impl<'lua> Table<'lua> {
let len = ffi::lua_rawlen(state, -1);
for i in 1..=len {
ffi::lua_rawgeti(state, -1, i as _);
- f(V::from_stack(-1, lua)?)?;
+ f(V::from_stack(-1, &lua)?)?;
ffi::lua_pop(state, 1);
}
}
@@ -755,14 +729,14 @@ impl<'lua> Table<'lua> {
#[cfg(feature = "luau")]
self.check_readonly_write()?;
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
check_stack(state, 5)?;
lua.push_ref(&self.0);
- value.push_into_stack(lua)?;
+ value.push_into_stack(&lua)?;
let idx = idx.try_into().unwrap();
if lua.unlikely_memory_error() {
@@ -776,7 +750,7 @@ impl<'lua> Table<'lua> {
#[cfg(feature = "serialize")]
pub(crate) fn is_array(&self) -> bool {
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -828,7 +802,7 @@ impl<'lua> Table<'lua> {
}
}
-impl fmt::Debug for Table<'_> {
+impl fmt::Debug for Table {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
if fmt.alternate() {
return self.fmt_pretty(fmt, 0, &mut HashSet::new());
@@ -837,25 +811,25 @@ impl fmt::Debug for Table<'_> {
}
}
-impl<'lua> PartialEq for Table<'lua> {
+impl PartialEq for Table {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
-impl<'lua> AsRef<Table<'lua>> for Table<'lua> {
+impl AsRef<Table> for Table {
#[inline]
fn as_ref(&self) -> &Self {
self
}
}
-impl<'lua, T> PartialEq<[T]> for Table<'lua>
+impl<T> PartialEq<[T]> for Table
where
T: IntoLua + Clone,
{
fn eq(&self, other: &[T]) -> bool {
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -870,7 +844,7 @@ where
if val == Nil {
return i == other.len();
}
- match other.get(i).map(|v| v.clone().into_lua(lua)) {
+ match other.get(i).map(|v| v.clone().into_lua(lua.lua())) {
Some(Ok(other_val)) if val == other_val => continue,
_ => return false,
}
@@ -880,7 +854,7 @@ where
}
}
-impl<'lua, T> PartialEq<&[T]> for Table<'lua>
+impl<T> PartialEq<&[T]> for Table
where
T: IntoLua + Clone,
{
@@ -890,7 +864,7 @@ where
}
}
-impl<'lua, T, const N: usize> PartialEq<[T; N]> for Table<'lua>
+impl<T, const N: usize> PartialEq<[T; N]> for Table
where
T: IntoLua + Clone,
{
@@ -901,24 +875,24 @@ where
}
/// An extension trait for `Table`s that provides a variety of convenient functionality.
-pub trait TableExt<'lua>: Sealed {
+pub trait TableExt: Sealed {
/// Calls the table as function assuming it has `__call` metamethod.
///
/// The metamethod is called with the table as its first argument, followed by the passed arguments.
fn call<A, R>(&self, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>;
+ R: FromLuaMulti;
/// Asynchronously calls the table as function assuming it has `__call` metamethod.
///
/// The metamethod is called with the table as its first argument, followed by the passed arguments.
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- fn call_async<A, R>(&self, args: A) -> LocalBoxFuture<'lua, Result<R>>
+ fn call_async<A, R>(&self, args: A) -> LocalBoxFuture<'static, Result<R>>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua;
+ R: FromLuaMulti + 'static;
/// Gets the function associated to `key` from the table and executes it,
/// passing the table itself along with `args` as function arguments.
@@ -930,7 +904,7 @@ pub trait TableExt<'lua>: Sealed {
fn call_method<A, R>(&self, name: &str, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>;
+ R: FromLuaMulti;
/// Gets the function associated to `key` from the table and executes it,
/// passing `args` as function arguments.
@@ -942,7 +916,7 @@ pub trait TableExt<'lua>: Sealed {
fn call_function<A, R>(&self, name: &str, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>;
+ R: FromLuaMulti;
/// Gets the function associated to `key` from the table and asynchronously executes it,
/// passing the table itself along with `args` as function arguments and returning Future.
@@ -952,10 +926,10 @@ pub trait TableExt<'lua>: Sealed {
/// This might invoke the `__index` metamethod.
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- fn call_async_method<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'lua, Result<R>>
+ fn call_async_method<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'static, Result<R>>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua;
+ R: FromLuaMulti + 'static;
/// Gets the function associated to `key` from the table and asynchronously executes it,
/// passing `args` as function arguments and returning Future.
@@ -965,29 +939,30 @@ pub trait TableExt<'lua>: Sealed {
/// This might invoke the `__index` metamethod.
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- fn call_async_function<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'lua, Result<R>>
+ fn call_async_function<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'static, Result<R>>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua;
+ R: FromLuaMulti + 'static;
}
-impl<'lua> TableExt<'lua> for Table<'lua> {
+impl TableExt for Table {
fn call<A, R>(&self, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>,
+ R: FromLuaMulti,
{
// Convert table to a function and call via pcall that respects the `__call` metamethod.
Function(self.0.clone()).call(args)
}
#[cfg(feature = "async")]
- fn call_async<A, R>(&self, args: A) -> LocalBoxFuture<'lua, Result<R>>
+ fn call_async<A, R>(&self, args: A) -> LocalBoxFuture<'static, Result<R>>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua,
+ R: FromLuaMulti + 'static,
{
- let args = match args.into_lua_multi(self.0.lua) {
+ let lua = self.0.lua.lock();
+ let args = match args.into_lua_multi(lua.lua()) {
Ok(args) => args,
Err(e) => return Box::pin(future::err(e)),
};
@@ -998,7 +973,7 @@ impl<'lua> TableExt<'lua> for Table<'lua> {
fn call_method<A, R>(&self, name: &str, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>,
+ R: FromLuaMulti,
{
self.get::<_, Function>(name)?.call((self, args))
}
@@ -1006,30 +981,30 @@ impl<'lua> TableExt<'lua> for Table<'lua> {
fn call_function<A, R>(&self, name: &str, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>,
+ R: FromLuaMulti,
{
self.get::<_, Function>(name)?.call(args)
}
#[cfg(feature = "async")]
- fn call_async_method<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'lua, Result<R>>
+ fn call_async_method<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'static, Result<R>>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua,
+ R: FromLuaMulti + 'static,
{
self.call_async_function(name, (self, args))
}
#[cfg(feature = "async")]
- fn call_async_function<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'lua, Result<R>>
+ fn call_async_function<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'static, Result<R>>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua,
+ R: FromLuaMulti + 'static,
{
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
match self.get::<_, Function>(name) {
Ok(func) => {
- let args = match args.into_lua_multi(lua) {
+ let args = match args.into_lua_multi(lua.lua()) {
Ok(args) => args,
Err(e) => return Box::pin(future::err(e)),
};
@@ -1042,14 +1017,14 @@ impl<'lua> TableExt<'lua> for Table<'lua> {
/// A wrapped [`Table`] with customized serialization behavior.
#[cfg(feature = "serialize")]
-pub(crate) struct SerializableTable<'a, 'lua> {
- table: &'a Table<'lua>,
+pub(crate) struct SerializableTable<'a> {
+ table: &'a Table,
options: crate::serde::de::Options,
visited: Rc<RefCell<FxHashSet<*const c_void>>>,
}
#[cfg(feature = "serialize")]
-impl<'lua> Serialize for Table<'lua> {
+impl Serialize for Table {
#[inline]
fn serialize<S: Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
SerializableTable::new(self, Default::default(), Default::default()).serialize(serializer)
@@ -1057,10 +1032,10 @@ impl<'lua> Serialize for Table<'lua> {
}
#[cfg(feature = "serialize")]
-impl<'a, 'lua> SerializableTable<'a, 'lua> {
+impl<'a> SerializableTable<'a> {
#[inline]
pub(crate) fn new(
- table: &'a Table<'lua>,
+ table: &'a Table,
options: crate::serde::de::Options,
visited: Rc<RefCell<FxHashSet<*const c_void>>>,
) -> Self {
@@ -1073,7 +1048,7 @@ impl<'a, 'lua> SerializableTable<'a, 'lua> {
}
#[cfg(feature = "serialize")]
-impl<'a, 'lua> Serialize for SerializableTable<'a, 'lua> {
+impl<'a> Serialize for SerializableTable<'a> {
fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
where
S: Serializer,
@@ -1157,22 +1132,22 @@ impl<'a, 'lua> Serialize for SerializableTable<'a, 'lua> {
/// This struct is created by the [`Table::pairs`] method.
///
/// [`Table::pairs`]: crate::Table::pairs
-pub struct TablePairs<'lua, K, V> {
- table: ValueRef<'lua>,
- key: Option<Value<'lua>>,
+pub struct TablePairs<K, V> {
+ table: ValueRef,
+ key: Option<Value>,
_phantom: PhantomData<(K, V)>,
}
-impl<'lua, K, V> Iterator for TablePairs<'lua, K, V>
+impl<K, V> Iterator for TablePairs<K, V>
where
- K: FromLua<'lua>,
- V: FromLua<'lua>,
+ K: FromLua,
+ V: FromLua,
{
type Item = Result<(K, V)>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(prev_key) = self.key.take() {
- let lua = self.table.lua;
+ let lua = self.table.lua.lock();
let state = lua.state();
let res = (|| unsafe {
@@ -1189,8 +1164,8 @@ where
let key = lua.stack_value(-2);
Ok(Some((
key.clone(),
- K::from_lua(key, lua)?,
- V::from_stack(-1, lua)?,
+ K::from_lua(key, lua.lua())?,
+ V::from_stack(-1, &lua)?,
)))
} else {
Ok(None)
@@ -1216,21 +1191,21 @@ where
/// This struct is created by the [`Table::sequence_values`] method.
///
/// [`Table::sequence_values`]: crate::Table::sequence_values
-pub struct TableSequence<'lua, V> {
+pub struct TableSequence<V> {
// TODO: Use `&Table`
- table: ValueRef<'lua>,
+ table: ValueRef,
index: Integer,
_phantom: PhantomData<V>,
}
-impl<'lua, V> Iterator for TableSequence<'lua, V>
+impl<V> Iterator for TableSequence<V>
where
- V: FromLua<'lua>,
+ V: FromLua,
{
type Item = Result<V>;
fn next(&mut self) -> Option<Self::Item> {
- let lua = self.table.lua;
+ let lua = self.table.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -1243,19 +1218,16 @@ where
ffi::LUA_TNIL => None,
_ => {
self.index += 1;
- Some(V::from_stack(-1, lua))
+ Some(V::from_stack(-1, &lua))
}
}
}
}
}
-#[cfg(test)]
-mod assertions {
- use super::*;
+// #[cfg(test)]
+// mod assertions {
+// use super::*;
- static_assertions::assert_not_impl_any!(Table: Send);
-
- #[cfg(feature = "unstable")]
- static_assertions::assert_not_impl_any!(OwnedTable: Send);
-}
+// static_assertions::assert_not_impl_any!(Table: Send);
+// }
diff --git a/src/thread.rs b/src/thread.rs
index 489416f..b6a0e86 100644
--- a/src/thread.rs
+++ b/src/thread.rs
@@ -3,6 +3,7 @@ use std::os::raw::{c_int, c_void};
use crate::error::{Error, Result};
#[allow(unused)]
use crate::lua::Lua;
+use crate::lua::LuaInner;
use crate::types::ValueRef;
use crate::util::{check_stack, error_traceback_thread, pop_error, StackGuard};
use crate::value::{FromLuaMulti, IntoLuaMulti};
@@ -43,31 +44,7 @@ pub enum ThreadStatus {
/// Handle to an internal Lua thread (coroutine).
#[derive(Clone, Debug)]
-pub struct Thread<'lua>(pub(crate) ValueRef<'lua>, pub(crate) *mut ffi::lua_State);
-
-/// Owned handle to an internal Lua thread (coroutine).
-///
-/// The owned handle holds a *strong* reference to the current Lua instance.
-/// Be warned, if you place it into a Lua type (eg. [`UserData`] or a Rust callback), it is *very easy*
-/// to accidentally cause reference cycles that would prevent destroying Lua instance.
-///
-/// [`UserData`]: crate::UserData
-#[cfg(feature = "unstable")]
-#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
-#[derive(Clone, Debug)]
-pub struct OwnedThread(
- pub(crate) crate::types::OwnedValueRef,
- pub(crate) *mut ffi::lua_State,
-);
-
-#[cfg(feature = "unstable")]
-impl OwnedThread {
- /// Get borrowed handle to the underlying Lua table.
- #[cfg_attr(feature = "send", allow(unused))]
- pub const fn to_ref(&self) -> Thread {
- Thread(self.0.to_ref(), self.1)
- }
-}
+pub struct Thread(pub(crate) ValueRef, pub(crate) *mut ffi::lua_State);
/// Thread (coroutine) representation as an async [`Future`] or [`Stream`].
///
@@ -78,17 +55,17 @@ impl OwnedThread {
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
#[must_use = "futures do nothing unless you `.await` or poll them"]
-pub struct AsyncThread<'lua, R> {
- thread: Thread<'lua>,
- init_args: Option<Result<MultiValue<'lua>>>,
+pub struct AsyncThread<R> {
+ thread: Thread,
+ init_args: Option<Result<MultiValue>>,
ret: PhantomData<R>,
recycle: bool,
}
-impl<'lua> Thread<'lua> {
+impl Thread {
#[inline(always)]
- pub(crate) fn new(r#ref: ValueRef<'lua>) -> Self {
- let state = unsafe { ffi::lua_tothread(r#ref.lua.ref_thread(), r#ref.index) };
+ pub(crate) fn new(lua: &LuaInner, r#ref: ValueRef) -> Self {
+ let state = unsafe { ffi::lua_tothread(lua.ref_thread(), r#ref.index) };
Thread(r#ref, state)
}
@@ -140,13 +117,14 @@ impl<'lua> Thread<'lua> {
pub fn resume<A, R>(&self, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>,
+ R: FromLuaMulti,
{
- if self.status() != ThreadStatus::Resumable {
+ let lua = self.0.lua.lock();
+
+ if unsafe { self.status_unprotected() } != ThreadStatus::Resumable {
return Err(Error::CoroutineInactive);
}
- let lua = self.0.lua;
let state = lua.state();
let thread_state = self.state();
unsafe {
@@ -157,7 +135,7 @@ impl<'lua> Thread<'lua> {
check_stack(state, nresults + 1)?;
ffi::lua_xmove(thread_state, state, nresults);
- R::from_stack_multi(nresults, lua)
+ R::from_stack_multi(nresults, &lua)
}
}
@@ -165,11 +143,11 @@ impl<'lua> Thread<'lua> {
///
/// It's similar to `resume()` but leaves `nresults` values on the thread stack.
unsafe fn resume_inner<A: IntoLuaMulti>(&self, args: A) -> Result<c_int> {
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
let thread_state = self.state();
- let nargs = args.push_into_stack_multi(lua)?;
+ let nargs = args.push_into_stack_multi(&lua)?;
if nargs > 0 {
check_stack(thread_state, nargs)?;
ffi::lua_xmove(state, thread_state, nargs);
@@ -195,20 +173,25 @@ impl<'lua> Thread<'lua> {
/// Gets the status of the thread.
pub fn status(&self) -> ThreadStatus {
+ let _guard = self.0.lua.lock();
+ unsafe { self.status_unprotected() }
+ }
+
+ /// Gets the status of the thread without locking the Lua state.
+ pub(crate) unsafe fn status_unprotected(&self) -> ThreadStatus {
let thread_state = self.state();
- if thread_state == self.0.lua.state() {
+ // FIXME: skip double lock
+ if thread_state == self.0.lua.lock().state() {
// The coroutine is currently running
return ThreadStatus::Unresumable;
}
- unsafe {
- let status = ffi::lua_status(thread_state);
- if status != ffi::LUA_OK && status != ffi::LUA_YIELD {
- ThreadStatus::Error
- } else if status == ffi::LUA_YIELD || ffi::lua_gettop(thread_state) > 0 {
- ThreadStatus::Resumable
- } else {
- ThreadStatus::Unresumable
- }
+ let status = ffi::lua_status(thread_state);
+ if status != ffi::LUA_OK && status != ffi::LUA_YIELD {
+ ThreadStatus::Error
+ } else if status == ffi::LUA_YIELD || ffi::lua_gettop(thread_state) > 0 {
+ ThreadStatus::Resumable
+ } else {
+ ThreadStatus::Unresumable
}
}
@@ -222,7 +205,7 @@ impl<'lua> Thread<'lua> {
where
F: Fn(&Lua, Debug) -> Result<()> + MaybeSend + 'static,
{
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
unsafe {
lua.set_thread_hook(self.state(), triggers, callback);
}
@@ -244,8 +227,8 @@ impl<'lua> Thread<'lua> {
/// [Lua 5.4]: https://www.lua.org/manual/5.4/manual.html#lua_closethread
#[cfg(any(feature = "lua54", feature = "luau"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "lua54", feature = "luau"))))]
- pub fn reset(&self, func: crate::function::Function<'lua>) -> Result<()> {
- let lua = self.0.lua;
+ pub fn reset(&self, func: crate::function::Function) -> Result<()> {
+ let lua = self.0.lua.lock();
let thread_state = self.state();
if thread_state == lua.state() {
return Err(Error::runtime("cannot reset a running thread"));
@@ -323,12 +306,13 @@ impl<'lua> Thread<'lua> {
/// ```
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- pub fn into_async<A, R>(self, args: A) -> AsyncThread<'lua, R>
+ pub fn into_async<A, R>(self, args: A) -> AsyncThread<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>,
+ R: FromLuaMulti,
{
- let args = args.into_lua_multi(self.0.lua);
+ let lua = self.0.lua.lock();
+ let args = args.into_lua_multi(lua.lua());
AsyncThread {
thread: self,
init_args: Some(args),
@@ -372,7 +356,7 @@ impl<'lua> Thread<'lua> {
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
#[doc(hidden)]
pub fn sandbox(&self) -> Result<()> {
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
let thread_state = self.state();
unsafe {
@@ -391,44 +375,16 @@ impl<'lua> Thread<'lua> {
pub fn to_pointer(&self) -> *const c_void {
self.0.to_pointer()
}
-
- /// Convert this handle to owned version.
- #[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
- #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
- #[inline]
- pub fn into_owned(self) -> OwnedThread {
- OwnedThread(self.0.into_owned(), self.1)
- }
}
-impl<'lua> PartialEq for Thread<'lua> {
+impl PartialEq for Thread {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
-// Additional shortcuts
-#[cfg(feature = "unstable")]
-impl OwnedThread {
- /// Resumes execution of this thread.
- ///
- /// See [`Thread::resume()`] for more details.
- pub fn resume<'lua, A, R>(&'lua self, args: A) -> Result<R>
- where
- A: IntoLuaMulti,
- R: FromLuaMulti<'lua>,
- {
- self.to_ref().resume(args)
- }
-
- /// Gets the status of the thread.
- pub fn status(&self) -> ThreadStatus {
- self.to_ref().status()
- }
-}
-
#[cfg(feature = "async")]
-impl<'lua, R> AsyncThread<'lua, R> {
+impl<R> AsyncThread<R> {
#[inline]
pub(crate) fn set_recyclable(&mut self, recyclable: bool) {
self.recycle = recyclable;
@@ -437,15 +393,15 @@ impl<'lua, R> AsyncThread<'lua, R> {
#[cfg(feature = "async")]
#[cfg(any(feature = "lua54", feature = "luau"))]
-impl<'lua, R> Drop for AsyncThread<'lua, R> {
+impl<R> Drop for AsyncThread<R> {
fn drop(&mut self) {
if self.recycle {
unsafe {
- let lua = self.thread.0.lua;
+ let lua = self.thread.0.lua.lock();
// For Lua 5.4 this also closes all pending to-be-closed variables
if !lua.recycle_thread(&mut self.thread) {
#[cfg(feature = "lua54")]
- if self.thread.status() == ThreadStatus::Error {
+ if self.thread.status_unprotected() == ThreadStatus::Error {
#[cfg(not(feature = "vendored"))]
ffi::lua_resetthread(self.thread.state());
#[cfg(feature = "vendored")]
@@ -458,24 +414,21 @@ impl<'lua, R> Drop for AsyncThread<'lua, R> {
}
#[cfg(feature = "async")]
-impl<'lua, R> Stream for AsyncThread<'lua, R>
-where
- R: FromLuaMulti<'lua>,
-{
+impl<R: FromLuaMulti> Stream for AsyncThread<R> {
type Item = Result<R>;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
- if self.thread.status() != ThreadStatus::Resumable {
- return Poll::Ready(None);
- }
-
- let lua = self.thread.0.lua;
+ let lua = self.thread.0.lua.lock();
let state = lua.state();
let thread_state = self.thread.state();
unsafe {
+ if self.thread.status_unprotected() != ThreadStatus::Resumable {
+ return Poll::Ready(None);
+ }
+
let _sg = StackGuard::new(state);
let _thread_sg = StackGuard::with_top(thread_state, 0);
- let _wg = WakerGuard::new(lua, cx.waker());
+ let _wg = WakerGuard::new(&lua, cx.waker());
// This is safe as we are not moving the whole struct
let this = self.get_unchecked_mut();
@@ -493,30 +446,27 @@ where
ffi::lua_xmove(thread_state, state, nresults);
cx.waker().wake_by_ref();
- Poll::Ready(Some(R::from_stack_multi(nresults, lua)))
+ Poll::Ready(Some(R::from_stack_multi(nresults, &lua)))
}
}
}
#[cfg(feature = "async")]
-impl<'lua, R> Future for AsyncThread<'lua, R>
-where
- R: FromLuaMulti<'lua>,
-{
+impl<R: FromLuaMulti> Future for AsyncThread<R> {
type Output = Result<R>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
- if self.thread.status() != ThreadStatus::Resumable {
- return Poll::Ready(Err(Error::CoroutineInactive));
- }
-
- let lua = self.thread.0.lua;
+ let lua = self.thread.0.lua.lock();
let state = lua.state();
let thread_state = self.thread.state();
unsafe {
+ if self.thread.status_unprotected() != ThreadStatus::Resumable {
+ return Poll::Ready(Err(Error::CoroutineInactive));
+ }
+
let _sg = StackGuard::new(state);
let _thread_sg = StackGuard::with_top(thread_state, 0);
- let _wg = WakerGuard::new(lua, cx.waker());
+ let _wg = WakerGuard::new(&lua, cx.waker());
// This is safe as we are not moving the whole struct
let this = self.get_unchecked_mut();
@@ -539,7 +489,7 @@ where
check_stack(state, nresults + 1)?;
ffi::lua_xmove(thread_state, state, nresults);
- Poll::Ready(R::from_stack_multi(nresults, lua))
+ Poll::Ready(R::from_stack_multi(nresults, &lua))
}
}
}
@@ -552,7 +502,7 @@ unsafe fn is_poll_pending(state: *mut ffi::lua_State) -> bool {
#[cfg(feature = "async")]
struct WakerGuard<'lua, 'a> {
- lua: &'lua Lua,
+ lua: &'lua LuaInner,
prev: NonNull<Waker>,
_phantom: PhantomData<&'a ()>,
}
@@ -560,7 +510,7 @@ struct WakerGuard<'lua, 'a> {
#[cfg(feature = "async")]
impl<'lua, 'a> WakerGuard<'lua, 'a> {
#[inline]
- pub fn new(lua: &'lua Lua, waker: &'a Waker) -> Result<WakerGuard<'lua, 'a>> {
+ pub fn new(lua: &'lua LuaInner, waker: &'a Waker) -> Result<WakerGuard<'lua, 'a>> {
let prev = unsafe { lua.set_waker(NonNull::from(waker)) };
Ok(WakerGuard {
lua,
diff --git a/src/types.rs b/src/types.rs
index aa8ccad..f15f79e 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -5,22 +5,20 @@ use std::ops::{Deref, DerefMut};
use std::os::raw::{c_int, c_void};
use std::result::Result as StdResult;
use std::sync::atomic::{AtomicI32, Ordering};
-use std::sync::{Arc, Mutex};
+use std::sync::Arc;
use std::{fmt, mem, ptr};
+use parking_lot::{Mutex, RawMutex, RawThreadId};
use rustc_hash::FxHashMap;
use crate::error::Result;
#[cfg(not(feature = "luau"))]
use crate::hook::Debug;
-use crate::lua::{ExtraData, Lua};
+use crate::lua::{ExtraData, Lua, LuaGuard, LuaInner, WeakLua};
#[cfg(feature = "async")]
use {crate::value::MultiValue, futures_util::future::LocalBoxFuture};
-#[cfg(feature = "unstable")]
-use {crate::lua::LuaInner, std::marker::PhantomData};
-
#[cfg(all(feature = "luau", feature = "serialize"))]
use serde::ser::{Serialize, SerializeTupleStruct, Serializer};
@@ -43,21 +41,21 @@ pub(crate) enum SubtypeId {
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct LightUserData(pub *mut c_void);
-pub(crate) type Callback<'lua, 'a> = Box<dyn Fn(&'lua Lua, c_int) -> Result<c_int> + 'a>;
+pub(crate) type Callback<'a> = Box<dyn Fn(&'a LuaInner, c_int) -> Result<c_int> + 'static>;
pub(crate) struct Upvalue<T> {
pub(crate) data: T,
pub(crate) extra: Arc<UnsafeCell<ExtraData>>,
}
-pub(crate) type CallbackUpvalue = Upvalue<Callback<'static, 'static>>;
+pub(crate) type CallbackUpvalue = Upvalue<Callback<'static>>;
#[cfg(feature = "async")]
-pub(crate) type AsyncCallback<'lua, 'a> =
- Box<dyn Fn(&'lua Lua, MultiValue<'lua>) -> LocalBoxFuture<'lua, Result<c_int>> + 'a>;
+pub(crate) type AsyncCallback<'a> =
+ Box<dyn Fn(&'a LuaInner, MultiValue) -> LocalBoxFuture<'a, Result<c_int>> + 'static>;
#[cfg(feature = "async")]
-pub(crate) type AsyncCallbackUpvalue = Upvalue<AsyncCallback<'static, 'static>>;
+pub(crate) type AsyncCallbackUpvalue = Upvalue<AsyncCallback<'static>>;
#[cfg(feature = "async")]
pub(crate) type AsyncPollUpvalue = Upvalue<LocalBoxFuture<'static, Result<c_int>>>;
@@ -184,6 +182,9 @@ impl PartialEq<[f32; Self::SIZE]> for Vector {
}
}
+pub(crate) type ArcReentrantMutexGuard<T> =
+ parking_lot::lock_api::ArcReentrantMutexGuard<RawMutex, RawThreadId, T>;
+
pub(crate) struct DestructedUserdata;
/// An auto generated key into the Lua registry.
@@ -233,7 +234,7 @@ impl Drop for RegistryKey {
let registry_id = self.id();
// We don't need to collect nil slot
if registry_id > ffi::LUA_REFNIL {
- let mut unref_list = mlua_expect!(self.unref_list.lock(), "unref list poisoned");
+ let mut unref_list = self.unref_list.lock();
if let Some(list) = unref_list.as_mut() {
list.push(registry_id);
}
@@ -273,16 +274,16 @@ impl RegistryKey {
}
}
-pub(crate) struct ValueRef<'lua> {
- pub(crate) lua: &'lua Lua,
+pub(crate) struct ValueRef {
+ pub(crate) lua: WeakLua,
pub(crate) index: c_int,
pub(crate) drop: bool,
}
-impl<'lua> ValueRef<'lua> {
- pub(crate) const fn new(lua: &'lua Lua, index: c_int) -> Self {
+impl ValueRef {
+ pub(crate) fn new(lua: &LuaInner, index: c_int) -> Self {
ValueRef {
- lua,
+ lua: lua.weak().clone(),
index,
drop: true,
}
@@ -290,95 +291,39 @@ impl<'lua> ValueRef<'lua> {
#[inline]
pub(crate) fn to_pointer(&self) -> *const c_void {
- unsafe { ffi::lua_topointer(self.lua.ref_thread(), self.index) }
- }
-
- #[cfg(feature = "unstable")]
- #[inline]
- pub(crate) fn into_owned(self) -> OwnedValueRef {
- assert!(self.drop, "Cannot turn non-drop reference into owned");
- let owned_ref = OwnedValueRef::new(self.lua.clone(), self.index);
- mem::forget(self);
- owned_ref
+ let lua = self.lua.lock();
+ unsafe { ffi::lua_topointer(lua.ref_thread(), self.index) }
}
}
-impl<'lua> fmt::Debug for ValueRef<'lua> {
+impl fmt::Debug for ValueRef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Ref({:p})", self.to_pointer())
}
}
-impl<'lua> Clone for ValueRef<'lua> {
+impl Clone for ValueRef {
fn clone(&self) -> Self {
- self.lua.clone_ref(self)
+ self.lua.lock().clone_ref(self)
}
}
-impl<'lua> Drop for ValueRef<'lua> {
+impl Drop for ValueRef {
fn drop(&mut self) {
if self.drop {
- self.lua.drop_ref_index(self.index);
+ self.lua.lock().drop_ref(self);
}
}
}
-impl<'lua> PartialEq for ValueRef<'lua> {
+impl PartialEq for ValueRef {
fn eq(&self, other: &Self) -> bool {
- let ref_thread = self.lua.ref_thread();
assert!(
- ref_thread == other.lua.ref_thread(),
+ self.lua == other.lua,
"Lua instance passed Value created from a different main Lua state"
);
- unsafe { ffi::lua_rawequal(ref_thread, self.index, other.index) == 1 }
- }
-}
-
-#[cfg(feature = "unstable")]
-pub(crate) struct OwnedValueRef {
- pub(crate) inner: Arc<LuaInner>,
- pub(crate) index: c_int,
- _non_send: PhantomData<*const ()>,
-}
-
-#[cfg(feature = "unstable")]
-impl fmt::Debug for OwnedValueRef {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "OwnedRef({:p})", self.to_ref().to_pointer())
- }
-}
-
-#[cfg(feature = "unstable")]
-impl Clone for OwnedValueRef {
- fn clone(&self) -> Self {
- self.to_ref().clone().into_owned()
- }
-}
-
-#[cfg(feature = "unstable")]
-impl Drop for OwnedValueRef {
- fn drop(&mut self) {
- let lua: &Lua = unsafe { mem::transmute(&self.inner) };
- lua.drop_ref_index(self.index);
- }
-}
-
-#[cfg(feature = "unstable")]
-impl OwnedValueRef {
- pub(crate) const fn new(inner: Arc<LuaInner>, index: c_int) -> Self {
- OwnedValueRef {
- inner,
- index,
- _non_send: PhantomData,
- }
- }
-
- pub(crate) const fn to_ref(&self) -> ValueRef {
- ValueRef {
- lua: unsafe { mem::transmute(&self.inner) },
- index: self.index,
- drop: false,
- }
+ let lua = self.lua.lock();
+ unsafe { ffi::lua_rawequal(lua.ref_thread(), self.index, other.index) == 1 }
}
}
@@ -411,7 +356,7 @@ impl AppData {
}
#[track_caller]
- pub(crate) fn borrow<T: 'static>(&self) -> Option<AppDataRef<T>> {
+ pub(crate) fn borrow<T: 'static>(&self, guard: Option<LuaGuard>) -> Option<AppDataRef<T>> {
let data = unsafe { &*self.container.get() }
.get(&TypeId::of::<T>())?
.borrow();
@@ -419,11 +364,15 @@ impl AppData {
Some(AppDataRef {
data: Ref::filter_map(data, |data| data.downcast_ref()).ok()?,
borrow: &self.borrow,
+ _guard: guard,
})
}
#[track_caller]
- pub(crate) fn borrow_mut<T: 'static>(&self) -> Option<AppDataRefMut<T>> {
+ pub(crate) fn borrow_mut<T: 'static>(
+ &self,
+ guard: Option<LuaGuard>,
+ ) -> Option<AppDataRefMut<T>> {
let data = unsafe { &*self.container.get() }
.get(&TypeId::of::<T>())?
.borrow_mut();
@@ -431,6 +380,7 @@ impl AppData {
Some(AppDataRefMut {
data: RefMut::filter_map(data, |data| data.downcast_mut()).ok()?,
borrow: &self.borrow,
+ _guard: guard,
})
}
@@ -455,6 +405,7 @@ impl AppData {
pub struct AppDataRef<'a, T: ?Sized + 'a> {
data: Ref<'a, T>,
borrow: &'a Cell<usize>,
+ _guard: Option<LuaGuard>,
}
impl<T: ?Sized> Drop for AppDataRef<'_, T> {
@@ -490,6 +441,7 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for AppDataRef<'_, T> {
pub struct AppDataRefMut<'a, T: ?Sized + 'a> {
data: RefMut<'a, T>,
borrow: &'a Cell<usize>,
+ _guard: Option<LuaGuard>,
}
impl<T: ?Sized> Drop for AppDataRefMut<'_, T> {
@@ -526,13 +478,10 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for AppDataRefMut<'_, T> {
}
}
-#[cfg(test)]
-mod assertions {
- use super::*;
-
- static_assertions::assert_impl_all!(RegistryKey: Send, Sync);
- static_assertions::assert_not_impl_any!(ValueRef: Send);
+// #[cfg(test)]
+// mod assertions {
+// use super::*;
- #[cfg(feature = "unstable")]
- static_assertions::assert_not_impl_any!(OwnedValueRef: Send);
-}
+// static_assertions::assert_impl_all!(RegistryKey: Send, Sync);
+// static_assertions::assert_not_impl_any!(ValueRef: Send);
+// }
diff --git a/src/userdata.rs b/src/userdata.rs
index 408333b..b21000c 100644
--- a/src/userdata.rs
+++ b/src/userdata.rs
@@ -1,10 +1,7 @@
-use std::any::{type_name, TypeId};
-use std::cell::{Ref, RefCell, RefMut};
+use std::any::TypeId;
use std::ffi::CStr;
use std::fmt;
use std::hash::Hash;
-use std::mem;
-use std::ops::{Deref, DerefMut};
use std::os::raw::{c_char, c_int, c_void};
use std::string::String as StdString;
@@ -19,10 +16,11 @@ use {
use crate::error::{Error, Result};
use crate::function::Function;
-use crate::lua::Lua;
+use crate::lua::{Lua, LuaGuard};
use crate::string::String;
use crate::table::{Table, TablePairs};
use crate::types::{MaybeSend, SubtypeId, ValueRef};
+use crate::userdata_cell::{UserDataRef, UserDataRefMut, UserDataVariant};
use crate::util::{check_stack, get_userdata, take_userdata, StackGuard};
use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Value};
use crate::UserDataRegistry;
@@ -254,7 +252,7 @@ impl AsRef<str> for MetaMethod {
/// Method registry for [`UserData`] implementors.
///
/// [`UserData`]: crate::UserData
-pub trait UserDataMethods<'lua, T> {
+pub trait UserDataMethods<'a, T> {
/// Add a regular method which accepts a `&T` as the first parameter.
///
/// Regular methods are implemented by overriding the `__index` metamethod and returning the
@@ -262,10 +260,10 @@ pub trait UserDataMethods<'lua, T> {
///
/// If `add_meta_method` is used to set the `__index` metamethod, the `__index` metamethod will
/// be used as a fall-back if no regular method is found.
- fn add_method<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_method<M, A, R>(&mut self, name: impl ToString, method: M)
where
- M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ M: Fn(&'a Lua, &T, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti;
/// Add a regular method which accepts a `&mut T` as the first parameter.
@@ -273,10 +271,10 @@ pub trait UserDataMethods<'lua, T> {
/// Refer to [`add_method`] for more information about the implementation.
///
/// [`add_method`]: #method.add_method
- fn add_method_mut<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_method_mut<M, A, R>(&mut self, name: impl ToString, method: M)
where
- M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ M: FnMut(&'a Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti;
/// Add an async method which accepts a `&T` as the first parameter and returns Future.
@@ -288,13 +286,12 @@ pub trait UserDataMethods<'lua, T> {
/// [`add_method`]: #method.add_method
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- fn add_async_method<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_async_method<M, A, MR, R>(&mut self, name: impl ToString, method: M)
where
- 'lua: 's,
T: 'static,
- M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- MR: Future<Output = Result<R>> + 's,
+ M: Fn(&'a Lua, &'a T, A) -> MR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ MR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti;
/// Add an async method which accepts a `&mut T` as the first parameter and returns Future.
@@ -306,13 +303,12 @@ pub trait UserDataMethods<'lua, T> {
/// [`add_method`]: #method.add_method
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- fn add_async_method_mut<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_async_method_mut<M, A, MR, R>(&mut self, name: impl ToString, method: M)
where
- 'lua: 's,
T: 'static,
- M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- MR: Future<Output = Result<R>> + 's,
+ M: Fn(&'a Lua, &'a mut T, A) -> MR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ MR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti;
/// Add a regular method as a function which accepts generic arguments, the first argument will
@@ -325,10 +321,10 @@ pub trait UserDataMethods<'lua, T> {
/// [`AnyUserData`]: crate::AnyUserData
/// [`add_method`]: #method.add_method
/// [`add_method_mut`]: #method.add_method_mut
- fn add_function<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_function<F, A, R>(&mut self, name: impl ToString, function: F)
where
- F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ F: Fn(&'a Lua, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti;
/// Add a regular method as a mutable function which accepts generic arguments.
@@ -336,10 +332,10 @@ pub trait UserDataMethods<'lua, T> {
/// This is a version of [`add_function`] that accepts a FnMut argument.
///
/// [`add_function`]: #method.add_function
- fn add_function_mut<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_function_mut<F, A, R>(&mut self, name: impl ToString, function: F)
where
- F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ F: FnMut(&'a Lua, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti;
/// Add a regular method as an async function which accepts generic arguments
@@ -352,11 +348,11 @@ pub trait UserDataMethods<'lua, T> {
/// [`add_function`]: #method.add_function
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- fn add_async_function<F, A, FR, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_async_function<F, A, FR, R>(&mut self, name: impl ToString, function: F)
where
- F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- FR: Future<Output = Result<R>> + 'lua,
+ F: Fn(&'a Lua, A) -> FR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ FR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti;
/// Add a metamethod which accepts a `&T` as the first parameter.
@@ -367,10 +363,10 @@ pub trait UserDataMethods<'lua, T> {
/// side has a metatable. To prevent this, use [`add_meta_function`].
///
/// [`add_meta_function`]: #method.add_meta_function
- fn add_meta_method<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_meta_method<M, A, R>(&mut self, name: impl ToString, method: M)
where
- M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ M: Fn(&'a Lua, &T, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti;
/// Add a metamethod as a function which accepts a `&mut T` as the first parameter.
@@ -381,10 +377,10 @@ pub trait UserDataMethods<'lua, T> {
/// side has a metatable. To prevent this, use [`add_meta_function`].
///
/// [`add_meta_function`]: #method.add_meta_function
- fn add_meta_method_mut<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_meta_method_mut<M, A, R>(&mut self, name: impl ToString, method: M)
where
- M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ M: FnMut(&'a Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti;
/// Add an async metamethod which accepts a `&T` as the first parameter and returns Future.
@@ -396,13 +392,12 @@ pub trait UserDataMethods<'lua, T> {
/// [`add_meta_method`]: #method.add_meta_method
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- fn add_async_meta_method<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_async_meta_method<M, A, MR, R>(&mut self, name: impl ToString, method: M)
where
- 'lua: 's,
T: 'static,
- M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- MR: Future<Output = Result<R>> + 's,
+ M: Fn(&'a Lua, &'a T, A) -> MR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ MR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti;
/// Add an async metamethod which accepts a `&mut T` as the first parameter and returns Future.
@@ -414,13 +409,12 @@ pub trait UserDataMethods<'lua, T> {
/// [`add_meta_method_mut`]: #method.add_meta_method_mut
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- fn add_async_meta_method_mut<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_async_meta_method_mut<M, A, MR, R>(&mut self, name: impl ToString, method: M)
where
- 'lua: 's,
T: 'static,
- M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- MR: Future<Output = Result<R>> + 's,
+ M: Fn(&'a Lua, &'a mut T, A) -> MR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ MR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti;
/// Add a metamethod which accepts generic arguments.
@@ -428,10 +422,10 @@ pub trait UserDataMethods<'lua, T> {
/// Metamethods for binary operators can be triggered if either the left or right argument to
/// the binary operator has a metatable, so the first argument here is not necessarily a
/// userdata of type `T`.
- fn add_meta_function<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_meta_function<F, A, R>(&mut self, name: impl ToString, function: F)
where
- F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ F: Fn(&'a Lua, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti;
/// Add a metamethod as a mutable function which accepts generic arguments.
@@ -439,10 +433,10 @@ pub trait UserDataMethods<'lua, T> {
/// This is a version of [`add_meta_function`] that accepts a FnMut argument.
///
/// [`add_meta_function`]: #method.add_meta_function
- fn add_meta_function_mut<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_meta_function_mut<F, A, R>(&mut self, name: impl ToString, function: F)
where
- F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ F: FnMut(&'a Lua, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti;
/// Add a metamethod which accepts generic arguments and returns Future.
@@ -454,25 +448,18 @@ pub trait UserDataMethods<'lua, T> {
/// [`add_meta_function`]: #method.add_meta_function
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- fn add_async_meta_function<F, A, FR, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_async_meta_function<F, A, FR, R>(&mut self, name: impl ToString, function: F)
where
- F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- FR: Future<Output = Result<R>> + 'lua,
+ F: Fn(&'a Lua, A) -> FR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ FR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti;
-
- //
- // Below are internal methods used in generated code
- //
-
- #[doc(hidden)]
- fn append_methods_from<S>(&mut self, _other: UserDataRegistry<'lua, S>) {}
}
/// Field registry for [`UserData`] implementors.
///
/// [`UserData`]: crate::UserData
-pub trait UserDataFields<'lua, T> {
+pub trait UserDataFields<'a, T> {
/// Add a static field to the `UserData`.
///
/// Static fields are implemented by updating the `__index` metamethod and returning the
@@ -482,7 +469,7 @@ pub trait UserDataFields<'lua, T> {
///
/// If `add_meta_method` is used to set the `__index` metamethod, it will
/// be used as a fall-back if no regular field or method are found.
- fn add_field<V>(&mut self, name: impl AsRef<str>, value: V)
+ fn add_field<V>(&mut self, name: impl ToString, value: V)
where
V: IntoLua + Clone + 'static;
@@ -493,9 +480,9 @@ pub trait UserDataFields<'lua, T> {
///
/// If `add_meta_method` is used to set the `__index` metamethod, the `__index` metamethod will
/// be used as a fall-back if no regular field or method are found.
- fn add_field_method_get<M, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_field_method_get<M, R>(&mut self, name: impl ToString, method: M)
where
- M: Fn(&'lua Lua, &T) -> Result<R> + MaybeSend + 'static,
+ M: Fn(&'a Lua, &T) -> Result<R> + MaybeSend + 'static,
R: IntoLua;
/// Add a regular field setter as a method which accepts a `&mut T` as the first parameter.
@@ -505,10 +492,10 @@ pub trait UserDataFields<'lua, T> {
///
/// If `add_meta_method` is used to set the `__newindex` metamethod, the `__newindex` metamethod will
/// be used as a fall-back if no regular field is found.
- fn add_field_method_set<M, A>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_field_method_set<M, A>(&mut self, name: impl ToString, method: M)
where
- M: FnMut(&'lua Lua, &mut T, A) -> Result<()> + MaybeSend + 'static,
- A: FromLua<'lua>;
+ M: FnMut(&'a Lua, &mut T, A) -> Result<()> + MaybeSend + 'static,
+ A: FromLua;
/// Add a regular field getter as a function which accepts a generic [`AnyUserData`] of type `T`
/// argument.
@@ -517,9 +504,9 @@ pub trait UserDataFields<'lua, T> {
///
/// [`AnyUserData`]: crate::AnyUserData
/// [`add_field_method_get`]: #method.add_field_method_get
- fn add_field_function_get<F, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_field_function_get<F, R>(&mut self, name: impl ToString, function: F)
where
- F: Fn(&'lua Lua, AnyUserData<'lua>) -> Result<R> + MaybeSend + 'static,
+ F: Fn(&'a Lua, AnyUserData) -> Result<R> + MaybeSend + 'static,
R: IntoLua;
/// Add a regular field setter as a function which accepts a generic [`AnyUserData`] of type `T`
@@ -529,10 +516,10 @@ pub trait UserDataFields<'lua, T> {
///
/// [`AnyUserData`]: crate::AnyUserData
/// [`add_field_method_set`]: #method.add_field_method_set
- fn add_field_function_set<F, A>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_field_function_set<F, A>(&mut self, name: impl ToString, function: F)
where
- F: FnMut(&'lua Lua, AnyUserData<'lua>, A) -> Result<()> + MaybeSend + 'static,
- A: FromLua<'lua>;
+ F: FnMut(&'a Lua, AnyUserData, A) -> Result<()> + MaybeSend + 'static,
+ A: FromLua;
/// Add a metatable field.
///
@@ -542,7 +529,7 @@ pub trait UserDataFields<'lua, T> {
///
/// `mlua` will trigger an error on an attempt to define a protected metamethod,
/// like `__gc` or `__metatable`.
- fn add_meta_field<V>(&mut self, name: impl AsRef<str>, value: V)
+ fn add_meta_field<V>(&mut self, name: impl ToString, value: V)
where
V: IntoLua + Clone + 'static;
@@ -554,17 +541,10 @@ pub trait UserDataFields<'lua, T> {
///
/// `mlua` will trigger an error on an attempt to define a protected metamethod,
/// like `__gc` or `__metatable`.
- fn add_meta_field_with<F, R>(&mut self, name: impl AsRef<str>, f: F)
+ fn add_meta_field_with<F, R>(&mut self, name: impl ToString, f: F)
where
- F: Fn(&'lua Lua) -> Result<R> + MaybeSend + 'static,
+ F: Fn(&'a Lua) -> Result<R> + MaybeSend + 'static,
R: IntoLua;
-
- //
- // Below are internal methods used in generated code
- //
-
- #[doc(hidden)]
- fn append_fields_from<S>(&mut self, _other: UserDataRegistry<'lua, S>) {}
}
/// Trait for custom userdata types.
@@ -602,11 +582,11 @@ pub trait UserDataFields<'lua, T> {
/// struct MyUserData(i32);
///
/// impl UserData for MyUserData {
-/// fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
+/// fn add_fields<'a, F: UserDataFields<'a, Self>>(fields: &mut F) {
/// fields.add_field_method_get("val", |_, this| Ok(this.0));
/// }
///
-/// fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+/// fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
/// methods.add_method_mut("add", |_, this, value: i32| {
/// this.0 += value;
/// Ok(())
@@ -637,140 +617,19 @@ pub trait UserDataFields<'lua, T> {
pub trait UserData: Sized {
/// Adds custom fields specific to this userdata.
#[allow(unused_variables)]
- fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {}
+ fn add_fields<'a, F: UserDataFields<'a, Self>>(fields: &mut F) {}
/// Adds custom methods and operators specific to this userdata.
#[allow(unused_variables)]
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {}
-}
-
-// Wraps UserData in a way to always implement `serde::Serialize` trait.
-pub(crate) struct UserDataCell<T>(RefCell<UserDataVariant<T>>);
-
-impl<T> UserDataCell<T> {
- #[inline]
- pub(crate) fn new(data: T) -> Self {
- UserDataCell(RefCell::new(UserDataVariant::new(data)))
- }
-
- #[inline]
- pub(crate) fn new_ref(data: &T) -> Self {
- UserDataCell(RefCell::new(UserDataVariant::new_ref(data)))
- }
-
- #[inline]
- pub(crate) fn new_ref_mut(data: &mut T) -> Self {
- UserDataCell(RefCell::new(UserDataVariant::new_ref_mut(data)))
- }
-
- #[cfg(feature = "serialize")]
- #[inline]
- pub(crate) fn new_ser(data: T) -> Self
- where
- T: Serialize + 'static,
- {
- UserDataCell(RefCell::new(UserDataVariant::new_ser(data)))
- }
-
- // Immutably borrows the wrapped value.
- #[inline]
- pub(crate) fn try_borrow(&self) -> Result<Ref<T>> {
- self.0
- .try_borrow()
- .map(|r| Ref::map(r, |r| r.deref()))
- .map_err(|_| Error::UserDataBorrowError)
- }
-
- // Mutably borrows the wrapped value.
- #[inline]
- pub(crate) fn try_borrow_mut(&self) -> Result<RefMut<T>> {
- self.0
- .try_borrow_mut()
- .map_err(|_| Error::UserDataBorrowMutError)
- .and_then(|r| {
- RefMut::filter_map(r, |r| r.try_deref_mut().ok())
- .map_err(|_| Error::UserDataBorrowMutError)
- })
- }
-
- // Consumes this `UserDataCell`, returning the wrapped value.
- #[inline]
- fn into_inner(self) -> Result<T> {
- self.0.into_inner().into_inner()
- }
-}
-
-pub(crate) enum UserDataVariant<T> {
- Default(Box<T>),
- Ref(*const T),
- RefMut(*mut T),
- #[cfg(feature = "serialize")]
- Serializable(Box<dyn erased_serde::Serialize>),
-}
-
-impl<T> UserDataVariant<T> {
- #[inline]
- fn new(data: T) -> Self {
- UserDataVariant::Default(Box::new(data))
- }
-
- #[inline]
- fn new_ref(data: &T) -> Self {
- UserDataVariant::Ref(data)
- }
-
- #[inline]
- fn new_ref_mut(data: &mut T) -> Self {
- UserDataVariant::RefMut(data)
- }
-
- #[cfg(feature = "serialize")]
- #[inline]
- fn new_ser(data: T) -> Self
- where
- T: Serialize + 'static,
- {
- UserDataVariant::Serializable(Box::new(data))
- }
-
- #[inline]
- fn try_deref_mut(&mut self) -> Result<&mut T> {
- match self {
- Self::Default(data) => Ok(data.deref_mut()),
- Self::Ref(_) => Err(Error::UserDataBorrowMutError),
- Self::RefMut(data) => unsafe { Ok(&mut **data) },
- #[cfg(feature = "serialize")]
- Self::Serializable(data) => unsafe { Ok(&mut *(data.as_mut() as *mut _ as *mut T)) },
- }
- }
-
- #[inline]
- fn into_inner(self) -> Result<T> {
- match self {
- Self::Default(data) => Ok(*data),
- Self::Ref(_) | Self::RefMut(_) => Err(Error::UserDataTypeMismatch),
- #[cfg(feature = "serialize")]
- Self::Serializable(data) => unsafe {
- Ok(*Box::from_raw(Box::into_raw(data) as *mut T))
- },
- }
- }
-}
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {}
-impl<T> Deref for UserDataVariant<T> {
- type Target = T;
-
- #[inline]
- fn deref(&self) -> &Self::Target {
- match self {
- Self::Default(data) => data,
- Self::Ref(data) => unsafe { &**data },
- Self::RefMut(data) => unsafe { &**data },
- #[cfg(feature = "serialize")]
- Self::Serializable(data) => unsafe {
- &*(data.as_ref() as *const _ as *const Self::Target)
- },
- }
+ /// Registers this type for use in Lua.
+ ///
+ /// This method is responsible for calling `add_fields` and `add_methods` on the provided
+ /// [`UserDataRegistry`].
+ fn register(registry: &mut UserDataRegistry<Self>) {
+ Self::add_fields(registry);
+ Self::add_methods(registry);
}
}
@@ -791,31 +650,12 @@ impl<T> Deref for UserDataVariant<T> {
/// [`is`]: crate::AnyUserData::is
/// [`borrow`]: crate::AnyUserData::borrow
#[derive(Clone, Debug)]
-pub struct AnyUserData<'lua>(pub(crate) ValueRef<'lua>, pub(crate) SubtypeId);
+pub struct AnyUserData(pub(crate) ValueRef, pub(crate) SubtypeId);
-/// Owned handle to an internal Lua userdata.
-///
-/// The owned handle holds a *strong* reference to the current Lua instance.
-/// Be warned, if you place it into a Lua type (eg. [`UserData`] or a Rust callback), it is *very easy*
-/// to accidentally cause reference cycles that would prevent destroying Lua instance.
-#[cfg(feature = "unstable")]
-#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
-#[derive(Clone, Debug)]
-pub struct OwnedAnyUserData(pub(crate) crate::types::OwnedValueRef, pub(crate) SubtypeId);
-
-#[cfg(feature = "unstable")]
-impl OwnedAnyUserData {
- /// Get borrowed handle to the underlying Lua userdata.
- #[cfg_attr(feature = "send", allow(unused))]
- pub const fn to_ref(&self) -> AnyUserData {
- AnyUserData(self.0.to_ref(), self.1)
- }
-}
-
-impl<'lua> AnyUserData<'lua> {
+impl AnyUserData {
/// Checks whether the type of this userdata is `T`.
pub fn is<T: 'static>(&self) -> bool {
- self.inspect(|_: &UserDataCell<T>| Ok(())).is_ok()
+ self.inspect::<T, _, _>(|_, _| Ok(())).is_ok()
}
/// Borrow this userdata immutably if it is of type `T`.
@@ -825,8 +665,8 @@ impl<'lua> AnyUserData<'lua> {
/// Returns a `UserDataBorrowError` if the userdata is already mutably borrowed. Returns a
/// `UserDataTypeMismatch` if the userdata is not of type `T`.
#[inline]
- pub fn borrow<T: 'static>(&self) -> Result<Ref<T>> {
- self.inspect(|cell| cell.try_borrow())
+ pub fn borrow<T: 'static>(&self) -> Result<UserDataRef<T>> {
+ self.inspect(|variant, guard| variant.try_make_ref(guard))
}
/// Borrow this userdata mutably if it is of type `T`.
@@ -836,8 +676,8 @@ impl<'lua> AnyUserData<'lua> {
/// Returns a `UserDataBorrowMutError` if the userdata cannot be mutably borrowed.
/// Returns a `UserDataTypeMismatch` if the userdata is not of type `T`.
#[inline]
- pub fn borrow_mut<T: 'static>(&self) -> Result<RefMut<T>> {
- self.inspect(|cell| cell.try_borrow_mut())
+ pub fn borrow_mut<T: 'static>(&self) -> Result<UserDataRefMut<T>> {
+ self.inspect(|variant, guard| variant.try_make_mut_ref(guard))
}
/// Takes the value out of this userdata.
@@ -845,7 +685,7 @@ impl<'lua> AnyUserData<'lua> {
///
/// Keeps associated user values unchanged (they will be collected by Lua's GC).
pub fn take<T: 'static>(&self) -> Result<T> {
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -855,8 +695,8 @@ impl<'lua> AnyUserData<'lua> {
match type_id {
Some(type_id) if type_id == TypeId::of::<T>() => {
// Try to borrow userdata exclusively
- let _ = (*get_userdata::<UserDataCell<T>>(state, -1)).try_borrow_mut()?;
- take_userdata::<UserDataCell<T>>(state).into_inner()
+ let _ = (*get_userdata::<UserDataVariant<T>>(state, -1)).try_borrow_mut()?;
+ take_userdata::<UserDataVariant<T>>(state).into_inner()
}
_ => Err(Error::UserDataTypeMismatch),
}
@@ -883,13 +723,13 @@ impl<'lua> AnyUserData<'lua> {
/// [`set_user_value`]: #method.set_user_value
/// [`nth_user_value`]: #method.nth_user_value
#[inline]
- pub fn user_value<V: FromLua<'lua>>(&self) -> Result<V> {
+ pub fn user_value<V: FromLua>(&self) -> Result<V> {
self.nth_user_value(1)
}
#[doc(hidden)]
#[deprecated(since = "0.9.0", note = "please use `user_value` instead")]
- pub fn get_user_value<V: FromLua<'lua>>(&self) -> Result<V> {
+ pub fn get_user_value<V: FromLua>(&self) -> Result<V> {
self.nth_user_value(1)
}
@@ -908,7 +748,7 @@ impl<'lua> AnyUserData<'lua> {
return Err(Error::runtime("user value index out of bounds"));
}
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -956,12 +796,12 @@ impl<'lua> AnyUserData<'lua> {
/// For other Lua versions this functionality is provided using a wrapping table.
///
/// [`set_nth_user_value`]: #method.set_nth_user_value
- pub fn nth_user_value<V: FromLua<'lua>>(&self, n: usize) -> Result<V> {
+ pub fn nth_user_value<V: FromLua>(&self, n: usize) -> Result<V> {
if n < 1 || n > u16::MAX as usize {
return Err(Error::runtime("user value index out of bounds"));
}
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -972,7 +812,7 @@ impl<'lua> AnyUserData<'lua> {
#[cfg(feature = "lua54")]
if n < USER_VALUE_MAXSLOT {
ffi::lua_getiuservalue(state, -1, n as c_int);
- return V::from_lua(lua.pop_value(), lua);
+ return V::from_lua(lua.pop_value(), lua.lua());
}
// Multiple (extra) user values are emulated by storing them in a table
@@ -987,13 +827,13 @@ impl<'lua> AnyUserData<'lua> {
ffi::lua_rawgeti(state, -1, n as ffi::lua_Integer);
})?;
- V::from_lua(lua.pop_value(), lua)
+ V::from_lua(lua.pop_value(), lua.lua())
}
}
#[doc(hidden)]
#[deprecated(since = "0.9.0", note = "please use `nth_user_value` instead")]
- pub fn get_nth_user_value<V: FromLua<'lua>>(&self, n: usize) -> Result<V> {
+ pub fn get_nth_user_value<V: FromLua>(&self, n: usize) -> Result<V> {
self.nth_user_value(n)
}
@@ -1003,7 +843,7 @@ impl<'lua> AnyUserData<'lua> {
///
/// [`named_user_value`]: #method.named_user_value
pub fn set_named_user_value<V: IntoLua>(&self, name: &str, v: V) -> Result<()> {
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -1037,8 +877,8 @@ impl<'lua> AnyUserData<'lua> {
/// Returns an associated value by name set by [`set_named_user_value`].
///
/// [`set_named_user_value`]: #method.set_named_user_value
- pub fn named_user_value<V: FromLua<'lua>>(&self, name: &str) -> Result<V> {
- let lua = self.0.lua;
+ pub fn named_user_value<V: FromLua>(&self, name: &str) -> Result<V> {
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -1056,13 +896,13 @@ impl<'lua> AnyUserData<'lua> {
ffi::lua_rawget(state, -2);
})?;
- V::from_lua(lua.pop_value(), lua)
+ V::from_lua(lua.pop_value(), lua.lua())
}
}
#[doc(hidden)]
#[deprecated(since = "0.9.0", note = "please use `named_user_value` instead")]
- pub fn get_named_user_value<V: FromLua<'lua>>(&self, name: &str) -> Result<V> {
+ pub fn get_named_user_value<V: FromLua>(&self, name: &str) -> Result<V> {
self.named_user_value(name)
}
@@ -1075,12 +915,12 @@ impl<'lua> AnyUserData<'lua> {
///
/// [`UserDataMetatable`]: crate::UserDataMetatable
#[inline]
- pub fn get_metatable(&self) -> Result<UserDataMetatable<'lua>> {
+ pub fn get_metatable(&self) -> Result<UserDataMetatable> {
self.get_raw_metatable().map(UserDataMetatable)
}
- fn get_raw_metatable(&self) -> Result<Table<'lua>> {
- let lua = self.0.lua;
+ fn get_raw_metatable(&self) -> Result<Table> {
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -1102,18 +942,11 @@ impl<'lua> AnyUserData<'lua> {
self.0.to_pointer()
}
- /// Convert this handle to owned version.
- #[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
- #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", not(feature = "send")))))]
- #[inline]
- pub fn into_owned(self) -> OwnedAnyUserData {
- OwnedAnyUserData(self.0.into_owned(), self.1)
- }
-
#[cfg(feature = "async")]
#[inline]
pub(crate) fn type_id(&self) -> Result<Option<TypeId>> {
- unsafe { self.0.lua.get_userdata_ref_type_id(&self.0) }
+ let lua = self.0.lua.lock();
+ unsafe { lua.get_userdata_ref_type_id(&self.0) }
}
/// Returns a type name of this `UserData` (from a metatable field).
@@ -1126,7 +959,7 @@ impl<'lua> AnyUserData<'lua> {
SubtypeId::CData => return Ok(Some("cdata".to_owned())),
}
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let state = lua.state();
unsafe {
let _sg = StackGuard::new(state);
@@ -1170,32 +1003,33 @@ impl<'lua> AnyUserData<'lua> {
/// Returns `true` if this `AnyUserData` is serializable (eg. was created using `create_ser_userdata`).
#[cfg(feature = "serialize")]
pub(crate) fn is_serializable(&self) -> bool {
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
let is_serializable = || unsafe {
- // Userdata can be unregistered or destructed
+ // Userdata must be registered and not destructed
let _ = lua.get_userdata_ref_type_id(&self.0)?;
- let ud = &*get_userdata::<UserDataCell<()>>(lua.ref_thread(), self.0.index);
- match &*ud.0.try_borrow().map_err(|_| Error::UserDataBorrowError)? {
- UserDataVariant::Serializable(_) => Result::Ok(true),
+ let ud = &*get_userdata::<UserDataVariant<()>>(lua.ref_thread(), self.0.index);
+ match ud {
+ UserDataVariant::Serializable(..) => Result::Ok(true),
_ => Result::Ok(false),
}
};
is_serializable().unwrap_or(false)
}
- fn inspect<'a, T, F, R>(&'a self, func: F) -> Result<R>
+ pub(crate) fn inspect<'a, T, F, R>(&'a self, func: F) -> Result<R>
where
T: 'static,
- F: FnOnce(&'a UserDataCell<T>) -> Result<R>,
+ F: FnOnce(&'a UserDataVariant<T>, LuaGuard) -> Result<R>,
{
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
unsafe {
let type_id = lua.get_userdata_ref_type_id(&self.0)?;
match type_id {
Some(type_id) if type_id == TypeId::of::<T>() => {
let ref_thread = lua.ref_thread();
- func(&*get_userdata::<UserDataCell<T>>(ref_thread, self.0.index))
+ let ud = get_userdata::<UserDataVariant<T>>(ref_thread, self.0.index);
+ func(&*ud, lua)
}
_ => Err(Error::UserDataTypeMismatch),
}
@@ -1203,13 +1037,13 @@ impl<'lua> AnyUserData<'lua> {
}
}
-impl<'lua> PartialEq for AnyUserData<'lua> {
+impl PartialEq for AnyUserData {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
-impl<'lua> AsRef<AnyUserData<'lua>> for AnyUserData<'lua> {
+impl AsRef<AnyUserData> for AnyUserData {
#[inline]
fn as_ref(&self) -> &Self {
self
@@ -1223,50 +1057,16 @@ unsafe fn getuservalue_table(state: *mut ffi::lua_State, idx: c_int) -> c_int {
return ffi::lua_getuservalue(state, idx);
}
-// Additional shortcuts
-#[cfg(feature = "unstable")]
-impl OwnedAnyUserData {
- /// Borrow this userdata immutably if it is of type `T`.
- ///
- /// This is a shortcut for [`AnyUserData::borrow()`]
- #[inline]
- pub fn borrow<T: 'static>(&self) -> Result<Ref<T>> {
- let ud = self.to_ref();
- let t = ud.borrow::<T>()?;
- // Reattach lifetime to &self
- Ok(unsafe { mem::transmute::<Ref<T>, Ref<T>>(t) })
- }
-
- /// Borrow this userdata mutably if it is of type `T`.
- ///
- /// This is a shortcut for [`AnyUserData::borrow_mut()`]
- #[inline]
- pub fn borrow_mut<T: 'static>(&self) -> Result<RefMut<T>> {
- let ud = self.to_ref();
- let t = ud.borrow_mut::<T>()?;
- // Reattach lifetime to &self
- Ok(unsafe { mem::transmute::<RefMut<T>, RefMut<T>>(t) })
- }
-
- /// Takes the value out of this userdata.
- ///
- /// This is a shortcut for [`AnyUserData::take()`]
- #[inline]
- pub fn take<T: 'static>(&self) -> Result<T> {
- self.to_ref().take()
- }
-}
-
/// Handle to a `UserData` metatable.
#[derive(Clone, Debug)]
-pub struct UserDataMetatable<'lua>(pub(crate) Table<'lua>);
+pub struct UserDataMetatable(pub(crate) Table);
-impl<'lua> UserDataMetatable<'lua> {
+impl UserDataMetatable {
/// Gets the value associated to `key` from the metatable.
///
/// If no value is associated to `key`, returns the `Nil` value.
/// Access to restricted metamethods such as `__gc` or `__metatable` will cause an error.
- pub fn get<V: FromLua<'lua>>(&self, key: impl AsRef<str>) -> Result<V> {
+ pub fn get<V: FromLua>(&self, key: impl AsRef<str>) -> Result<V> {
self.0.raw_get(MetaMethod::validate(key.as_ref())?)
}
@@ -1295,7 +1095,7 @@ impl<'lua> UserDataMetatable<'lua> {
/// The pairs are wrapped in a [`Result`], since they are lazily converted to `V` type.
///
/// [`Result`]: crate::Result
- pub fn pairs<V: FromLua<'lua>>(self) -> UserDataMetatablePairs<'lua, V> {
+ pub fn pairs<V: FromLua>(self) -> UserDataMetatablePairs<V> {
UserDataMetatablePairs(self.0.pairs())
}
}
@@ -1308,11 +1108,11 @@ impl<'lua> UserDataMetatable<'lua> {
///
/// [`UserData`]: crate::UserData
/// [`UserDataMetatable::pairs`]: crate::UserDataMetatable::method.pairs
-pub struct UserDataMetatablePairs<'lua, V>(TablePairs<'lua, StdString, V>);
+pub struct UserDataMetatablePairs<V>(TablePairs<StdString, V>);
-impl<'lua, V> Iterator for UserDataMetatablePairs<'lua, V>
+impl<V> Iterator for UserDataMetatablePairs<V>
where
- V: FromLua<'lua>,
+ V: FromLua,
{
type Item = Result<(StdString, V)>;
@@ -1332,12 +1132,12 @@ where
}
#[cfg(feature = "serialize")]
-impl<'lua> Serialize for AnyUserData<'lua> {
+impl Serialize for AnyUserData {
fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
where
S: Serializer,
{
- let lua = self.0.lua;
+ let lua = self.0.lua.lock();
// Special case for Luau buffer type
#[cfg(feature = "luau")]
@@ -1351,74 +1151,19 @@ impl<'lua> Serialize for AnyUserData<'lua> {
return serializer.serialize_bytes(buf);
}
- let data = unsafe {
+ unsafe {
let _ = lua
.get_userdata_ref_type_id(&self.0)
.map_err(ser::Error::custom)?;
- let ud = &*get_userdata::<UserDataCell<()>>(lua.ref_thread(), self.0.index);
- ud.0.try_borrow()
- .map_err(|_| ser::Error::custom(Error::UserDataBorrowError))?
- };
- match &*data {
- UserDataVariant::Serializable(ser) => ser.serialize(serializer),
- _ => Err(ser::Error::custom("cannot serialize <userdata>")),
+ let ud = &*get_userdata::<UserDataVariant<()>>(lua.ref_thread(), self.0.index);
+ ud.serialize(serializer)
}
}
}
-/// A wrapper type for an immutably borrowed value from a `AnyUserData`.
-///
-/// It implements [`FromLua`] and can be used to receive a typed userdata from Lua.
-pub struct UserDataRef<'lua, T: 'static>(#[allow(unused)] AnyUserData<'lua>, Ref<'lua, T>);
-
-impl<'lua, T: 'static> Deref for UserDataRef<'lua, T> {
- type Target = T;
-
- fn deref(&self) -> &Self::Target {
- &self.1
- }
-}
-
-impl<'lua, T: 'static> UserDataRef<'lua, T> {
- pub(crate) fn from_value(value: Value<'lua>) -> Result<Self> {
- let ud = try_value_to_userdata::<T>(value)?;
- // It's safe to lift lifetime of `Ref<T>` to `'lua` as long as we hold AnyUserData to it.
- let this = unsafe { mem::transmute(ud.borrow::<T>()?) };
- Ok(UserDataRef(ud, this))
- }
-}
-
-/// A wrapper type for a mutably borrowed value from a `AnyUserData`.
-///
-/// It implements [`FromLua`] and can be used to receive a typed userdata from Lua.
-pub struct UserDataRefMut<'lua, T: 'static>(#[allow(unused)] AnyUserData<'lua>, RefMut<'lua, T>);
-
-impl<'lua, T: 'static> Deref for UserDataRefMut<'lua, T> {
- type Target = T;
-
- fn deref(&self) -> &Self::Target {
- &self.1
- }
-}
-
-impl<'lua, T: 'static> DerefMut for UserDataRefMut<'lua, T> {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.1
- }
-}
+pub(crate) struct WrappedUserdata<F: FnOnce(&Lua) -> Result<AnyUserData>>(F);
-impl<'lua, T: 'static> UserDataRefMut<'lua, T> {
- pub(crate) fn from_value(value: Value<'lua>) -> Result<Self> {
- let ud = try_value_to_userdata::<T>(value)?;
- // It's safe to lift lifetime of `RefMut<T>` to `'lua` as long as we hold AnyUserData to it.
- let this = unsafe { mem::transmute(ud.borrow_mut::<T>()?) };
- Ok(UserDataRefMut(ud, this))
- }
-}
-
-pub(crate) struct WrappedUserdata<F: for<'lua> FnOnce(&'lua Lua) -> Result<AnyUserData<'lua>>>(F);
-
-impl<'lua> AnyUserData<'lua> {
+impl AnyUserData {
/// Wraps any Rust type, returning an opaque type that implements [`IntoLua`] trait.
///
/// This function uses [`Lua::create_any_userdata()`] under the hood.
@@ -1429,31 +1174,16 @@ impl<'lua> AnyUserData<'lua> {
impl<F> IntoLua for WrappedUserdata<F>
where
- F: for<'l> FnOnce(&'l Lua) -> Result<AnyUserData<'l>>,
+ F: for<'l> FnOnce(&'l Lua) -> Result<AnyUserData>,
{
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>> {
+ fn into_lua(self, lua: &Lua) -> Result<Value> {
(self.0)(lua).map(Value::UserData)
}
}
-#[inline]
-fn try_value_to_userdata<T>(value: Value) -> Result<AnyUserData> {
- match value {
- Value::UserData(ud) => Ok(ud),
- _ => Err(Error::FromLuaConversionError {
- from: value.type_name(),
- to: "userdata",
- message: Some(format!("expected userdata of type {}", type_name::<T>())),
- }),
- }
-}
+// #[cfg(test)]
+// mod assertions {
+// use super::*;
-#[cfg(test)]
-mod assertions {
- use super::*;
-
- static_assertions::assert_not_impl_any!(AnyUserData: Send);
-
- #[cfg(all(feature = "unstable", not(feature = "send")))]
- static_assertions::assert_not_impl_any!(OwnedAnyUserData: Send);
-}
+// static_assertions::assert_not_impl_any!(AnyUserData: Send);
+// }
diff --git a/src/userdata_cell.rs b/src/userdata_cell.rs
new file mode 100644
index 0000000..59b4503
--- /dev/null
+++ b/src/userdata_cell.rs
@@ -0,0 +1,410 @@
+use std::any::{type_name, TypeId};
+use std::cell::{Cell, UnsafeCell};
+use std::fmt;
+use std::ops::{Deref, DerefMut};
+use std::os::raw::c_int;
+use std::rc::Rc;
+
+#[cfg(feature = "serialize")]
+use serde::ser::{Serialize, Serializer};
+
+use crate::error::{Error, Result};
+use crate::lua::{Lua, LuaGuard, LuaInner};
+use crate::userdata::AnyUserData;
+use crate::util::get_userdata;
+use crate::value::{FromLua, Value};
+
+// A enum for storing userdata values.
+// It's stored inside a Lua VM and protected by the outer `ReentrantMutex`.
+pub(crate) enum UserDataVariant<T> {
+ Default(Rc<InnerRefCell<T>>),
+ #[cfg(feature = "serialize")]
+ Serializable(Rc<InnerRefCell<Box<dyn erased_serde::Serialize>>>),
+}
+
+impl<T> Clone for UserDataVariant<T> {
+ #[inline]
+ fn clone(&self) -> Self {
+ match self {
+ Self::Default(inner) => Self::Default(Rc::clone(inner)),
+ #[cfg(feature = "serialize")]
+ Self::Serializable(inner) => UserDataVariant::Serializable(Rc::clone(inner)),
+ }
+ }
+}
+
+impl<T> UserDataVariant<T> {
+ #[inline(always)]
+ pub(crate) fn new(data: T) -> Self {
+ Self::Default(Rc::new(InnerRefCell::new(data)))
+ }
+
+ // Immutably borrows the wrapped value in-place.
+ #[inline(always)]
+ pub(crate) unsafe fn try_borrow(&self) -> Result<UserDataBorrowRef<T>> {
+ UserDataBorrowRef::try_from(self)
+ }
+
+ // Immutably borrows the wrapped value and returns an owned reference.
+ #[inline(always)]
+ pub(crate) fn try_make_ref(&self, guard: LuaGuard) -> Result<UserDataRef<T>> {
+ UserDataRef::try_from(self.clone(), guard)
+ }
+
+ // Mutably borrows the wrapped value in-place.
+ #[inline(always)]
+ pub(crate) unsafe fn try_borrow_mut(&self) -> Result<UserDataBorrowMut<T>> {
+ UserDataBorrowMut::try_from(self)
+ }
+
+ // Mutably borrows the wrapped value and returns an owned reference.
+ #[inline(always)]
+ pub(crate) fn try_make_mut_ref(&self, guard: LuaGuard) -> Result<UserDataRefMut<T>> {
+ UserDataRefMut::try_from(self.clone(), guard)
+ }
+
+ // Returns the wrapped value.
+ //
+ // This method checks that we have exclusive access to the value.
+ pub(crate) fn into_inner(self) -> Result<T> {
+ set_writing(self.flag())?;
+ Ok(match self {
+ Self::Default(inner) => Rc::into_inner(inner).unwrap().value.into_inner(),
+ #[cfg(feature = "serialize")]
+ Self::Serializable(inner) => unsafe {
+ let raw = Box::into_raw(Rc::into_inner(inner).unwrap().value.into_inner());
+ *Box::from_raw(raw as *mut T)
+ },
+ })
+ }
+
+ #[inline(always)]
+ fn flag(&self) -> &Cell<BorrowFlag> {
+ match self {
+ Self::Default(inner) => &inner.borrow,
+ #[cfg(feature = "serialize")]
+ Self::Serializable(inner) => &inner.borrow,
+ }
+ }
+
+ #[inline(always)]
+ unsafe fn get_ref(&self) -> &T {
+ match self {
+ Self::Default(inner) => &*inner.value.get(),
+ #[cfg(feature = "serialize")]
+ Self::Serializable(inner) => &*(inner.value.get() as *mut Box<T>),
+ }
+ }
+
+ #[inline(always)]
+ unsafe fn get_mut(&self) -> &mut T {
+ match self {
+ Self::Default(inner) => &mut *inner.value.get(),
+ #[cfg(feature = "serialize")]
+ Self::Serializable(inner) => &mut *(inner.value.get() as *mut Box<T>),
+ }
+ }
+}
+
+#[cfg(feature = "serialize")]
+impl<T: Serialize + 'static> UserDataVariant<T> {
+ #[inline(always)]
+ pub(crate) fn new_ser(data: T) -> Self {
+ let data = Box::new(data) as Box<dyn erased_serde::Serialize>;
+ Self::Serializable(Rc::new(InnerRefCell::new(data)))
+ }
+}
+
+#[cfg(feature = "serialize")]
+impl Serialize for UserDataVariant<()> {
+ fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
+ match self {
+ UserDataVariant::Default(_) => {
+ Err(serde::ser::Error::custom("cannot serialize <userdata>"))
+ }
+ UserDataVariant::Serializable(inner) => unsafe {
+ let _ = self.try_borrow().map_err(serde::ser::Error::custom)?;
+ (*inner.value.get()).serialize(serializer)
+ },
+ }
+ }
+}
+
+//
+// Inspired by `std::cell::RefCell`` implementation
+//
+
+pub(crate) struct InnerRefCell<T> {
+ borrow: Cell<BorrowFlag>,
+ value: UnsafeCell<T>,
+}
+
+impl<T> InnerRefCell<T> {
+ #[inline(always)]
+ pub fn new(value: T) -> Self {
+ InnerRefCell {
+ borrow: Cell::new(UNUSED),
+ value: UnsafeCell::new(value),
+ }
+ }
+}
+
+/// A wrapper type for a [`UserData`] value that provides read access.
+///
+/// It implements [`FromLua`] and can be used to receive a typed userdata from Lua.
+pub struct UserDataRef<T> {
+ variant: UserDataVariant<T>,
+ #[allow(unused)]
+ guard: LuaGuard,
+}
+
+impl<T> Deref for UserDataRef<T> {
+ type Target = T;
+
+ #[inline]
+ fn deref(&self) -> &T {
+ unsafe { self.variant.get_ref() }
+ }
+}
+
+impl<T> Drop for UserDataRef<T> {
+ #[inline]
+ fn drop(&mut self) {
+ unset_reading(self.variant.flag());
+ }
+}
+
+impl<T: fmt::Debug> fmt::Debug for UserDataRef<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ (**self).fmt(f)
+ }
+}
+
+impl<T: fmt::Display> fmt::Display for UserDataRef<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ (**self).fmt(f)
+ }
+}
+
+impl<T> UserDataRef<T> {
+ #[inline]
+ fn try_from(variant: UserDataVariant<T>, guard: LuaGuard) -> Result<Self> {
+ set_reading(variant.flag())?;
+ Ok(UserDataRef { variant, guard })
+ }
+}
+
+impl<T: 'static> FromLua for UserDataRef<T> {
+ fn from_lua(value: Value, _: &Lua) -> Result<Self> {
+ try_value_to_userdata::<T>(value)?.borrow()
+ }
+
+ unsafe fn from_stack(idx: c_int, lua: &LuaInner) -> Result<Self> {
+ let type_id = lua.get_userdata_type_id(idx)?;
+ match type_id {
+ Some(type_id) if type_id == TypeId::of::<T>() => lua.get_userdata_ref(idx),
+ _ => Err(Error::UserDataTypeMismatch),
+ }
+ }
+}
+
+/// A wrapper type for a mutably borrowed value from a `AnyUserData`.
+///
+/// It implements [`FromLua`] and can be used to receive a typed userdata from Lua.
+pub struct UserDataRefMut<T> {
+ variant: UserDataVariant<T>,
+ #[allow(unused)]
+ guard: LuaGuard,
+}
+
+impl<T> Deref for UserDataRefMut<T> {
+ type Target = T;
+
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ unsafe { self.variant.get_ref() }
+ }
+}
+
+impl<T> DerefMut for UserDataRefMut<T> {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ unsafe { self.variant.get_mut() }
+ }
+}
+
+impl<T> Drop for UserDataRefMut<T> {
+ #[inline]
+ fn drop(&mut self) {
+ unset_writing(self.variant.flag());
+ }
+}
+
+impl<T: fmt::Debug> fmt::Debug for UserDataRefMut<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ (**self).fmt(f)
+ }
+}
+
+impl<T: fmt::Display> fmt::Display for UserDataRefMut<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ (**self).fmt(f)
+ }
+}
+
+impl<T> UserDataRefMut<T> {
+ fn try_from(variant: UserDataVariant<T>, guard: LuaGuard) -> Result<Self> {
+ // There must currently be no existing references
+ set_writing(variant.flag())?;
+ Ok(UserDataRefMut { variant, guard })
+ }
+}
+
+impl<T: 'static> FromLua for UserDataRefMut<T> {
+ fn from_lua(value: Value, _: &Lua) -> Result<Self> {
+ try_value_to_userdata::<T>(value)?.borrow_mut()
+ }
+
+ unsafe fn from_stack(idx: c_int, lua: &LuaInner) -> Result<Self> {
+ let type_id = lua.get_userdata_type_id(idx)?;
+ match type_id {
+ Some(type_id) if type_id == TypeId::of::<T>() => {
+ let guard = lua.lua().lock_arc();
+ (*get_userdata::<UserDataVariant<T>>(lua.state(), idx)).try_make_mut_ref(guard)
+ }
+ _ => Err(Error::UserDataTypeMismatch),
+ }
+ }
+}
+
+// Positive values represent the number of `Ref` active. Negative values
+// represent the number of `RefMut` active. Multiple `RefMut`s can only be
+// active at a time if they refer to distinct, nonoverlapping components of a
+// `RefCell` (e.g., different ranges of a slice).
+type BorrowFlag = isize;
+const UNUSED: BorrowFlag = 0;
+
+#[inline(always)]
+fn is_writing(x: BorrowFlag) -> bool {
+ x < UNUSED
+}
+
+#[inline(always)]
+fn is_reading(x: BorrowFlag) -> bool {
+ x > UNUSED
+}
+
+#[inline(always)]
+fn set_writing(borrow: &Cell<BorrowFlag>) -> Result<()> {
+ let flag = borrow.get();
+ if flag != UNUSED {
+ return Err(Error::UserDataBorrowMutError);
+ }
+ borrow.set(UNUSED - 1);
+ Ok(())
+}
+
+#[inline(always)]
+fn set_reading(borrow: &Cell<BorrowFlag>) -> Result<()> {
+ let flag = borrow.get().wrapping_add(1);
+ if !is_reading(flag) {
+ return Err(Error::UserDataBorrowError);
+ }
+ borrow.set(flag);
+ Ok(())
+}
+
+#[inline(always)]
+#[track_caller]
+fn unset_writing(borrow: &Cell<BorrowFlag>) {
+ let flag = borrow.get();
+ debug_assert!(is_writing(flag));
+ borrow.set(flag + 1);
+}
+
+#[inline(always)]
+#[track_caller]
+fn unset_reading(borrow: &Cell<BorrowFlag>) {
+ let flag = borrow.get();
+ debug_assert!(is_reading(flag));
+ borrow.set(flag - 1);
+}
+
+pub(crate) struct UserDataBorrowRef<'a, T>(&'a UserDataVariant<T>);
+
+impl<'a, T> Drop for UserDataBorrowRef<'a, T> {
+ #[inline]
+ fn drop(&mut self) {
+ unset_reading(self.0.flag());
+ }
+}
+
+impl<'a, T> Deref for UserDataBorrowRef<'a, T> {
+ type Target = T;
+
+ #[inline]
+ fn deref(&self) -> &T {
+ unsafe { self.0.get_ref() }
+ }
+}
+
+impl<'a, T> UserDataBorrowRef<'a, T> {
+ #[inline(always)]
+ pub(crate) fn try_from(variant: &'a UserDataVariant<T>) -> Result<Self> {
+ set_reading(variant.flag())?;
+ Ok(UserDataBorrowRef(&variant))
+ }
+}
+
+pub(crate) struct UserDataBorrowMut<'a, T>(&'a UserDataVariant<T>);
+
+impl<'a, T> Drop for UserDataBorrowMut<'a, T> {
+ #[inline]
+ fn drop(&mut self) {
+ unset_writing(self.0.flag());
+ }
+}
+
+impl<'a, T> Deref for UserDataBorrowMut<'a, T> {
+ type Target = T;
+
+ #[inline]
+ fn deref(&self) -> &T {
+ unsafe { self.0.get_ref() }
+ }
+}
+
+impl<'a, T> DerefMut for UserDataBorrowMut<'a, T> {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut T {
+ unsafe { self.0.get_mut() }
+ }
+}
+
+impl<'a, T> UserDataBorrowMut<'a, T> {
+ #[inline(always)]
+ pub(crate) fn try_from(variant: &'a UserDataVariant<T>) -> Result<Self> {
+ set_writing(variant.flag())?;
+ Ok(UserDataBorrowMut(&variant))
+ }
+}
+
+#[inline]
+fn try_value_to_userdata<T>(value: Value) -> Result<AnyUserData> {
+ match value {
+ Value::UserData(ud) => Ok(ud),
+ _ => Err(Error::FromLuaConversionError {
+ from: value.type_name(),
+ to: "userdata",
+ message: Some(format!("expected userdata of type {}", type_name::<T>())),
+ }),
+ }
+}
+
+#[cfg(test)]
+mod assertions {
+ use super::*;
+
+ static_assertions::assert_not_impl_all!(UserDataRef<()>: Sync, Send);
+ static_assertions::assert_not_impl_all!(UserDataRefMut<()>: Sync, Send);
+}
diff --git a/src/userdata_ext.rs b/src/userdata_ext.rs
index 268324d..0863d9b 100644
--- a/src/userdata_ext.rs
+++ b/src/userdata_ext.rs
@@ -7,9 +7,9 @@ use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Value};
use futures_util::future::{self, LocalBoxFuture};
/// An extension trait for [`AnyUserData`] that provides a variety of convenient functionality.
-pub trait AnyUserDataExt<'lua>: Sealed {
+pub trait AnyUserDataExt: Sealed {
/// Gets the value associated to `key` from the userdata, assuming it has `__index` metamethod.
- fn get<K: IntoLua, V: FromLua<'lua>>(&self, key: K) -> Result<V>;
+ fn get<K: IntoLua, V: FromLua>(&self, key: K) -> Result<V>;
/// Sets the value associated to `key` in the userdata, assuming it has `__newindex` metamethod.
fn set<K: IntoLua, V: IntoLua>(&self, key: K, value: V) -> Result<()>;
@@ -20,24 +20,24 @@ pub trait AnyUserDataExt<'lua>: Sealed {
fn call<A, R>(&self, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>;
+ R: FromLuaMulti;
/// Asynchronously calls the userdata as a function assuming it has `__call` metamethod.
///
/// The metamethod is called with the userdata as its first argument, followed by the passed arguments.
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- fn call_async<A, R>(&self, args: A) -> LocalBoxFuture<'lua, Result<R>>
+ fn call_async<A, R>(&self, args: A) -> LocalBoxFuture<'static, Result<R>>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua;
+ R: FromLuaMulti + 'static;
/// Calls the userdata method, assuming it has `__index` metamethod
/// and a function associated to `name`.
fn call_method<A, R>(&self, name: &str, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>;
+ R: FromLuaMulti;
/// Gets the function associated to `key` from the table and asynchronously executes it,
/// passing the table itself along with `args` as function arguments and returning Future.
@@ -47,10 +47,10 @@ pub trait AnyUserDataExt<'lua>: Sealed {
/// This might invoke the `__index` metamethod.
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- fn call_async_method<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'lua, Result<R>>
+ fn call_async_method<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'static, Result<R>>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua;
+ R: FromLuaMulti + 'static;
/// Gets the function associated to `key` from the table and executes it,
/// passing `args` as function arguments.
@@ -62,7 +62,7 @@ pub trait AnyUserDataExt<'lua>: Sealed {
fn call_function<A, R>(&self, name: &str, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>;
+ R: FromLuaMulti;
/// Gets the function associated to `key` from the table and asynchronously executes it,
/// passing `args` as function arguments and returning Future.
@@ -72,14 +72,14 @@ pub trait AnyUserDataExt<'lua>: Sealed {
/// This might invoke the `__index` metamethod.
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
- fn call_async_function<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'lua, Result<R>>
+ fn call_async_function<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'static, Result<R>>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua;
+ R: FromLuaMulti + 'static;
}
-impl<'lua> AnyUserDataExt<'lua> for AnyUserData<'lua> {
- fn get<K: IntoLua, V: FromLua<'lua>>(&self, key: K) -> Result<V> {
+impl AnyUserDataExt for AnyUserData {
+ fn get<K: IntoLua, V: FromLua>(&self, key: K) -> Result<V> {
let metatable = self.get_metatable()?;
match metatable.get::<Value>(MetaMethod::Index)? {
Value::Table(table) => table.raw_get(key),
@@ -100,7 +100,7 @@ impl<'lua> AnyUserDataExt<'lua> for AnyUserData<'lua> {
fn call<A, R>(&self, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>,
+ R: FromLuaMulti,
{
let metatable = self.get_metatable()?;
match metatable.get::<Value>(MetaMethod::Call)? {
@@ -110,10 +110,10 @@ impl<'lua> AnyUserDataExt<'lua> for AnyUserData<'lua> {
}
#[cfg(feature = "async")]
- fn call_async<A, R>(&self, args: A) -> LocalBoxFuture<'lua, Result<R>>
+ fn call_async<A, R>(&self, args: A) -> LocalBoxFuture<'static, Result<R>>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua,
+ R: FromLuaMulti + 'static,
{
let metatable = match self.get_metatable() {
Ok(metatable) => metatable,
@@ -121,7 +121,8 @@ impl<'lua> AnyUserDataExt<'lua> for AnyUserData<'lua> {
};
match metatable.get::<Value>(MetaMethod::Call) {
Ok(Value::Function(func)) => {
- let args = match (self, args).into_lua_multi(self.0.lua) {
+ let lua = self.0.lua.lock();
+ let args = match (self, args).into_lua_multi(lua.lua()) {
Ok(args) => args,
Err(e) => return Box::pin(future::err(e)),
};
@@ -137,16 +138,16 @@ impl<'lua> AnyUserDataExt<'lua> for AnyUserData<'lua> {
fn call_method<A, R>(&self, name: &str, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>,
+ R: FromLuaMulti,
{
self.call_function(name, (self, args))
}
#[cfg(feature = "async")]
- fn call_async_method<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'lua, Result<R>>
+ fn call_async_method<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'static, Result<R>>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua,
+ R: FromLuaMulti + 'static,
{
self.call_async_function(name, (self, args))
}
@@ -154,7 +155,7 @@ impl<'lua> AnyUserDataExt<'lua> for AnyUserData<'lua> {
fn call_function<A, R>(&self, name: &str, args: A) -> Result<R>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua>,
+ R: FromLuaMulti,
{
match self.get(name)? {
Value::Function(func) => func.call(args),
@@ -166,14 +167,15 @@ impl<'lua> AnyUserDataExt<'lua> for AnyUserData<'lua> {
}
#[cfg(feature = "async")]
- fn call_async_function<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'lua, Result<R>>
+ fn call_async_function<A, R>(&self, name: &str, args: A) -> LocalBoxFuture<'static, Result<R>>
where
A: IntoLuaMulti,
- R: FromLuaMulti<'lua> + 'lua,
+ R: FromLuaMulti + 'static,
{
match self.get(name) {
Ok(Value::Function(func)) => {
- let args = match args.into_lua_multi(self.0.lua) {
+ let lua = self.0.lua.lock();
+ let args = match args.into_lua_multi(lua.lua()) {
Ok(args) => args,
Err(e) => return Box::pin(future::err(e)),
};
diff --git a/src/userdata_impl.rs b/src/userdata_impl.rs
index b3acd48..b552778 100644
--- a/src/userdata_impl.rs
+++ b/src/userdata_impl.rs
@@ -1,7 +1,7 @@
#![allow(clippy::await_holding_refcell_ref, clippy::await_holding_lock)]
use std::any::TypeId;
-use std::cell::{Ref, RefCell, RefMut};
+use std::cell::RefCell;
use std::marker::PhantomData;
use std::os::raw::c_int;
use std::string::String as StdString;
@@ -10,9 +10,8 @@ use std::sync::{Arc, Mutex, RwLock};
use crate::error::{Error, Result};
use crate::lua::Lua;
use crate::types::{Callback, MaybeSend};
-use crate::userdata::{
- AnyUserData, MetaMethod, UserData, UserDataCell, UserDataFields, UserDataMethods,
-};
+use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataFields, UserDataMethods};
+use crate::userdata_cell::{UserDataBorrowMut, UserDataBorrowRef, UserDataVariant};
use crate::util::{get_userdata, short_type_name};
use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Value};
@@ -23,25 +22,25 @@ use std::rc::Rc;
use {crate::types::AsyncCallback, futures_util::future, std::future::Future};
/// Handle to registry for userdata methods and metamethods.
-pub struct UserDataRegistry<'lua, T: 'static> {
+pub struct UserDataRegistry<'a, T: 'static> {
// Fields
- pub(crate) fields: Vec<(String, Callback<'lua, 'static>)>,
- pub(crate) field_getters: Vec<(String, Callback<'lua, 'static>)>,
- pub(crate) field_setters: Vec<(String, Callback<'lua, 'static>)>,
- pub(crate) meta_fields: Vec<(String, Callback<'lua, 'static>)>,
+ pub(crate) fields: Vec<(String, Callback<'a>)>,
+ pub(crate) field_getters: Vec<(String, Callback<'a>)>,
+ pub(crate) field_setters: Vec<(String, Callback<'a>)>,
+ pub(crate) meta_fields: Vec<(String, Callback<'a>)>,
// Methods
- pub(crate) methods: Vec<(String, Callback<'lua, 'static>)>,
+ pub(crate) methods: Vec<(String, Callback<'a>)>,
#[cfg(feature = "async")]
- pub(crate) async_methods: Vec<(String, AsyncCallback<'lua, 'static>)>,
- pub(crate) meta_methods: Vec<(String, Callback<'lua, 'static>)>,
+ pub(crate) async_methods: Vec<(String, AsyncCallback<'a>)>,
+ pub(crate) meta_methods: Vec<(String, Callback<'a>)>,
#[cfg(feature = "async")]
- pub(crate) async_meta_methods: Vec<(String, AsyncCallback<'lua, 'static>)>,
+ pub(crate) async_meta_methods: Vec<(String, AsyncCallback<'a>)>,
_type: PhantomData<T>,
}
-impl<'lua, T: 'static> UserDataRegistry<'lua, T> {
+impl<'a, T: 'static> UserDataRegistry<'a, T> {
pub(crate) const fn new() -> Self {
UserDataRegistry {
fields: Vec::new(),
@@ -58,10 +57,10 @@ impl<'lua, T: 'static> UserDataRegistry<'lua, T> {
}
}
- fn box_method<M, A, R>(name: &str, method: M) -> Callback<'lua, 'static>
+ fn box_method<M, A, R>(name: &str, method: M) -> Callback<'a>
where
- M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ M: Fn(&'a Lua, &T, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti,
{
let name = get_function_name::<T>(name);
@@ -87,57 +86,57 @@ impl<'lua, T: 'static> UserDataRegistry<'lua, T> {
match try_self_arg!(lua.get_userdata_type_id(index)) {
Some(id) if id == TypeId::of::<T>() => {
- let ud = try_self_arg!(get_userdata_ref::<T>(state, index));
- method(lua, &ud, args?)?.push_into_stack_multi(lua)
- }
- #[cfg(not(feature = "send"))]
- Some(id) if id == TypeId::of::<Rc<T>>() => {
- let ud = try_self_arg!(get_userdata_ref::<Rc<T>>(state, index));
- method(lua, &ud, args?)?.push_into_stack_multi(lua)
- }
- #[cfg(not(feature = "send"))]
- Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
- let ud = try_self_arg!(get_userdata_ref::<Rc<RefCell<T>>>(state, index));
- let ud = try_self_arg!(ud.try_borrow(), Error::UserDataBorrowError);
- method(lua, &ud, args?)?.push_into_stack_multi(lua)
- }
- Some(id) if id == TypeId::of::<Arc<T>>() => {
- let ud = try_self_arg!(get_userdata_ref::<Arc<T>>(state, index));
- method(lua, &ud, args?)?.push_into_stack_multi(lua)
- }
- Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
- let ud = try_self_arg!(get_userdata_ref::<Arc<Mutex<T>>>(state, index));
- let ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowError);
- method(lua, &ud, args?)?.push_into_stack_multi(lua)
- }
- #[cfg(feature = "parking_lot")]
- Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
- let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(state, index);
- let ud = try_self_arg!(ud);
- let ud = try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowError));
- method(lua, &ud, args?)?.push_into_stack_multi(lua)
- }
- Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
- let ud = try_self_arg!(get_userdata_ref::<Arc<RwLock<T>>>(state, index));
- let ud = try_self_arg!(ud.try_read(), Error::UserDataBorrowError);
- method(lua, &ud, args?)?.push_into_stack_multi(lua)
- }
- #[cfg(feature = "parking_lot")]
- Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
- let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(state, index);
- let ud = try_self_arg!(ud);
- let ud = try_self_arg!(ud.try_read().ok_or(Error::UserDataBorrowError));
- method(lua, &ud, args?)?.push_into_stack_multi(lua)
+ let ud = try_self_arg!(borrow_userdata_ref::<T>(state, index));
+ method(lua.lua(), &ud, args?)?.push_into_stack_multi(lua)
}
+ // #[cfg(not(feature = "send"))]
+ // Some(id) if id == TypeId::of::<Rc<T>>() => {
+ // let ud = try_self_arg!(get_userdata_ref::<Rc<T>>(state, index));
+ // method(lua.lua(), ud, args?)?.push_into_stack_multi(lua)
+ // }
+ // #[cfg(not(feature = "send"))]
+ // Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
+ // let ud = try_self_arg!(get_userdata_ref::<Rc<RefCell<T>>>(state, index));
+ // let ud = try_self_arg!(ud.try_borrow(), Error::UserDataBorrowError);
+ // method(lua.lua(), &ud, args?)?.push_into_stack_multi(lua)
+ // }
+ // Some(id) if id == TypeId::of::<Arc<T>>() => {
+ // let ud = try_self_arg!(get_userdata_ref::<Arc<T>>(state, index));
+ // method(lua.lua(), &ud, args?)?.push_into_stack_multi(lua)
+ // }
+ // Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
+ // let ud = try_self_arg!(get_userdata_ref::<Arc<Mutex<T>>>(state, index));
+ // let ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowError);
+ // method(lua.lua(), &ud, args?)?.push_into_stack_multi(lua)
+ // }
+ // #[cfg(feature = "parking_lot")]
+ // Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
+ // let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(state, index);
+ // let ud = try_self_arg!(ud);
+ // let ud = try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowError));
+ // method(lua.lua(), &ud, args?)?.push_into_stack_multi(lua)
+ // }
+ // Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
+ // let ud = try_self_arg!(get_userdata_ref::<Arc<RwLock<T>>>(state, index));
+ // let ud = try_self_arg!(ud.try_read(), Error::UserDataBorrowError);
+ // method(lua.lua(), &ud, args?)?.push_into_stack_multi(lua)
+ // }
+ // #[cfg(feature = "parking_lot")]
+ // Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
+ // let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(state, index);
+ // let ud = try_self_arg!(ud);
+ // let ud = try_self_arg!(ud.try_read().ok_or(Error::UserDataBorrowError));
+ // method(lua.lua(), &ud, args?)?.push_into_stack_multi(lua)
+ // }
_ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)),
}
})
}
- fn box_method_mut<M, A, R>(name: &str, method: M) -> Callback<'lua, 'static>
+ fn box_method_mut<M, A, R>(name: &str, method: M) -> Callback<'a>
where
- M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ M: FnMut(&'a Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti,
{
let name = get_function_name::<T>(name);
@@ -167,61 +166,59 @@ impl<'lua, T: 'static> UserDataRegistry<'lua, T> {
match try_self_arg!(lua.get_userdata_type_id(index)) {
Some(id) if id == TypeId::of::<T>() => {
- let mut ud = try_self_arg!(get_userdata_mut::<T>(state, index));
- method(lua, &mut ud, args?)?.push_into_stack_multi(lua)
- }
- #[cfg(not(feature = "send"))]
- Some(id) if id == TypeId::of::<Rc<T>>() => Err(Error::UserDataBorrowMutError),
- #[cfg(not(feature = "send"))]
- Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
- let ud = try_self_arg!(get_userdata_mut::<Rc<RefCell<T>>>(state, index));
- let mut ud = try_self_arg!(ud.try_borrow_mut(), Error::UserDataBorrowMutError);
- method(lua, &mut ud, args?)?.push_into_stack_multi(lua)
- }
- Some(id) if id == TypeId::of::<Arc<T>>() => Err(Error::UserDataBorrowMutError),
- Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
- let ud = try_self_arg!(get_userdata_mut::<Arc<Mutex<T>>>(state, index));
- let mut ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowMutError);
- method(lua, &mut ud, args?)?.push_into_stack_multi(lua)
- }
- #[cfg(feature = "parking_lot")]
- Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
- let ud = get_userdata_mut::<Arc<parking_lot::Mutex<T>>>(state, index);
- let ud = try_self_arg!(ud);
- let mut ud = try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowMutError));
- method(lua, &mut ud, args?)?.push_into_stack_multi(lua)
- }
- Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
- let ud = try_self_arg!(get_userdata_mut::<Arc<RwLock<T>>>(state, index));
- let mut ud = try_self_arg!(ud.try_write(), Error::UserDataBorrowMutError);
- method(lua, &mut ud, args?)?.push_into_stack_multi(lua)
- }
- #[cfg(feature = "parking_lot")]
- Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
- let ud = get_userdata_mut::<Arc<parking_lot::RwLock<T>>>(state, index);
- let ud = try_self_arg!(ud);
- let mut ud = try_self_arg!(ud.try_write().ok_or(Error::UserDataBorrowMutError));
- method(lua, &mut ud, args?)?.push_into_stack_multi(lua)
+ let mut ud = try_self_arg!(borrow_userdata_mut::<T>(state, index));
+ method(lua.lua(), &mut ud, args?)?.push_into_stack_multi(lua)
}
+ // #[cfg(not(feature = "send"))]
+ // Some(id) if id == TypeId::of::<Rc<T>>() => Err(Error::UserDataBorrowMutError),
+ // #[cfg(not(feature = "send"))]
+ // Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
+ // let ud = try_self_arg!(get_userdata_mut::<Rc<RefCell<T>>>(state, index));
+ // let mut ud = try_self_arg!(ud.try_borrow_mut(), Error::UserDataBorrowMutError);
+ // method(lua.lua(), &mut ud, args?)?.push_into_stack_multi(lua)
+ // }
+ // Some(id) if id == TypeId::of::<Arc<T>>() => Err(Error::UserDataBorrowMutError),
+ // Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
+ // let ud = try_self_arg!(get_userdata_mut::<Arc<Mutex<T>>>(state, index));
+ // let mut ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowMutError);
+ // method(lua.lua(), &mut ud, args?)?.push_into_stack_multi(lua)
+ // }
+ // #[cfg(feature = "parking_lot")]
+ // Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
+ // let ud = get_userdata_mut::<Arc<parking_lot::Mutex<T>>>(state, index);
+ // let ud = try_self_arg!(ud);
+ // let mut ud = try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowMutError));
+ // method(lua.lua(), &mut ud, args?)?.push_into_stack_multi(lua)
+ // }
+ // Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
+ // let ud = try_self_arg!(get_userdata_mut::<Arc<RwLock<T>>>(state, index));
+ // let mut ud = try_self_arg!(ud.try_write(), Error::UserDataBorrowMutError);
+ // method(lua.lua(), &mut ud, args?)?.push_into_stack_multi(lua)
+ // }
+ // #[cfg(feature = "parking_lot")]
+ // Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
+ // let ud = get_userdata_mut::<Arc<parking_lot::RwLock<T>>>(state, index);
+ // let ud = try_self_arg!(ud);
+ // let mut ud = try_self_arg!(ud.try_write().ok_or(Error::UserDataBorrowMutError));
+ // method(lua.lua(), &mut ud, args?)?.push_into_stack_multi(lua)
+ // }
_ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)),
}
})
}
#[cfg(feature = "async")]
- fn box_async_method<'s, M, A, MR, R>(name: &str, method: M) -> AsyncCallback<'lua, 'static>
+ fn box_async_method<M, A, MR, R>(name: String, method: M) -> AsyncCallback<'a>
where
- 'lua: 's,
- T: 'static,
- M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- MR: Future<Output = Result<R>> + 's,
+ M: Fn(&'a Lua, &'a T, A) -> MR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ MR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti,
{
- let name = Arc::new(get_function_name::<T>(name));
+ let name = Arc::new(get_function_name::<T>(&name));
let method = Arc::new(method);
- Box::new(move |lua, mut args| unsafe {
+ Box::new(move |rawlua, mut args| unsafe {
let name = name.clone();
let method = method.clone();
macro_rules! try_self_arg {
@@ -237,65 +234,63 @@ impl<'lua, T: 'static> UserDataRegistry<'lua, T> {
let this = args.pop_front().ok_or_else(|| {
Error::from_lua_conversion("missing argument", "userdata", None)
});
+ let lua = rawlua.lua();
let this = try_self_arg!(AnyUserData::from_lua(try_self_arg!(this), lua));
let args = A::from_lua_args(args, 2, Some(&name), lua);
- let (ref_thread, index) = (lua.ref_thread(), this.0.index);
+ let (ref_thread, index) = (rawlua.ref_thread(), this.0.index);
match try_self_arg!(this.type_id()) {
Some(id) if id == TypeId::of::<T>() => {
- let ud = try_self_arg!(get_userdata_ref::<T>(ref_thread, index));
- let ud = std::mem::transmute::<&T, &T>(&ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
- }
- #[cfg(not(feature = "send"))]
- Some(id) if id == TypeId::of::<Rc<T>>() => {
- let ud = try_self_arg!(get_userdata_ref::<Rc<T>>(ref_thread, index));
- let ud = std::mem::transmute::<&T, &T>(&ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
- }
- #[cfg(not(feature = "send"))]
- Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
- let ud =
- try_self_arg!(get_userdata_ref::<Rc<RefCell<T>>>(ref_thread, index));
- let ud = try_self_arg!(ud.try_borrow(), Error::UserDataBorrowError);
- let ud = std::mem::transmute::<&T, &T>(&ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
- }
- Some(id) if id == TypeId::of::<Arc<T>>() => {
- let ud = try_self_arg!(get_userdata_ref::<Arc<T>>(ref_thread, index));
- let ud = std::mem::transmute::<&T, &T>(&ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
- }
- Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
- let ud =
- try_self_arg!(get_userdata_ref::<Arc<Mutex<T>>>(ref_thread, index));
- let ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowError);
- let ud = std::mem::transmute::<&T, &T>(&ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
- }
- #[cfg(feature = "parking_lot")]
- Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
- let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(ref_thread, index);
- let ud = try_self_arg!(ud);
- let ud = try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowError));
- let ud = std::mem::transmute::<&T, &T>(&ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
- }
- Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
- let ud =
- try_self_arg!(get_userdata_ref::<Arc<RwLock<T>>>(ref_thread, index));
- let ud = try_self_arg!(ud.try_read(), Error::UserDataBorrowError);
- let ud = std::mem::transmute::<&T, &T>(&ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
- }
- #[cfg(feature = "parking_lot")]
- Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
- let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(ref_thread, index);
- let ud = try_self_arg!(ud);
- let ud = try_self_arg!(ud.try_read().ok_or(Error::UserDataBorrowError));
+ let ud = try_self_arg!(borrow_userdata_ref::<T>(ref_thread, index));
let ud = std::mem::transmute::<&T, &T>(&ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
+ method(lua, ud, args?).await?.push_into_stack_multi(&rawlua)
}
+ // #[cfg(not(feature = "send"))]
+ // Some(id) if id == TypeId::of::<Rc<T>>() => {
+ // let ud = try_self_arg!(rawlua.get_userdata_ref::<Rc<T>>(&this));
+ // let ud = std::mem::transmute::<&T, &T>(&ud);
+ // method(lua, ud, args?).await?.push_into_stack_multi(&rawlua)
+ // }
+ // #[cfg(not(feature = "send"))]
+ // Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
+ // let ud = try_self_arg!(rawlua.get_userdata_ref::<Rc<RefCell<T>>>(&this));
+ // let ud = try_self_arg!(ud.try_borrow(), Error::UserDataBorrowError);
+ // let ud = std::mem::transmute::<&T, &T>(&ud);
+ // method(lua, ud, args?).await?.push_into_stack_multi(&rawlua)
+ // }
+ // Some(id) if id == TypeId::of::<Arc<T>>() => {
+ // let ud = try_self_arg!(rawlua.get_userdata_ref::<Arc<T>>(&this));
+ // let ud = std::mem::transmute::<&T, &T>(&ud);
+ // method(lua, ud, args?).await?.push_into_stack_multi(&rawlua)
+ // }
+ // Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
+ // let ud = try_self_arg!(rawlua.get_userdata_ref::<Arc<Mutex<T>>>(&this));
+ // let ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowError);
+ // let ud = std::mem::transmute::<&T, &T>(&ud);
+ // method(lua, ud, args?).await?.push_into_stack_multi(&rawlua)
+ // }
+ // #[cfg(feature = "parking_lot")]
+ // Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
+ // let ud = rawlua.get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(&this);
+ // let ud = try_self_arg!(ud);
+ // let ud = try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowError));
+ // let ud = std::mem::transmute::<&T, &T>(&ud);
+ // method(lua, ud, args?).await?.push_into_stack_multi(lua)
+ // }
+ // Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
+ // let ud = try_self_arg!(rawlua.get_userdata_ref::<Arc<RwLock<T>>>(&this));
+ // let ud = try_self_arg!(ud.try_read(), Error::UserDataBorrowError);
+ // let ud = std::mem::transmute::<&T, &T>(&ud);
+ // method(lua, ud, args?).await?.push_into_stack_multi(&rawlua)
+ // }
+ // #[cfg(feature = "parking_lot")]
+ // Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
+ // let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(ref_thread, index);
+ // let ud = try_self_arg!(ud);
+ // let ud = try_self_arg!(ud.try_read().ok_or(Error::UserDataBorrowError));
+ // let ud = std::mem::transmute::<&T, &T>(&ud);
+ // method(lua, ud, args?).await?.push_into_stack_multi(lua)
+ // }
_ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)),
}
})
@@ -303,19 +298,17 @@ impl<'lua, T: 'static> UserDataRegistry<'lua, T> {
}
#[cfg(feature = "async")]
- fn box_async_method_mut<'s, M, A, MR, R>(name: &str, method: M) -> AsyncCallback<'lua, 'static>
+ fn box_async_method_mut<M, A, MR, R>(name: String, method: M) -> AsyncCallback<'a>
where
- 'lua: 's,
- T: 'static,
- M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- MR: Future<Output = Result<R>> + 's,
+ M: Fn(&'a Lua, &'a mut T, A) -> MR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ MR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti,
{
- let name = Arc::new(get_function_name::<T>(name));
+ let name = Arc::new(get_function_name::<T>(&name));
let method = Arc::new(method);
- Box::new(move |lua, mut args| unsafe {
+ Box::new(move |rawlua, mut args| unsafe {
let name = name.clone();
let method = method.clone();
macro_rules! try_self_arg {
@@ -331,86 +324,87 @@ impl<'lua, T: 'static> UserDataRegistry<'lua, T> {
let this = args.pop_front().ok_or_else(|| {
Error::from_lua_conversion("missing argument", "userdata", None)
});
+ let lua = rawlua.lua();
let this = try_self_arg!(AnyUserData::from_lua(try_self_arg!(this), lua));
let args = A::from_lua_args(args, 2, Some(&name), lua);
- let (ref_thread, index) = (lua.ref_thread(), this.0.index);
+ let (ref_thread, index) = (rawlua.ref_thread(), this.0.index);
match try_self_arg!(this.type_id()) {
Some(id) if id == TypeId::of::<T>() => {
- let mut ud = try_self_arg!(get_userdata_mut::<T>(ref_thread, index));
+ let mut ud = try_self_arg!(borrow_userdata_mut::<T>(ref_thread, index));
let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
- }
- #[cfg(not(feature = "send"))]
- Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
- Err(Error::UserDataBorrowMutError)
- }
- #[cfg(not(feature = "send"))]
- Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
- let ud =
- try_self_arg!(get_userdata_mut::<Rc<RefCell<T>>>(ref_thread, index));
- let mut ud =
- try_self_arg!(ud.try_borrow_mut(), Error::UserDataBorrowMutError);
- let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
- }
- #[cfg(not(feature = "send"))]
- Some(id) if id == TypeId::of::<Arc<T>>() => Err(Error::UserDataBorrowMutError),
- Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
- let ud =
- try_self_arg!(get_userdata_mut::<Arc<Mutex<T>>>(ref_thread, index));
- let mut ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowMutError);
- let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
- }
- #[cfg(feature = "parking_lot")]
- Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
- let ud = get_userdata_mut::<Arc<parking_lot::Mutex<T>>>(ref_thread, index);
- let ud = try_self_arg!(ud);
- let mut ud =
- try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowMutError));
- let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
- }
- Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
- let ud =
- try_self_arg!(get_userdata_mut::<Arc<RwLock<T>>>(ref_thread, index));
- let mut ud = try_self_arg!(ud.try_write(), Error::UserDataBorrowMutError);
- let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
- }
- #[cfg(feature = "parking_lot")]
- Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
- let ud = get_userdata_mut::<Arc<parking_lot::RwLock<T>>>(ref_thread, index);
- let ud = try_self_arg!(ud);
- let mut ud =
- try_self_arg!(ud.try_write().ok_or(Error::UserDataBorrowMutError));
- let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
- method(lua, ud, args?).await?.push_into_stack_multi(lua)
+ method(lua, ud, args?).await?.push_into_stack_multi(&rawlua)
}
+ // #[cfg(not(feature = "send"))]
+ // Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
+ // Err(Error::UserDataBorrowMutError)
+ // }
+ // #[cfg(not(feature = "send"))]
+ // Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
+ // let ud =
+ // try_self_arg!(get_userdata_mut::<Rc<RefCell<T>>>(ref_thread, index));
+ // let mut ud =
+ // try_self_arg!(ud.try_borrow_mut(), Error::UserDataBorrowMutError);
+ // let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
+ // method(lua, ud, args?).await?.push_into_stack_multi(&rawlua)
+ // }
+ // #[cfg(not(feature = "send"))]
+ // Some(id) if id == TypeId::of::<Arc<T>>() => Err(Error::UserDataBorrowMutError),
+ // Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
+ // let ud =
+ // try_self_arg!(get_userdata_mut::<Arc<Mutex<T>>>(ref_thread, index));
+ // let mut ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowMutError);
+ // let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
+ // method(lua, ud, args?).await?.push_into_stack_multi(&rawlua)
+ // }
+ // #[cfg(feature = "parking_lot")]
+ // Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
+ // let ud = get_userdata_mut::<Arc<parking_lot::Mutex<T>>>(ref_thread, index);
+ // let ud = try_self_arg!(ud);
+ // let mut ud =
+ // try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowMutError));
+ // let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
+ // method(lua, ud, args?).await?.push_into_stack_multi(&rawlua)
+ // }
+ // Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
+ // let ud =
+ // try_self_arg!(get_userdata_mut::<Arc<RwLock<T>>>(ref_thread, index));
+ // let mut ud = try_self_arg!(ud.try_write(), Error::UserDataBorrowMutError);
+ // let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
+ // method(lua, ud, args?).await?.push_into_stack_multi(&rawlua)
+ // }
+ // #[cfg(feature = "parking_lot")]
+ // Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
+ // let ud = get_userdata_mut::<Arc<parking_lot::RwLock<T>>>(ref_thread, index);
+ // let ud = try_self_arg!(ud);
+ // let mut ud =
+ // try_self_arg!(ud.try_write().ok_or(Error::UserDataBorrowMutError));
+ // let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
+ // method(lua, ud, args?).await?.push_into_stack_multi(lua)
+ // }
_ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)),
}
})
})
}
- fn box_function<F, A, R>(name: &str, function: F) -> Callback<'lua, 'static>
+ fn box_function<F, A, R>(name: &str, function: F) -> Callback<'a>
where
- F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ F: Fn(&'a Lua, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti,
{
let name = get_function_name::<T>(name);
Box::new(move |lua, nargs| unsafe {
let args = A::from_stack_args(nargs, 1, Some(&name), lua)?;
- function(lua, args)?.push_into_stack_multi(lua)
+ function(lua.lua(), args)?.push_into_stack_multi(lua)
})
}
- fn box_function_mut<F, A, R>(name: &str, function: F) -> Callback<'lua, 'static>
+ fn box_function_mut<F, A, R>(name: &str, function: F) -> Callback<'a>
where
- F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ F: FnMut(&'a Lua, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti,
{
let name = get_function_name::<T>(name);
@@ -420,30 +414,32 @@ impl<'lua, T: 'static> UserDataRegistry<'lua, T> {
.try_borrow_mut()
.map_err(|_| Error::RecursiveMutCallback)?;
let args = A::from_stack_args(nargs, 1, Some(&name), lua)?;
- function(lua, args)?.push_into_stack_multi(lua)
+ function(lua.lua(), args)?.push_into_stack_multi(lua)
})
}
#[cfg(feature = "async")]
- fn box_async_function<F, A, FR, R>(name: &str, function: F) -> AsyncCallback<'lua, 'static>
+ fn box_async_function<F, A, FR, R>(name: String, function: F) -> AsyncCallback<'a>
where
- F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- FR: Future<Output = Result<R>> + 'lua,
+ F: Fn(&'a Lua, A) -> FR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ FR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti,
{
- let name = get_function_name::<T>(name);
- Box::new(move |lua, args| unsafe {
+ let name = get_function_name::<T>(&name);
+ Box::new(move |rawlua, args| unsafe {
+ let lua = rawlua.lua();
let args = match A::from_lua_args(args, 1, Some(&name), lua) {
Ok(args) => args,
Err(e) => return Box::pin(future::err(e)),
};
let fut = function(lua, args);
- Box::pin(async move { fut.await?.push_into_stack_multi(lua) })
+ let weak = rawlua.weak().clone();
+ Box::pin(async move { fut.await?.push_into_stack_multi(&weak.lock()) })
})
}
- pub(crate) fn check_meta_field<V>(lua: &'lua Lua, name: &str, value: V) -> Result<Value<'lua>>
+ pub(crate) fn check_meta_field<V>(lua: &Lua, name: &str, value: V) -> Result<Value>
where
V: IntoLua,
{
@@ -469,310 +465,296 @@ fn get_function_name<T>(name: &str) -> StdString {
format!("{}.{name}", short_type_name::<T>())
}
-impl<'lua, T: 'static> UserDataFields<'lua, T> for UserDataRegistry<'lua, T> {
- fn add_field<V>(&mut self, name: impl AsRef<str>, value: V)
+impl<'a, T: 'static> UserDataFields<'a, T> for UserDataRegistry<'a, T> {
+ fn add_field<V>(&mut self, name: impl ToString, value: V)
where
V: IntoLua + Clone + 'static,
{
- let name = name.as_ref().to_string();
- self.fields.push((
- name,
- Box::new(move |lua, _| unsafe { value.clone().push_into_stack_multi(lua) }),
- ));
+ let name = name.to_string();
+ let callback = Box::new(move |lua, _| unsafe { value.clone().push_into_stack_multi(lua) });
+ self.fields.push((name, callback));
}
- fn add_field_method_get<M, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_field_method_get<M, R>(&mut self, name: impl ToString, method: M)
where
- M: Fn(&'lua Lua, &T) -> Result<R> + MaybeSend + 'static,
+ M: Fn(&'a Lua, &T) -> Result<R> + MaybeSend + 'static,
R: IntoLua,
{
- let name = name.as_ref();
- let method = Self::box_method(name, move |lua, data, ()| method(lua, data));
- self.field_getters.push((name.into(), method));
+ let name = name.to_string();
+ let callback = Self::box_method(&name, move |lua, data, ()| method(lua, &data));
+ self.field_getters.push((name.into(), callback));
}
- fn add_field_method_set<M, A>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_field_method_set<M, A>(&mut self, name: impl ToString, method: M)
where
- M: FnMut(&'lua Lua, &mut T, A) -> Result<()> + MaybeSend + 'static,
- A: FromLua<'lua>,
+ M: FnMut(&'a Lua, &mut T, A) -> Result<()> + MaybeSend + 'static,
+ A: FromLua,
{
- let name = name.as_ref();
- let method = Self::box_method_mut(name, method);
- self.field_setters.push((name.into(), method));
+ let name = name.to_string();
+ let callback = Self::box_method_mut(&name, method);
+ self.field_setters.push((name, callback));
}
- fn add_field_function_get<F, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_field_function_get<F, R>(&mut self, name: impl ToString, function: F)
where
- F: Fn(&'lua Lua, AnyUserData<'lua>) -> Result<R> + MaybeSend + 'static,
+ F: Fn(&'a Lua, AnyUserData) -> Result<R> + MaybeSend + 'static,
R: IntoLua,
{
- let name = name.as_ref();
- let func = Self::box_function(name, function);
- self.field_getters.push((name.into(), func));
+ let name = name.to_string();
+ let callback = Self::box_function(&name, function);
+ self.field_getters.push((name, callback));
}
- fn add_field_function_set<F, A>(&mut self, name: impl AsRef<str>, mut function: F)
+ fn add_field_function_set<F, A>(&mut self, name: impl ToString, mut function: F)
where
- F: FnMut(&'lua Lua, AnyUserData<'lua>, A) -> Result<()> + MaybeSend + 'static,
- A: FromLua<'lua>,
+ F: FnMut(&'a Lua, AnyUserData, A) -> Result<()> + MaybeSend + 'static,
+ A: FromLua,
{
- let name = name.as_ref();
- let func = Self::box_function_mut(name, move |lua, (data, val)| function(lua, data, val));
- self.field_setters.push((name.into(), func));
+ let name = name.to_string();
+ let callback =
+ Self::box_function_mut(&name, move |lua, (data, val)| function(lua, data, val));
+ self.field_setters.push((name, callback));
}
- fn add_meta_field<V>(&mut self, name: impl AsRef<str>, value: V)
+ fn add_meta_field<V>(&mut self, name: impl ToString, value: V)
where
V: IntoLua + Clone + 'static,
{
- let name = name.as_ref().to_string();
+ let name = name.to_string();
let name2 = name.clone();
self.meta_fields.push((
name,
Box::new(move |lua, _| unsafe {
- Self::check_meta_field(lua, &name2, value.clone())?.push_into_stack_multi(lua)
+ Self::check_meta_field(lua.lua(), &name2, value.clone())?.push_into_stack_multi(lua)
}),
));
}
- fn add_meta_field_with<F, R>(&mut self, name: impl AsRef<str>, f: F)
+ fn add_meta_field_with<F, R>(&mut self, name: impl ToString, f: F)
where
- F: Fn(&'lua Lua) -> Result<R> + MaybeSend + 'static,
+ F: Fn(&'a Lua) -> Result<R> + MaybeSend + 'static,
R: IntoLua,
{
- let name = name.as_ref().to_string();
+ let name = name.to_string();
let name2 = name.clone();
self.meta_fields.push((
name,
- Box::new(move |lua, _| unsafe {
- Self::check_meta_field(lua, &name2, f(lua)?)?.push_into_stack_multi(lua)
+ Box::new(move |rawlua, _| unsafe {
+ let lua = rawlua.lua();
+ Self::check_meta_field(lua, &name2, f(lua)?)?.push_into_stack_multi(rawlua)
}),
));
}
-
- // Below are internal methods
-
- fn append_fields_from<S>(&mut self, other: UserDataRegistry<'lua, S>) {
- self.fields.extend(other.fields);
- self.field_getters.extend(other.field_getters);
- self.field_setters.extend(other.field_setters);
- self.meta_fields.extend(other.meta_fields);
- }
}
-impl<'lua, T: 'static> UserDataMethods<'lua, T> for UserDataRegistry<'lua, T> {
- fn add_method<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
+impl<'a, T: 'static> UserDataMethods<'a, T> for UserDataRegistry<'a, T> {
+ fn add_method<M, A, R>(&mut self, name: impl ToString, method: M)
where
- M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ M: Fn(&'a Lua, &T, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.methods
- .push((name.into(), Self::box_method(name, method)));
+ let name = name.to_string();
+ let callback = Self::box_method(&name, method);
+ self.methods.push((name, callback));
}
- fn add_method_mut<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_method_mut<M, A, R>(&mut self, name: impl ToString, method: M)
where
- M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ M: FnMut(&'a Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.methods
- .push((name.into(), Self::box_method_mut(name, method)));
+ let name = name.to_string();
+ let callback = Self::box_method_mut(&name, method);
+ self.methods.push((name, callback));
}
#[cfg(feature = "async")]
- fn add_async_method<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_async_method<M, A, MR, R>(&mut self, name: impl ToString, method: M)
where
- 'lua: 's,
- T: 'static,
- M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- MR: Future<Output = Result<R>> + 's,
+ M: Fn(&'a Lua, &'a T, A) -> MR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ MR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.async_methods
- .push((name.into(), Self::box_async_method(name, method)));
+ let name = name.to_string();
+ let callback = Self::box_async_method(name.clone(), method);
+ self.async_methods.push((name, callback));
}
#[cfg(feature = "async")]
- fn add_async_method_mut<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_async_method_mut<M, A, MR, R>(&mut self, name: impl ToString, method: M)
where
- 'lua: 's,
- T: 'static,
- M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- MR: Future<Output = Result<R>> + 's,
+ M: Fn(&'a Lua, &'a mut T, A) -> MR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ MR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.async_methods
- .push((name.into(), Self::box_async_method_mut(name, method)));
+ let name = name.to_string();
+ let callback = Self::box_async_method_mut(name.clone(), method);
+ self.async_methods.push((name, callback));
}
- fn add_function<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_function<F, A, R>(&mut self, name: impl ToString, function: F)
where
- F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ F: Fn(&'a Lua, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.methods
- .push((name.into(), Self::box_function(name, function)));
+ let name = name.to_string();
+ let callback = Self::box_function(&name, function);
+ self.methods.push((name, callback));
}
- fn add_function_mut<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_function_mut<F, A, R>(&mut self, name: impl ToString, function: F)
where
- F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ F: FnMut(&'a Lua, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.methods
- .push((name.into(), Self::box_function_mut(name, function)));
+ let name = name.to_string();
+ let callback = Self::box_function_mut(&name, function);
+ self.methods.push((name, callback));
}
#[cfg(feature = "async")]
- fn add_async_function<F, A, FR, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_async_function<F, A, FR, R>(&mut self, name: impl ToString, function: F)
where
- F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- FR: Future<Output = Result<R>> + 'lua,
+ F: Fn(&'a Lua, A) -> FR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ FR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.async_methods
- .push((name.into(), Self::box_async_function(name, function)));
+ let name = name.to_string();
+ let callback = Self::box_async_function(name.clone(), function);
+ self.async_methods.push((name, callback));
}
- fn add_meta_method<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_meta_method<M, A, R>(&mut self, name: impl ToString, method: M)
where
- M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ M: Fn(&'a Lua, &T, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.meta_methods
- .push((name.into(), Self::box_method(name, method)));
+ let name = name.to_string();
+ let callback = Self::box_method(&name, method);
+ self.meta_methods.push((name, callback));
}
- fn add_meta_method_mut<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_meta_method_mut<M, A, R>(&mut self, name: impl ToString, method: M)
where
- M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ M: FnMut(&'a Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.meta_methods
- .push((name.into(), Self::box_method_mut(name, method)));
+ let name = name.to_string();
+ let callback = Self::box_method_mut(&name, method);
+ self.meta_methods.push((name, callback));
}
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
- fn add_async_meta_method<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_async_meta_method<M, A, MR, R>(&mut self, name: impl ToString, method: M)
where
- 'lua: 's,
- T: 'static,
- M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- MR: Future<Output = Result<R>> + 's,
+ M: Fn(&'a Lua, &'a T, A) -> MR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ MR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.async_meta_methods
- .push((name.into(), Self::box_async_method(name, method)));
+ let name = name.to_string();
+ let callback = Self::box_async_method(name.clone(), method);
+ self.async_meta_methods.push((name, callback));
}
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
- fn add_async_meta_method_mut<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
+ fn add_async_meta_method_mut<M, A, MR, R>(&mut self, name: impl ToString, method: M)
where
- 'lua: 's,
- T: 'static,
- M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- MR: Future<Output = Result<R>> + 's,
+ M: Fn(&'a Lua, &'a mut T, A) -> MR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ MR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.async_meta_methods
- .push((name.into(), Self::box_async_method_mut(name, method)));
+ let name = name.to_string();
+ let callback = Self::box_async_method_mut(name.clone(), method);
+ self.async_meta_methods.push((name, callback));
}
- fn add_meta_function<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_meta_function<F, A, R>(&mut self, name: impl ToString, function: F)
where
- F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ F: Fn(&'a Lua, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.meta_methods
- .push((name.into(), Self::box_function(name, function)));
+ let name = name.to_string();
+ let callback = Self::box_function(&name, function);
+ self.meta_methods.push((name, callback));
}
- fn add_meta_function_mut<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_meta_function_mut<F, A, R>(&mut self, name: impl ToString, function: F)
where
- F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
+ F: FnMut(&'a Lua, A) -> Result<R> + MaybeSend + 'static,
+ A: FromLuaMulti,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.meta_methods
- .push((name.into(), Self::box_function_mut(name, function)));
+ let name = name.to_string();
+ let callback = Self::box_function_mut(&name, function);
+ self.meta_methods.push((name, callback));
}
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
- fn add_async_meta_function<F, A, FR, R>(&mut self, name: impl AsRef<str>, function: F)
+ fn add_async_meta_function<F, A, FR, R>(&mut self, name: impl ToString, function: F)
where
- F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
- A: FromLuaMulti<'lua>,
- FR: Future<Output = Result<R>> + 'lua,
+ F: Fn(&'a Lua, A) -> FR + MaybeSend + 'static,
+ A: FromLuaMulti,
+ FR: Future<Output = Result<R>> + 'a,
R: IntoLuaMulti,
{
- let name = name.as_ref();
- self.async_meta_methods
- .push((name.into(), Self::box_async_function(name, function)));
- }
-
- // Below are internal methods used in generated code
-
- fn append_methods_from<S>(&mut self, other: UserDataRegistry<'lua, S>) {
- self.methods.extend(other.methods);
- #[cfg(feature = "async")]
- self.async_methods.extend(other.async_methods);
- self.meta_methods.extend(other.meta_methods);
- #[cfg(feature = "async")]
- self.async_meta_methods.extend(other.async_meta_methods);
+ let name = name.to_string();
+ let callback = Self::box_async_function(name.clone(), function);
+ self.async_meta_methods.push((name, callback));
}
}
+// Borrow the userdata in-place from the Lua stack
#[inline]
-unsafe fn get_userdata_ref<'a, T>(state: *mut ffi::lua_State, index: c_int) -> Result<Ref<'a, T>> {
- (*get_userdata::<UserDataCell<T>>(state, index)).try_borrow()
+unsafe fn borrow_userdata_ref<'a, T>(
+ state: *mut ffi::lua_State,
+ index: c_int,
+) -> Result<UserDataBorrowRef<'a, T>> {
+ let ud = get_userdata::<UserDataVariant<T>>(state, index);
+ (*ud).try_borrow()
}
+// Borrow the userdata mutably in-place from the Lua stack
#[inline]
-unsafe fn get_userdata_mut<'a, T>(
+unsafe fn borrow_userdata_mut<'a, T>(
state: *mut ffi::lua_State,
index: c_int,
-) -> Result<RefMut<'a, T>> {
- (*get_userdata::<UserDataCell<T>>(state, index)).try_borrow_mut()
+) -> Result<UserDataBorrowMut<'a, T>> {
+ let ud = get_userdata::<UserDataVariant<T>>(state, index);
+ (*ud).try_borrow_mut()
}
macro_rules! lua_userdata_impl {
($type:ty) => {
impl<T: UserData + 'static> UserData for $type {
- fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
- let mut orig_fields = UserDataRegistry::new();
- T::add_fields(&mut orig_fields);
- fields.append_fields_from(orig_fields);
- }
-
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
- let mut orig_methods = UserDataRegistry::new();
- T::add_methods(&mut orig_methods);
- methods.append_methods_from(orig_methods);
+ fn register(registry: &mut UserDataRegistry<Self>) {
+ let mut orig_registry = UserDataRegistry::new();
+ T::register(&mut orig_registry);
+
+ // Copy all fields, methods, etc. from the original registry
+ registry.fields.extend(orig_registry.fields);
+ registry.field_getters.extend(orig_registry.field_getters);
+ registry.field_setters.extend(orig_registry.field_setters);
+ registry.meta_fields.extend(orig_registry.meta_fields);
+ registry.methods.extend(orig_registry.methods);
+ #[cfg(feature = "async")]
+ registry.async_methods.extend(orig_registry.async_methods);
+ registry.meta_methods.extend(orig_registry.meta_methods);
+ #[cfg(feature = "async")]
+ registry
+ .async_meta_methods
+ .extend(orig_registry.async_meta_methods);
}
}
};
diff --git a/src/value.rs b/src/value.rs
index 2e5f2d9..e589d8c 100644
--- a/src/value.rs
+++ b/src/value.rs
@@ -19,7 +19,7 @@ use {
use crate::error::{Error, Result};
use crate::function::Function;
-use crate::lua::Lua;
+use crate::lua::{Lua, LuaInner};
use crate::string::String;
use crate::table::Table;
use crate::thread::Thread;
@@ -31,7 +31,7 @@ use crate::util::{check_stack, StackGuard};
/// variants contain handle types into the internal Lua state. It is a logic error to mix handle
/// types between separate `Lua` instances, and doing so will result in a panic.
#[derive(Clone)]
-pub enum Value<'lua> {
+pub enum Value {
/// The Lua value `nil`.
Nil,
/// The Lua value `true` or `false`.
@@ -51,27 +51,27 @@ pub enum Value<'lua> {
/// An interned string, managed by Lua.
///
/// Unlike Rust strings, Lua strings may not be valid UTF-8.
- String(String<'lua>),
+ String(String),
/// Reference to a Lua table.
- Table(Table<'lua>),
+ Table(Table),
/// Reference to a Lua function (or closure).
- Function(Function<'lua>),
+ Function(Function),
/// Reference to a Lua thread (or coroutine).
- Thread(Thread<'lua>),
+ Thread(Thread),
/// Reference to a userdata object that holds a custom type which implements `UserData`.
/// Special builtin userdata types will be represented as other `Value` variants.
- UserData(AnyUserData<'lua>),
+ UserData(AnyUserData),
/// `Error` is a special builtin userdata type. When received from Lua it is implicitly cloned.
Error(Box<Error>),
}
pub use self::Value::Nil;
-impl<'lua> Value<'lua> {
+impl Value {
/// A special value (lightuserdata) to represent null value.
///
/// It can be used in Lua tables without downsides of `nil`.
- pub const NULL: Value<'static> = Value::LightUserData(LightUserData(ptr::null_mut()));
+ pub const NULL: Value = Value::LightUserData(LightUserData(ptr::null_mut()));
/// Returns type name of this value.
pub const fn type_name(&self) -> &'static str {
@@ -152,15 +152,16 @@ impl<'lua> Value<'lua> {
| Value::Function(Function(r))
| Value::Thread(Thread(r, ..))
| Value::UserData(AnyUserData(r, ..)) => unsafe {
- let state = r.lua.state();
+ let lua = r.lua.lock();
+ let state = lua.state();
let _guard = StackGuard::new(state);
check_stack(state, 3)?;
- r.lua.push_ref(r);
+ lua.push_ref(r);
protect_lua!(state, 1, 1, fn(state) {
ffi::luaL_tolstring(state, -1, ptr::null_mut());
})?;
- Ok(String(r.lua.pop_ref()).to_str()?.to_string())
+ Ok(String(lua.pop_ref()).to_str()?.to_string())
},
Value::Error(err) => Ok(err.to_string()),
}
@@ -440,7 +441,7 @@ impl<'lua> Value<'lua> {
#[cfg(feature = "serialize")]
#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
#[doc(hidden)]
- pub fn to_serializable(&self) -> SerializableValue<'_, 'lua> {
+ pub fn to_serializable(&self) -> SerializableValue {
SerializableValue::new(self, Default::default(), None)
}
@@ -522,7 +523,7 @@ impl<'lua> Value<'lua> {
}
}
-impl fmt::Debug for Value<'_> {
+impl fmt::Debug for Value {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
if fmt.alternate() {
return self.fmt_pretty(fmt, true, 0, &mut HashSet::new());
@@ -545,7 +546,7 @@ impl fmt::Debug for Value<'_> {
}
}
-impl<'lua> PartialEq for Value<'lua> {
+impl PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Value::Nil, Value::Nil) => true,
@@ -567,7 +568,7 @@ impl<'lua> PartialEq for Value<'lua> {
}
}
-impl<'lua> AsRef<Value<'lua>> for Value<'lua> {
+impl AsRef<Value> for Value {
#[inline]
fn as_ref(&self) -> &Self {
self
@@ -577,15 +578,15 @@ impl<'lua> AsRef<Value<'lua>> for Value<'lua> {
/// A wrapped [`Value`] with customized serialization behavior.
#[cfg(feature = "serialize")]
#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
-pub struct SerializableValue<'a, 'lua> {
- value: &'a Value<'lua>,
+pub struct SerializableValue<'a> {
+ value: &'a Value,
options: crate::serde::de::Options,
// In many cases we don't need `visited` map, so don't allocate memory by default
visited: Option<Rc<RefCell<FxHashSet<*const c_void>>>>,
}
#[cfg(feature = "serialize")]
-impl<'lua> Serialize for Value<'lua> {
+impl Serialize for Value {
#[inline]
fn serialize<S: Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
SerializableValue::new(self, Default::default(), None).serialize(serializer)
@@ -593,10 +594,10 @@ impl<'lua> Serialize for Value<'lua> {
}
#[cfg(feature = "serialize")]
-impl<'a, 'lua> SerializableValue<'a, 'lua> {
+impl<'a> SerializableValue<'a> {
#[inline]
pub(crate) fn new(
- value: &'a Value<'lua>,
+ value: &'a Value,
options: crate::serde::de::Options,
visited: Option<&Rc<RefCell<FxHashSet<*const c_void>>>>,
) -> Self {
@@ -648,7 +649,7 @@ impl<'a, 'lua> SerializableValue<'a, 'lua> {
}
#[cfg(feature = "serialize")]
-impl<'a, 'lua> Serialize for SerializableValue<'a, 'lua> {
+impl<'a> Serialize for SerializableValue<'a> {
fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
where
S: Serializer,
@@ -689,7 +690,7 @@ impl<'a, 'lua> Serialize for SerializableValue<'a, 'lua> {
/// Trait for types convertible to `Value`.
pub trait IntoLua: Sized {
/// Performs the conversion.
- fn into_lua(self, lua: &Lua) -> Result<Value<'_>>;
+ fn into_lua(self, lua: &Lua) -> Result<Value>;
/// Pushes the value into the Lua stack.
///
@@ -697,15 +698,15 @@ pub trait IntoLua: Sized {
/// This method does not check Lua stack space.
#[doc(hidden)]
#[inline]
- unsafe fn push_into_stack(self, lua: &Lua) -> Result<()> {
- lua.push_value(&self.into_lua(lua)?)
+ unsafe fn push_into_stack(self, lua: &LuaInner) -> Result<()> {
+ lua.push_value(&self.into_lua(lua.lua())?)
}
}
/// Trait for types convertible from `Value`.
-pub trait FromLua<'lua>: Sized {
+pub trait FromLua: Sized {
/// Performs the conversion.
- fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self>;
+ fn from_lua(value: Value, lua: &Lua) -> Result<Self>;
/// Performs the conversion for an argument (eg. function argument).
///
@@ -713,7 +714,7 @@ pub trait FromLua<'lua>: Sized {
/// `to` is a function name that received the argument.
#[doc(hidden)]
#[inline]
- fn from_lua_arg(arg: Value<'lua>, i: usize, to: Option<&str>, lua: &'lua Lua) -> Result<Self> {
+ fn from_lua_arg(arg: Value, i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> {
Self::from_lua(arg, lua).map_err(|err| Error::BadArgument {
to: to.map(|s| s.to_string()),
pos: i,
@@ -725,8 +726,8 @@ pub trait FromLua<'lua>: Sized {
/// Performs the conversion for a value in the Lua stack at index `idx`.
#[doc(hidden)]
#[inline]
- unsafe fn from_stack(idx: c_int, lua: &'lua Lua) -> Result<Self> {
- Self::from_lua(lua.stack_value(idx), lua)
+ unsafe fn from_stack(idx: c_int, lua: &LuaInner) -> Result<Self> {
+ Self::from_lua(lua.stack_value(idx), lua.lua())
}
/// Same as `from_lua_arg` but for a value in the Lua stack at index `idx`.
@@ -736,7 +737,7 @@ pub trait FromLua<'lua>: Sized {
idx: c_int,
i: usize,
to: Option<&str>,
- lua: &'lua Lua,
+ lua: &LuaInner,
) -> Result<Self> {
Self::from_stack(idx, lua).map_err(|err| Error::BadArgument {
to: to.map(|s| s.to_string()),
@@ -749,29 +750,31 @@ pub trait FromLua<'lua>: Sized {
/// Multiple Lua values used for both argument passing and also for multiple return values.
#[derive(Debug, Clone)]
-pub struct MultiValue<'lua> {
- deque: VecDeque<Value<'lua>>,
- lua: Option<&'lua Lua>,
+pub struct MultiValue {
+ deque: VecDeque<Value>,
+ // FIXME
+ // lua: Option<&'static Lua>,
}
-impl Drop for MultiValue<'_> {
+impl Drop for MultiValue {
fn drop(&mut self) {
- if let Some(lua) = self.lua {
- let vec = mem::take(&mut self.deque);
- lua.push_multivalue_to_pool(vec);
- }
+ // FIXME
+ // if let Some(lua) = self.lua {
+ // let vec = mem::take(&mut self.deque);
+ // lua.push_multivalue_to_pool(vec);
+ // }
}
}
-impl<'lua> Default for MultiValue<'lua> {
+impl Default for MultiValue {
#[inline]
- fn default() -> MultiValue<'lua> {
+ fn default() -> MultiValue {
MultiValue::new()
}
}
-impl<'lua> Deref for MultiValue<'lua> {
- type Target = VecDeque<Value<'lua>>;
+impl Deref for MultiValue {
+ type Target = VecDeque<Value>;
#[inline]
fn deref(&self) -> &Self::Target {
@@ -779,44 +782,46 @@ impl<'lua> Deref for MultiValue<'lua> {
}
}
-impl<'lua> DerefMut for MultiValue<'lua> {
+impl DerefMut for MultiValue {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.deque
}
}
-impl<'lua> MultiValue<'lua> {
+impl MultiValue {
/// Creates an empty `MultiValue` containing no values.
- pub const fn new() -> MultiValue<'lua> {
+ pub const fn new() -> MultiValue {
MultiValue {
deque: VecDeque::new(),
- lua: None,
+ // lua: None,
}
}
/// Similar to `new` but can reuse previously used container with allocated capacity.
#[inline]
- pub(crate) fn with_lua_and_capacity(lua: &'lua Lua, capacity: usize) -> MultiValue<'lua> {
- let deque = lua
- .pop_multivalue_from_pool()
- .map(|mut deque| {
- if capacity > 0 {
- deque.reserve(capacity);
- }
- deque
- })
- .unwrap_or_else(|| VecDeque::with_capacity(capacity));
+ pub(crate) fn with_lua_and_capacity(_lua: &Lua, capacity: usize) -> MultiValue {
+ // FIXME
+ // let deque = lua
+ // .pop_multivalue_from_pool()
+ // .map(|mut deque| {
+ // if capacity > 0 {
+ // deque.reserve(capacity);
+ // }
+ // deque
+ // })
+ // .unwrap_or_else(|| VecDeque::with_capacity(capacity));
+ let deque = VecDeque::with_capacity(capacity);
MultiValue {
deque,
- lua: Some(lua),
+ // lua: Some(lua),
}
}
#[inline]
pub(crate) fn extend_from_values(
&mut self,
- iter: impl IntoIterator<Item = Result<Value<'lua>>>,
+ iter: impl IntoIterator<Item = Result<Value>>,
) -> Result<()> {
for value in iter {
self.push_back(value?);
@@ -825,17 +830,20 @@ impl<'lua> MultiValue<'lua> {
}
}
-impl<'lua> FromIterator<Value<'lua>> for MultiValue<'lua> {
+impl FromIterator<Value> for MultiValue {
#[inline]
- fn from_iter<I: IntoIterator<Item = Value<'lua>>>(iter: I) -> Self {
+ fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
let deque = VecDeque::from_iter(iter);
- MultiValue { deque, lua: None }
+ MultiValue {
+ deque,
+ // lua: None,
+ }
}
}
-impl<'lua> IntoIterator for MultiValue<'lua> {
- type Item = Value<'lua>;
- type IntoIter = vec_deque::IntoIter<Value<'lua>>;
+impl IntoIterator for MultiValue {
+ type Item = Value;
+ type IntoIter = vec_deque::IntoIter<Value>;
#[inline]
fn into_iter(mut self) -> Self::IntoIter {
@@ -845,9 +853,9 @@ impl<'lua> IntoIterator for MultiValue<'lua> {
}
}
-impl<'a, 'lua> IntoIterator for &'a MultiValue<'lua> {
- type Item = &'a Value<'lua>;
- type IntoIter = vec_deque::Iter<'a, Value<'lua>>;
+impl<'a> IntoIterator for &'a MultiValue {
+ type Item = &'a Value;
+ type IntoIter = vec_deque::Iter<'a, Value>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
@@ -861,15 +869,15 @@ impl<'a, 'lua> IntoIterator for &'a MultiValue<'lua> {
/// one. Any type that implements `IntoLua` will automatically implement this trait.
pub trait IntoLuaMulti: Sized {
/// Performs the conversion.
- fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue<'_>>;
+ fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue>;
/// Pushes the values into the Lua stack.
///
/// Returns number of pushed values.
#[doc(hidden)]
#[inline]
- unsafe fn push_into_stack_multi(self, lua: &Lua) -> Result<c_int> {
- let values = self.into_lua_multi(lua)?;
+ unsafe fn push_into_stack_multi(self, lua: &LuaInner) -> Result<c_int> {
+ let values = self.into_lua_multi(lua.lua())?;
let len: c_int = values.len().try_into().unwrap();
unsafe {
check_stack(lua.state(), len + 1)?;
@@ -885,14 +893,14 @@ pub trait IntoLuaMulti: Sized {
///
/// This is a generalization of `FromLua`, allowing an arbitrary number of Lua values to participate
/// in the conversion. Any type that implements `FromLua` will automatically implement this trait.
-pub trait FromLuaMulti<'lua>: Sized {
+pub trait FromLuaMulti: Sized {
/// Performs the conversion.
///
/// In case `values` contains more values than needed to perform the conversion, the excess
/// values should be ignored. This reflects the semantics of Lua when calling a function or
/// assigning values. Similarly, if not enough values are given, conversions should assume that
/// any missing values are nil.
- fn from_lua_multi(values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self>;
+ fn from_lua_multi(values: MultiValue, lua: &Lua) -> Result<Self>;
/// Performs the conversion for a list of arguments.
///
@@ -900,12 +908,7 @@ pub trait FromLuaMulti<'lua>: Sized {
/// `to` is a function name that received the arguments.
#[doc(hidden)]
#[inline]
- fn from_lua_args(
- args: MultiValue<'lua>,
- i: usize,
- to: Option<&str>,
- lua: &'lua Lua,
- ) -> Result<Self> {
+ fn from_lua_args(args: MultiValue, i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> {
let _ = (i, to);
Self::from_lua_multi(args, lua)
}
@@ -913,8 +916,8 @@ pub trait FromLuaMulti<'lua>: Sized {
/// Performs the conversion for a number of values in the Lua stack.
#[doc(hidden)]
#[inline]
- unsafe fn from_stack_multi(nvals: c_int, lua: &'lua Lua) -> Result<Self> {
- let mut values = MultiValue::with_lua_and_capacity(lua, nvals as usize);
+ unsafe fn from_stack_multi(nvals: c_int, lua: &LuaInner) -> Result<Self> {
+ let mut values = MultiValue::with_lua_and_capacity(lua.lua(), nvals as usize);
for idx in 0..nvals {
values.push_back(lua.stack_value(-nvals + idx));
}
@@ -922,7 +925,7 @@ pub trait FromLuaMulti<'lua>: Sized {
// It's safe to clear the stack as all references moved to ref thread
ffi::lua_pop(lua.state(), nvals);
}
- Self::from_lua_multi(values, lua)
+ Self::from_lua_multi(values, lua.lua())
}
/// Same as `from_lua_args` but for a number of values in the Lua stack.
@@ -932,7 +935,7 @@ pub trait FromLuaMulti<'lua>: Sized {
nargs: c_int,
i: usize,
to: Option<&str>,
- lua: &'lua Lua,
+ lua: &LuaInner,
) -> Result<Self> {
let _ = (i, to);
Self::from_stack_multi(nargs, lua)
diff --git a/tests/async.rs b/tests/async.rs
index 9c4c865..0fda52f 100644
--- a/tests/async.rs
+++ b/tests/async.rs
@@ -386,7 +386,7 @@ async fn test_async_userdata() -> Result<()> {
struct MyUserData(u64);
impl UserData for MyUserData {
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_async_method("get_value", |_, data, ()| async move {
sleep_ms(10).await;
Ok(data.0)
@@ -488,7 +488,7 @@ async fn test_async_thread_error() -> Result<()> {
struct MyUserData;
impl UserData for MyUserData {
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_meta_method("__tostring", |_, _this, ()| Ok("myuserdata error"))
}
}
@@ -507,24 +507,6 @@ async fn test_async_thread_error() -> Result<()> {
Ok(())
}
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[tokio::test]
-async fn test_owned_async_call() -> Result<()> {
- let lua = Lua::new();
-
- let hello = lua
- .create_async_function(|_, name: String| async move {
- sleep_ms(10).await;
- Ok(format!("hello, {}!", name))
- })?
- .into_owned();
- drop(lua);
-
- assert_eq!(hello.call_async::<_, String>("alex").await?, "hello, alex!");
-
- Ok(())
-}
-
#[tokio::test]
async fn test_async_terminate() -> Result<()> {
let lua = Lua::new();
diff --git a/tests/conversion.rs b/tests/conversion.rs
index 5897d75..a0e0b38 100644
--- a/tests/conversion.rs
+++ b/tests/conversion.rs
@@ -43,35 +43,6 @@ fn test_string_into_lua() -> Result<()> {
Ok(())
}
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[test]
-fn test_owned_string_into_lua() -> Result<()> {
- let lua = Lua::new();
-
- // Direct conversion
- let s = lua.create_string("hello, world")?.into_owned();
- let s2 = (&s).into_lua(&lua)?;
- assert_eq!(s.to_ref(), *s2.as_string().unwrap());
-
- // Push into stack
- let table = lua.create_table()?;
- table.set("s", &s)?;
- assert_eq!(s.to_ref(), table.get::<_, String>("s")?);
-
- Ok(())
-}
-
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[test]
-fn test_owned_string_from_lua() -> Result<()> {
- let lua = Lua::new();
-
- let s = lua.unpack::<mlua::OwnedString>(lua.pack("hello, world")?)?;
- assert_eq!(s.to_ref(), "hello, world");
-
- Ok(())
-}
-
#[test]
fn test_table_into_lua() -> Result<()> {
let lua = Lua::new();
@@ -89,24 +60,6 @@ fn test_table_into_lua() -> Result<()> {
Ok(())
}
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[test]
-fn test_owned_table_into_lua() -> Result<()> {
- let lua = Lua::new();
-
- // Direct conversion
- let t = lua.create_table()?.into_owned();
- let t2 = (&t).into_lua(&lua)?;
- assert_eq!(t.to_ref(), *t2.as_table().unwrap());
-
- // Push into stack
- let f = lua.create_function(|_, (t, s): (Table, String)| t.set("s", s))?;
- f.call((&t, "hello"))?;
- assert_eq!("hello", t.to_ref().get::<_, String>("s")?);
-
- Ok(())
-}
-
#[test]
fn test_function_into_lua() -> Result<()> {
let lua = Lua::new();
@@ -124,26 +77,6 @@ fn test_function_into_lua() -> Result<()> {
Ok(())
}
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[test]
-fn test_owned_function_into_lua() -> Result<()> {
- let lua = Lua::new();
-
- // Direct conversion
- let f = lua
- .create_function(|_, ()| Ok::<_, Error>(()))?
- .into_owned();
- let f2 = (&f).into_lua(&lua)?;
- assert_eq!(f.to_ref(), *f2.as_function().unwrap());
-
- // Push into stack
- let table = lua.create_table()?;
- table.set("f", &f)?;
- assert_eq!(f.to_ref(), table.get::<_, Function>("f")?);
-
- Ok(())
-}
-
#[test]
fn test_thread_into_lua() -> Result<()> {
let lua = Lua::new();
@@ -162,36 +95,6 @@ fn test_thread_into_lua() -> Result<()> {
Ok(())
}
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[test]
-fn test_owned_thread_into_lua() -> Result<()> {
- let lua = Lua::new();
-
- // Direct conversion
- let f = lua.create_function(|_, ()| Ok::<_, Error>(()))?;
- let th = lua.create_thread(f)?.into_owned();
- let th2 = (&th).into_lua(&lua)?;
- assert_eq!(&th.to_ref(), th2.as_thread().unwrap());
-
- // Push into stack
- let table = lua.create_table()?;
- table.set("th", &th)?;
- assert_eq!(th.to_ref(), table.get::<_, Thread>("th")?);
-
- Ok(())
-}
-
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[test]
-fn test_owned_thread_from_lua() -> Result<()> {
- let lua = Lua::new();
-
- let th = lua.unpack::<mlua::OwnedThread>(Value::Thread(lua.current_thread()))?;
- assert_eq!(th.to_ref(), lua.current_thread());
-
- Ok(())
-}
-
#[test]
fn test_anyuserdata_into_lua() -> Result<()> {
let lua = Lua::new();
@@ -210,25 +113,6 @@ fn test_anyuserdata_into_lua() -> Result<()> {
Ok(())
}
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[test]
-fn test_owned_anyuserdata_into_lua() -> Result<()> {
- let lua = Lua::new();
-
- // Direct conversion
- let ud = lua.create_any_userdata(String::from("hello"))?.into_owned();
- let ud2 = (&ud).into_lua(&lua)?;
- assert_eq!(ud.to_ref(), *ud2.as_userdata().unwrap());
-
- // Push into stack
- let table = lua.create_table()?;
- table.set("ud", &ud)?;
- assert_eq!(ud.to_ref(), table.get::<_, AnyUserData>("ud")?);
- assert_eq!("hello", *table.get::<_, UserDataRef<String>>("ud")?);
-
- Ok(())
-}
-
#[test]
fn test_registry_value_into_lua() -> Result<()> {
let lua = Lua::new();
diff --git a/tests/function.rs b/tests/function.rs
index c95b012..c7596be 100644
--- a/tests/function.rs
+++ b/tests/function.rs
@@ -296,45 +296,3 @@ fn test_function_wrap() -> Result<()> {
Ok(())
}
-
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[test]
-fn test_owned_function() -> Result<()> {
- let lua = Lua::new();
-
- let f = lua
- .create_function(|_, ()| Ok("hello, world!"))?
- .into_owned();
- drop(lua);
-
- // We still should be able to call the function despite Lua is dropped
- let s = f.call::<_, String>(())?;
- assert_eq!(s.to_string_lossy(), "hello, world!");
-
- Ok(())
-}
-
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[test]
-fn test_owned_function_drop() -> Result<()> {
- let rc = std::sync::Arc::new(());
-
- {
- let lua = Lua::new();
-
- lua.set_app_data(rc.clone());
-
- let f1 = lua
- .create_function(|_, ()| Ok("hello, world!"))?
- .into_owned();
- let f2 =
- lua.create_function(move |_, ()| f1.to_ref().call::<_, std::string::String>(()))?;
- assert_eq!(f2.call::<_, String>(())?.to_string_lossy(), "hello, world!");
- }
-
- // Check that Lua is properly destroyed
- // It works because we collect garbage when Lua goes out of scope
- assert_eq!(std::sync::Arc::strong_count(&rc), 1);
-
- Ok(())
-}
diff --git a/tests/scope.rs b/tests/scope.rs.1
index b04b7b5..b04b7b5 100644
--- a/tests/scope.rs
+++ b/tests/scope.rs.1
diff --git a/tests/serde.rs b/tests/serde.rs
index 11c1d71..5dc4bd8 100644
--- a/tests/serde.rs
+++ b/tests/serde.rs
@@ -71,49 +71,49 @@ fn test_serialize() -> Result<(), Box<dyn StdError>> {
Ok(())
}
-#[test]
-fn test_serialize_in_scope() -> LuaResult<()> {
- #[derive(Serialize, Clone)]
- struct MyUserData(i64, String);
-
- impl UserData for MyUserData {}
-
- let lua = Lua::new();
- lua.scope(|scope| {
- let ud = scope.create_ser_userdata(MyUserData(-5, "test userdata".into()))?;
- assert_eq!(
- serde_json::to_value(&ud).unwrap(),
- serde_json::json!((-5, "test userdata"))
- );
- Ok(())
- })?;
-
- lua.scope(|scope| {
- let ud = scope.create_ser_userdata(MyUserData(-5, "test userdata".into()))?;
- lua.globals().set("ud", ud)
- })?;
- let val = lua.load("ud").eval::<Value>()?;
- match serde_json::to_value(&val) {
- Ok(v) => panic!("expected destructed error, got {}", v),
- Err(e) if e.to_string().contains("destructed") => {}
- Err(e) => panic!("expected destructed error, got {}", e),
- }
-
- struct MyUserDataRef<'a>(#[allow(unused)] &'a ());
-
- impl<'a> UserData for MyUserDataRef<'a> {}
-
- lua.scope(|scope| {
- let ud = scope.create_nonstatic_userdata(MyUserDataRef(&()))?;
- match serde_json::to_value(&ud) {
- Ok(v) => panic!("expected serialization error, got {}", v),
- Err(serde_json::Error { .. }) => {}
- };
- Ok(())
- })?;
-
- Ok(())
-}
+// #[test]
+// fn test_serialize_in_scope() -> LuaResult<()> {
+// #[derive(Serialize, Clone)]
+// struct MyUserData(i64, String);
+
+// impl UserData for MyUserData {}
+
+// let lua = Lua::new();
+// lua.scope(|scope| {
+// let ud = scope.create_ser_userdata(MyUserData(-5, "test userdata".into()))?;
+// assert_eq!(
+// serde_json::to_value(&ud).unwrap(),
+// serde_json::json!((-5, "test userdata"))
+// );
+// Ok(())
+// })?;
+
+// lua.scope(|scope| {
+// let ud = scope.create_ser_userdata(MyUserData(-5, "test userdata".into()))?;
+// lua.globals().set("ud", ud)
+// })?;
+// let val = lua.load("ud").eval::<Value>()?;
+// match serde_json::to_value(&val) {
+// Ok(v) => panic!("expected destructed error, got {}", v),
+// Err(e) if e.to_string().contains("destructed") => {}
+// Err(e) => panic!("expected destructed error, got {}", e),
+// }
+
+// struct MyUserDataRef<'a>(#[allow(unused)] &'a ());
+
+// impl<'a> UserData for MyUserDataRef<'a> {}
+
+// lua.scope(|scope| {
+// let ud = scope.create_nonstatic_userdata(MyUserDataRef(&()))?;
+// match serde_json::to_value(&ud) {
+// Ok(v) => panic!("expected serialization error, got {}", v),
+// Err(serde_json::Error { .. }) => {}
+// };
+// Ok(())
+// })?;
+
+// Ok(())
+// }
#[test]
fn test_serialize_any_userdata() -> Result<(), Box<dyn StdError>> {
diff --git a/tests/static.rs b/tests/static.rs
index 92164d7..7f6e028 100644
--- a/tests/static.rs
+++ b/tests/static.rs
@@ -7,7 +7,7 @@ fn test_static_lua() -> Result<()> {
let lua = Lua::new().into_static();
thread_local! {
- static TABLE: RefCell<Option<Table<'static>>> = RefCell::new(None);
+ static TABLE: RefCell<Option<Table>> = RefCell::new(None);
}
let f = lua.create_function(|_, table: Table| {
@@ -38,7 +38,7 @@ fn test_static_lua_coroutine() -> Result<()> {
let lua = Lua::new().into_static();
thread_local! {
- static TABLE: RefCell<Option<Table<'static>>> = RefCell::new(None);
+ static TABLE: RefCell<Option<Table>> = RefCell::new(None);
}
let f = lua.create_function(|_, table: Table| {
diff --git a/tests/string.rs b/tests/string.rs
index ad06c5f..289e3ea 100644
--- a/tests/string.rs
+++ b/tests/string.rs
@@ -111,22 +111,3 @@ fn test_string_pointer() -> Result<()> {
Ok(())
}
-
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[test]
-fn test_owned_string() -> Result<()> {
- let lua = Lua::new();
-
- let s = lua.create_string("hello, world!")?.into_owned();
- drop(lua);
-
- // Shortcuts
- assert_eq!(s.as_bytes(), b"hello, world!");
- assert_eq!(s.to_str()?, "hello, world!");
- assert_eq!(format!("{s:?}"), "\"hello, world!\"");
-
- // Access via reference
- assert_eq!(s.to_ref().to_string_lossy(), "hello, world!");
-
- Ok(())
-}
diff --git a/tests/table.rs b/tests/table.rs
index 04885fc..cdbb122 100644
--- a/tests/table.rs
+++ b/tests/table.rs
@@ -455,17 +455,3 @@ fn test_table_call() -> Result<()> {
Ok(())
}
-
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[test]
-fn test_owned_table() -> Result<()> {
- let lua = Lua::new();
-
- let table = lua.create_table()?.into_owned();
- drop(lua);
-
- table.to_ref().set("abc", 123)?;
- assert_eq!(table.to_ref().get::<_, i64>("abc")?, 123);
-
- Ok(())
-}
diff --git a/tests/thread.rs b/tests/thread.rs
index 2bc1988..81f14e0 100644
--- a/tests/thread.rs
+++ b/tests/thread.rs
@@ -231,34 +231,3 @@ fn test_thread_pointer() -> Result<()> {
Ok(())
}
-
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[test]
-fn test_owned_thread() -> Result<()> {
- let lua = Lua::new();
-
- let accumulate = lua
- .create_thread(
- lua.load(
- r#"
- function (sum)
- while true do
- sum = sum + coroutine.yield(sum)
- end
- end
- "#,
- )
- .eval::<Function>()?,
- )?
- .into_owned();
-
- for i in 0..4 {
- accumulate.resume::<_, ()>(i)?;
- }
- assert_eq!(accumulate.resume::<_, i64>(4)?, 10);
- assert_eq!(accumulate.status(), ThreadStatus::Resumable);
- assert!(accumulate.resume::<_, ()>("error").is_err());
- assert_eq!(accumulate.status(), ThreadStatus::Error);
-
- Ok(())
-}
diff --git a/tests/userdata.rs b/tests/userdata.rs
index 7d5b623..fd22ec3 100644
--- a/tests/userdata.rs
+++ b/tests/userdata.rs
@@ -47,7 +47,7 @@ fn test_methods() -> Result<()> {
struct MyUserData(i64);
impl UserData for MyUserData {
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_method("get_value", |_, data, ()| Ok(data.0));
methods.add_method_mut("set_value", |_, data, args| {
data.0 = args;
@@ -97,7 +97,7 @@ fn test_method_variadic() -> Result<()> {
struct MyUserData(i64);
impl UserData for MyUserData {
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_method("get", |_, data, ()| Ok(data.0));
methods.add_method_mut("add", |_, data, vals: Variadic<i64>| {
data.0 += vals.into_iter().sum::<i64>();
@@ -122,7 +122,7 @@ fn test_metamethods() -> Result<()> {
struct MyUserData(i64);
impl UserData for MyUserData {
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_method("get", |_, data, ()| Ok(data.0));
methods.add_meta_function(
MetaMethod::Add,
@@ -241,7 +241,7 @@ fn test_metamethod_close() -> Result<()> {
struct MyUserData(Arc<AtomicI64>);
impl UserData for MyUserData {
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_method("get", |_, data, ()| Ok(data.0.load(Ordering::Relaxed)));
methods.add_meta_method(MetaMethod::Close, |_, data, _err: Value| {
data.0.store(0, Ordering::Relaxed);
@@ -287,7 +287,7 @@ fn test_gc_userdata() -> Result<()> {
}
impl UserData for MyUserdata {
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_method("access", |_, this, ()| {
assert!(this.id == 123);
Ok(())
@@ -326,7 +326,7 @@ fn test_userdata_take() -> Result<()> {
struct MyUserdata(Arc<i64>);
impl UserData for MyUserdata {
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_method("num", |_, this, ()| Ok(*this.0))
}
}
@@ -461,7 +461,7 @@ fn test_functions() -> Result<()> {
struct MyUserData(i64);
impl UserData for MyUserData {
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_function("get_value", |_, ud: AnyUserData| {
Ok(ud.borrow::<MyUserData>()?.0)
});
@@ -515,7 +515,7 @@ fn test_fields() -> Result<()> {
struct MyUserData(i64);
impl UserData for MyUserData {
- fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
+ fn add_fields<'a, F: UserDataFields<'a, Self>>(fields: &mut F) {
fields.add_field("static", "constant");
fields.add_field_method_get("val", |_, data| Ok(data.0));
fields.add_field_method_set("val", |_, data, val| {
@@ -562,12 +562,12 @@ fn test_fields() -> Result<()> {
struct MyUserData2(i64);
impl UserData for MyUserData2 {
- fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
+ fn add_fields<'a, F: UserDataFields<'a, Self>>(fields: &mut F) {
fields.add_field("z", 0);
fields.add_field_method_get("x", |_, data| Ok(data.0));
}
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Index, |_, _, name: StdString| match &*name {
"y" => Ok(Some(-1)),
_ => Ok(None),
@@ -594,7 +594,7 @@ fn test_metatable() -> Result<()> {
struct MyUserData;
impl UserData for MyUserData {
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_function("my_type_name", |_, data: AnyUserData| {
let metatable = data.get_metatable()?;
metatable.get::<String>(MetaMethod::Type)
@@ -640,7 +640,7 @@ fn test_metatable() -> Result<()> {
struct MyUserData2;
impl UserData for MyUserData2 {
- fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
+ fn add_fields<'a, F: UserDataFields<'a, Self>>(fields: &mut F) {
fields.add_meta_field_with("__index", |_| Ok(1));
}
}
@@ -655,7 +655,7 @@ fn test_metatable() -> Result<()> {
struct MyUserData3;
impl UserData for MyUserData3 {
- fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
+ fn add_fields<'a, F: UserDataFields<'a, Self>>(fields: &mut F) {
fields.add_meta_field_with(MetaMethod::Type, |_| Ok("CustomName"));
}
}
@@ -671,11 +671,12 @@ fn test_metatable() -> Result<()> {
}
#[test]
+#[ignore = "this functionality is deprecated"]
fn test_userdata_wrapped() -> Result<()> {
struct MyUserData(i64);
impl UserData for MyUserData {
- fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
+ fn add_fields<'a, F: UserDataFields<'a, Self>>(fields: &mut F) {
fields.add_field("static", "constant");
fields.add_field_method_get("data", |_, this| Ok(this.0));
fields.add_field_method_set("data", |_, this, val| {
@@ -794,12 +795,12 @@ fn test_userdata_proxy() -> Result<()> {
struct MyUserData(i64);
impl UserData for MyUserData {
- fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
+ fn add_fields<'a, F: UserDataFields<'a, Self>>(fields: &mut F) {
fields.add_field("static_field", 123);
fields.add_field_method_get("n", |_, this| Ok(this.0));
}
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_function("new", |_, n| Ok(Self(n)));
methods.add_method("plus", |_, this, n: i64| Ok(this.0 + n));
@@ -888,7 +889,7 @@ fn test_userdata_ext() -> Result<()> {
struct MyUserData(u32);
impl UserData for MyUserData {
- fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
+ fn add_fields<'a, F: UserDataFields<'a, Self>>(fields: &mut F) {
fields.add_field_method_get("n", |_, this| Ok(this.0));
fields.add_field_method_set("n", |_, this, val| {
this.0 = val;
@@ -896,7 +897,7 @@ fn test_userdata_ext() -> Result<()> {
});
}
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Call, |_, _this, ()| Ok("called"));
methods.add_method_mut("add", |_, this, x: u32| {
this.0 += x;
@@ -929,7 +930,7 @@ fn test_userdata_method_errors() -> Result<()> {
struct MyUserData(i64);
impl UserData for MyUserData {
- fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
methods.add_method("get_value", |_, data, ()| Ok(data.0));
}
}
@@ -967,25 +968,6 @@ fn test_userdata_pointer() -> Result<()> {
Ok(())
}
-#[cfg(all(feature = "unstable", not(feature = "send")))]
-#[test]
-fn test_owned_userdata() -> Result<()> {
- let lua = Lua::new();
-
- let ud = lua.create_any_userdata("abc")?.into_owned();
- drop(lua);
-
- assert_eq!(*ud.borrow::<&str>()?, "abc");
- *ud.borrow_mut()? = "cba";
- assert!(matches!(
- ud.borrow::<i64>(),
- Err(Error::UserDataTypeMismatch)
- ));
- assert_eq!(ud.take::<&str>()?, "cba");
-
- Ok(())
-}
-
#[cfg(feature = "macros")]
#[test]
fn test_userdata_derive() -> Result<()> {