Compare commits
7 commits
Author | SHA1 | Date | |
---|---|---|---|
06929469d8 | |||
79eb64d855 | |||
da15359368 | |||
cd0a1d1e7c | |||
a83ee546ba | |||
d30845e1ed | |||
8ba8fa0822 |
|
@ -42,7 +42,7 @@ macros = ["mlua_derive/macros"]
|
|||
|
||||
[dependencies]
|
||||
mlua_derive = { version = "=0.8.0", optional = true, path = "mlua_derive" }
|
||||
bstr = { version = "0.2", features = ["std"], default_features = false }
|
||||
bstr = { version = "1.0", features = ["std"], default_features = false }
|
||||
once_cell = { version = "1.0" }
|
||||
num-traits = { version = "0.2.14" }
|
||||
rustc-hash = "1.0"
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::future::Future;
|
||||
use std::net::SocketAddr;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use hyper::server::conn::AddrStream;
|
||||
|
@ -9,7 +8,8 @@ use hyper::service::Service;
|
|||
use hyper::{Body, Request, Response, Server};
|
||||
|
||||
use mlua::{
|
||||
chunk, Error as LuaError, Function, Lua, String as LuaString, Table, UserData, UserDataMethods,
|
||||
chunk, Error as LuaError, Function, Lua, OwnedFunction, String as LuaString, Table, UserData,
|
||||
UserDataMethods,
|
||||
};
|
||||
|
||||
struct LuaRequest(SocketAddr, Request<Body>);
|
||||
|
@ -21,7 +21,10 @@ impl UserData for LuaRequest {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Svc(Rc<Lua>, SocketAddr);
|
||||
#[derive(Clone)]
|
||||
struct Handler(OwnedFunction);
|
||||
|
||||
pub struct Svc(Handler, SocketAddr);
|
||||
|
||||
impl Service<Request<Body>> for Svc {
|
||||
type Response = Response<Body>;
|
||||
|
@ -34,11 +37,10 @@ impl Service<Request<Body>> for Svc {
|
|||
|
||||
fn call(&mut self, req: Request<Body>) -> Self::Future {
|
||||
// If handler returns an error then generate 5xx response
|
||||
let lua = self.0.clone();
|
||||
let handler = self.0.clone();
|
||||
let lua_req = LuaRequest(self.1, req);
|
||||
Box::pin(async move {
|
||||
let handler: Function = lua.named_registry_value("http_handler")?;
|
||||
match handler.call_async::<_, Table>(lua_req).await {
|
||||
match handler.0.to_ref().call_async::<_, Table>(lua_req).await {
|
||||
Ok(lua_resp) => {
|
||||
let status = lua_resp.get::<_, Option<u16>>("status")?.unwrap_or(200);
|
||||
let mut resp = Response::builder().status(status);
|
||||
|
@ -72,10 +74,10 @@ impl Service<Request<Body>> for Svc {
|
|||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() {
|
||||
let lua = Rc::new(Lua::new());
|
||||
let lua = Lua::new();
|
||||
|
||||
// Create Lua handler function
|
||||
let handler: Function = lua
|
||||
let handler_fn: Function = lua
|
||||
.load(chunk! {
|
||||
function(req)
|
||||
return {
|
||||
|
@ -91,12 +93,10 @@ async fn main() {
|
|||
.eval()
|
||||
.expect("cannot create Lua handler");
|
||||
|
||||
// Store it in the Registry
|
||||
lua.set_named_registry_value("http_handler", handler)
|
||||
.expect("cannot store Lua handler");
|
||||
|
||||
let addr = ([127, 0, 0, 1], 3000).into();
|
||||
let server = Server::bind(&addr).executor(LocalExec).serve(MakeSvc(lua));
|
||||
let server = Server::bind(&addr)
|
||||
.executor(LocalExec)
|
||||
.serve(MakeSvc(Handler(handler_fn.into_owned())));
|
||||
|
||||
println!("Listening on http://{}", addr);
|
||||
|
||||
|
@ -105,7 +105,7 @@ async fn main() {
|
|||
local.run_until(server).await.expect("cannot run server")
|
||||
}
|
||||
|
||||
struct MakeSvc(Rc<Lua>);
|
||||
struct MakeSvc(Handler);
|
||||
|
||||
impl Service<&AddrStream> for MakeSvc {
|
||||
type Response = Svc;
|
||||
|
@ -117,9 +117,9 @@ impl Service<&AddrStream> for MakeSvc {
|
|||
}
|
||||
|
||||
fn call(&mut self, stream: &AddrStream) -> Self::Future {
|
||||
let lua = self.0.clone();
|
||||
let handler = self.0.clone();
|
||||
let remote_addr = stream.remote_addr();
|
||||
Box::pin(async move { Ok(Svc(lua, remote_addr)) })
|
||||
Box::pin(async move { Ok(Svc(handler, remote_addr)) })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,13 +11,13 @@ use bstr::{BStr, BString};
|
|||
use num_traits::cast;
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
use crate::function::Function;
|
||||
use crate::function::{Function, OwnedFunction};
|
||||
use crate::lua::Lua;
|
||||
use crate::string::String;
|
||||
use crate::table::Table;
|
||||
use crate::thread::Thread;
|
||||
use crate::string::{OwnedString, String};
|
||||
use crate::table::{OwnedTable, Table};
|
||||
use crate::thread::{OwnedThread, Thread};
|
||||
use crate::types::{LightUserData, MaybeSend};
|
||||
use crate::userdata::{AnyUserData, UserData};
|
||||
use crate::userdata::{AnyUserData, OwnedAnyUserData, UserData};
|
||||
use crate::value::{FromLua, Nil, ToLua, Value};
|
||||
|
||||
impl<'lua> ToLua<'lua> for Value<'lua> {
|
||||
|
@ -54,6 +54,20 @@ impl<'lua> FromLua<'lua> for String<'lua> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'lua> ToLua<'lua> for OwnedString {
|
||||
#[inline]
|
||||
fn to_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
Ok(Value::String(String(lua.adopt_owned_ref(self.0))))
|
||||
}
|
||||
}
|
||||
|
||||
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<'lua> ToLua<'lua> for Table<'lua> {
|
||||
#[inline]
|
||||
fn to_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
|
@ -75,6 +89,20 @@ impl<'lua> FromLua<'lua> for Table<'lua> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'lua> ToLua<'lua> for OwnedTable {
|
||||
#[inline]
|
||||
fn to_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
Ok(Value::Table(Table(lua.adopt_owned_ref(self.0))))
|
||||
}
|
||||
}
|
||||
|
||||
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<'lua> ToLua<'lua> for Function<'lua> {
|
||||
#[inline]
|
||||
fn to_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
|
@ -96,6 +124,20 @@ impl<'lua> FromLua<'lua> for Function<'lua> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'lua> ToLua<'lua> for OwnedFunction {
|
||||
#[inline]
|
||||
fn to_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
Ok(Value::Function(Function(lua.adopt_owned_ref(self.0))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> FromLua<'lua> for OwnedFunction {
|
||||
#[inline]
|
||||
fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<OwnedFunction> {
|
||||
Function::from_lua(value, lua).map(|s| s.into_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> ToLua<'lua> for Thread<'lua> {
|
||||
#[inline]
|
||||
fn to_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
|
@ -117,6 +159,20 @@ impl<'lua> FromLua<'lua> for Thread<'lua> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'lua> ToLua<'lua> for OwnedThread {
|
||||
#[inline]
|
||||
fn to_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
Ok(Value::Thread(Thread(lua.adopt_owned_ref(self.0))))
|
||||
}
|
||||
}
|
||||
|
||||
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<'lua> ToLua<'lua> for AnyUserData<'lua> {
|
||||
#[inline]
|
||||
fn to_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
|
@ -138,6 +194,20 @@ impl<'lua> FromLua<'lua> for AnyUserData<'lua> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'lua> ToLua<'lua> for OwnedAnyUserData {
|
||||
#[inline]
|
||||
fn to_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
Ok(Value::UserData(AnyUserData(lua.adopt_owned_ref(self.0))))
|
||||
}
|
||||
}
|
||||
|
||||
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<'lua, T: 'static + MaybeSend + UserData> ToLua<'lua> for T {
|
||||
#[inline]
|
||||
fn to_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
|
@ -145,6 +215,7 @@ impl<'lua, T: 'static + MaybeSend + UserData> ToLua<'lua> for T {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Remove
|
||||
impl<'lua, T: 'static + UserData + Clone> FromLua<'lua> for T {
|
||||
#[inline]
|
||||
fn from_lua(value: Value<'lua>, _: &'lua Lua) -> Result<T> {
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::slice;
|
|||
|
||||
use crate::error::{Error, Result};
|
||||
use crate::ffi;
|
||||
use crate::types::LuaRef;
|
||||
use crate::types::{LuaOwnedRef, LuaRef};
|
||||
use crate::util::{
|
||||
assert_stack, check_stack, error_traceback, pop_error, ptr_to_cstr_bytes, StackGuard,
|
||||
};
|
||||
|
@ -18,6 +18,17 @@ use {futures_core::future::LocalBoxFuture, futures_util::future};
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct Function<'lua>(pub(crate) LuaRef<'lua>);
|
||||
|
||||
/// Owned handle to an internal Lua function.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OwnedFunction(pub(crate) LuaOwnedRef);
|
||||
|
||||
impl OwnedFunction {
|
||||
/// Get borrowed handle to the underlying Lua function.
|
||||
pub const fn to_ref(&self) -> Function {
|
||||
Function(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FunctionInfo {
|
||||
pub name: Option<Vec<u8>>,
|
||||
|
@ -373,6 +384,12 @@ impl<'lua> Function<'lua> {
|
|||
ffi::lua_getcoverage(lua.state, -1, func_ptr, callback::<F>);
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert this handle to owned version.
|
||||
#[inline]
|
||||
pub fn into_owned(self) -> OwnedFunction {
|
||||
OwnedFunction(self.0.into_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> PartialEq for Function<'lua> {
|
||||
|
|
|
@ -108,15 +108,15 @@ pub use crate::{ffi::lua_CFunction, ffi::lua_State};
|
|||
|
||||
pub use crate::chunk::{AsChunk, Chunk, ChunkMode};
|
||||
pub use crate::error::{Error, ExternalError, ExternalResult, Result};
|
||||
pub use crate::function::{Function, FunctionInfo};
|
||||
pub use crate::function::{Function, FunctionInfo, OwnedFunction};
|
||||
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::stdlib::StdLib;
|
||||
pub use crate::string::String;
|
||||
pub use crate::table::{Table, TableExt, TablePairs, TableSequence};
|
||||
pub use crate::thread::{Thread, ThreadStatus};
|
||||
pub use crate::string::{OwnedString, String};
|
||||
pub use crate::table::{OwnedTable, Table, TableExt, TablePairs, TableSequence};
|
||||
pub use crate::thread::{OwnedThread, Thread, ThreadStatus};
|
||||
pub use crate::types::{Integer, LightUserData, Number, RegistryKey};
|
||||
pub use crate::userdata::{
|
||||
AnyUserData, MetaMethod, UserData, UserDataFields, UserDataMetatable, UserDataMethods,
|
||||
|
|
75
src/lua.rs
75
src/lua.rs
|
@ -25,8 +25,8 @@ use crate::string::String;
|
|||
use crate::table::Table;
|
||||
use crate::thread::Thread;
|
||||
use crate::types::{
|
||||
Callback, CallbackUpvalue, DestructedUserdata, Integer, LightUserData, LuaRef, MaybeSend,
|
||||
Number, RegistryKey,
|
||||
Callback, CallbackUpvalue, DestructedUserdata, Integer, LightUserData, LuaOwnedRef, LuaRef,
|
||||
MaybeSend, Number, RegistryKey,
|
||||
};
|
||||
use crate::userdata::{AnyUserData, UserData, UserDataCell};
|
||||
use crate::userdata_impl::{StaticUserDataFields, StaticUserDataMethods, UserDataProxy};
|
||||
|
@ -711,13 +711,8 @@ 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, S, T>(
|
||||
&'lua self,
|
||||
modname: &S,
|
||||
func: Function<'lua>,
|
||||
) -> Result<T>
|
||||
pub fn load_from_function<'lua, T>(&'lua self, modname: &str, func: Function<'lua>) -> Result<T>
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
T: FromLua<'lua>,
|
||||
{
|
||||
let loaded = unsafe {
|
||||
|
@ -751,10 +746,7 @@ impl Lua {
|
|||
/// unloaded only by closing Lua state.
|
||||
///
|
||||
/// [`package.loaded`]: https://www.lua.org/manual/5.4/manual.html#pdf-package.loaded
|
||||
pub fn unload<S>(&self, modname: &S) -> Result<()>
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
{
|
||||
pub fn unload(&self, modname: &str) -> Result<()> {
|
||||
let loaded = unsafe {
|
||||
let _sg = StackGuard::new(self.state);
|
||||
check_stack(self.state, 2)?;
|
||||
|
@ -1429,10 +1421,7 @@ impl Lua {
|
|||
/// Create and return an interned Lua string. Lua strings can be arbitrary [u8] data including
|
||||
/// embedded nulls, so in addition to `&str` and `&String`, you can also pass plain `&[u8]`
|
||||
/// here.
|
||||
pub fn create_string<S>(&self, s: &S) -> Result<String>
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
{
|
||||
pub fn create_string(&self, s: impl AsRef<[u8]>) -> Result<String> {
|
||||
unsafe {
|
||||
if self.unlikely_memory_error() {
|
||||
push_string(self.ref_thread(), s.as_ref(), false)?;
|
||||
|
@ -1721,7 +1710,7 @@ impl Lua {
|
|||
ffi::lua_replace(thread_state, ffi::LUA_GLOBALSINDEX);
|
||||
}
|
||||
|
||||
return Ok(Thread(LuaRef { lua: self, index }));
|
||||
return Ok(Thread(LuaRef::new(self, index)));
|
||||
}
|
||||
};
|
||||
self.create_thread(func)
|
||||
|
@ -1750,7 +1739,7 @@ impl Lua {
|
|||
#[cfg(feature = "luau")]
|
||||
ffi::lua_resetthread(thread_state);
|
||||
extra.recycled_thread_cache.push(thread.0.index);
|
||||
thread.0.index = 0;
|
||||
thread.0.drop = false;
|
||||
return true;
|
||||
}
|
||||
false
|
||||
|
@ -1999,9 +1988,8 @@ 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, S, T>(&'lua self, name: &S, t: T) -> Result<()>
|
||||
pub fn set_named_registry_value<'lua, T>(&'lua self, name: &str, t: T) -> Result<()>
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
T: ToLua<'lua>,
|
||||
{
|
||||
let t = t.to_lua(self)?;
|
||||
|
@ -2020,9 +2008,8 @@ 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, S, T>(&'lua self, name: &S) -> Result<T>
|
||||
pub fn named_registry_value<'lua, T>(&'lua self, name: &str) -> Result<T>
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
T: FromLua<'lua>,
|
||||
{
|
||||
let value = unsafe {
|
||||
|
@ -2030,7 +2017,7 @@ impl Lua {
|
|||
check_stack(self.state, 3)?;
|
||||
|
||||
let protect = !self.unlikely_memory_error();
|
||||
push_string(self.state, name.as_ref(), protect)?;
|
||||
push_string(self.state, name.as_bytes(), protect)?;
|
||||
ffi::lua_rawget(self.state, ffi::LUA_REGISTRYINDEX);
|
||||
|
||||
self.pop_value()
|
||||
|
@ -2043,10 +2030,7 @@ impl Lua {
|
|||
/// Equivalent to calling [`set_named_registry_value`] with a value of Nil.
|
||||
///
|
||||
/// [`set_named_registry_value`]: #method.set_named_registry_value
|
||||
pub fn unset_named_registry_value<S>(&self, name: &S) -> Result<()>
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
{
|
||||
pub fn unset_named_registry_value(&self, name: &str) -> Result<()> {
|
||||
self.set_named_registry_value(name, Nil)
|
||||
}
|
||||
|
||||
|
@ -2440,7 +2424,7 @@ impl Lua {
|
|||
// Pushes a LuaRef value onto the stack, uses 1 stack space, does not call checkstack
|
||||
pub(crate) unsafe fn push_ref(&self, lref: &LuaRef) {
|
||||
assert!(
|
||||
Arc::ptr_eq(&lref.lua.extra, &self.extra),
|
||||
Arc::ptr_eq(&lref.lua.0, &self.0),
|
||||
"Lua instance passed Value created from a different main Lua state"
|
||||
);
|
||||
let extra = &*self.extra.get();
|
||||
|
@ -2460,14 +2444,14 @@ impl Lua {
|
|||
let extra = &mut *self.extra.get();
|
||||
ffi::lua_xmove(self.state, extra.ref_thread, 1);
|
||||
let index = ref_stack_pop(extra);
|
||||
LuaRef { lua: self, index }
|
||||
LuaRef::new(self, index)
|
||||
}
|
||||
|
||||
// Same as `pop_ref` but assumes the value is already on the reference thread
|
||||
pub(crate) unsafe fn pop_ref_thread(&self) -> LuaRef {
|
||||
let extra = &mut *self.extra.get();
|
||||
let index = ref_stack_pop(extra);
|
||||
LuaRef { lua: self, index }
|
||||
LuaRef::new(self, index)
|
||||
}
|
||||
|
||||
pub(crate) fn clone_ref<'lua>(&'lua self, lref: &LuaRef<'lua>) -> LuaRef<'lua> {
|
||||
|
@ -2475,7 +2459,7 @@ impl Lua {
|
|||
let extra = &mut *self.extra.get();
|
||||
ffi::lua_pushvalue(extra.ref_thread, lref.index);
|
||||
let index = ref_stack_pop(extra);
|
||||
LuaRef { lua: self, index }
|
||||
LuaRef::new(self, index)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2488,6 +2472,29 @@ impl Lua {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn make_owned_ref(&self, lref: LuaRef) -> LuaOwnedRef {
|
||||
assert!(lref.drop, "Cannot make owned non-drop reference");
|
||||
let owned_ref = LuaOwnedRef {
|
||||
lua: Lua(self.0.clone()),
|
||||
index: lref.index,
|
||||
};
|
||||
mem::forget(lref);
|
||||
owned_ref
|
||||
}
|
||||
|
||||
pub(crate) fn adopt_owned_ref(&self, loref: LuaOwnedRef) -> LuaRef {
|
||||
assert!(
|
||||
Arc::ptr_eq(&loref.lua.0, &self.0),
|
||||
"Lua instance passed Value created from a different main Lua state"
|
||||
);
|
||||
let index = loref.index;
|
||||
unsafe {
|
||||
ptr::read(&loref.lua);
|
||||
mem::forget(loref);
|
||||
}
|
||||
LuaRef::new(self, index)
|
||||
}
|
||||
|
||||
unsafe fn push_userdata_metatable<T: 'static + UserData>(&self) -> Result<()> {
|
||||
let extra = &mut *self.extra.get();
|
||||
|
||||
|
@ -3170,13 +3177,13 @@ where
|
|||
// Uses 3 stack spaces
|
||||
unsafe fn load_from_std_lib(state: *mut ffi::lua_State, libs: StdLib) -> Result<()> {
|
||||
#[inline(always)]
|
||||
pub unsafe fn requiref<S: AsRef<[u8]> + ?Sized>(
|
||||
pub unsafe fn requiref(
|
||||
state: *mut ffi::lua_State,
|
||||
modname: &S,
|
||||
modname: &str,
|
||||
openf: ffi::lua_CFunction,
|
||||
glb: c_int,
|
||||
) -> Result<()> {
|
||||
let modname = mlua_expect!(CString::new(modname.as_ref()), "modname contains nil byte");
|
||||
let modname = mlua_expect!(CString::new(modname), "modname contains nil byte");
|
||||
protect_lua!(state, 0, 1, |state| {
|
||||
ffi::luaL_requiref(state, modname.as_ptr() as *const c_char, openf, glb)
|
||||
})
|
||||
|
|
73
src/scope.rs
73
src/scope.rs
|
@ -606,7 +606,7 @@ enum NonStaticMethod<'lua, T> {
|
|||
}
|
||||
|
||||
struct NonStaticUserDataMethods<'lua, T: UserData> {
|
||||
methods: Vec<(Vec<u8>, NonStaticMethod<'lua, T>)>,
|
||||
methods: Vec<(String, NonStaticMethod<'lua, T>)>,
|
||||
meta_methods: Vec<(MetaMethod, NonStaticMethod<'lua, T>)>,
|
||||
}
|
||||
|
||||
|
@ -620,30 +620,28 @@ impl<'lua, T: UserData> Default for NonStaticUserDataMethods<'lua, T> {
|
|||
}
|
||||
|
||||
impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'lua, T> {
|
||||
fn add_method<S, A, R, M>(&mut self, name: &S, method: M)
|
||||
fn add_method<A, R, M>(&mut self, name: &str, method: M)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>,
|
||||
{
|
||||
self.methods.push((
|
||||
name.as_ref().to_vec(),
|
||||
name.into(),
|
||||
NonStaticMethod::Method(Box::new(move |lua, ud, args| {
|
||||
method(lua, ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
})),
|
||||
));
|
||||
}
|
||||
|
||||
fn add_method_mut<S, A, R, M>(&mut self, name: &S, mut method: M)
|
||||
fn add_method_mut<A, R, M>(&mut self, name: &str, mut method: M)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
|
||||
{
|
||||
self.methods.push((
|
||||
name.as_ref().to_vec(),
|
||||
name.into(),
|
||||
NonStaticMethod::MethodMut(Box::new(move |lua, ud, args| {
|
||||
method(lua, ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
})),
|
||||
|
@ -651,10 +649,9 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'l
|
|||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
fn add_async_method<S, A, R, M, MR>(&mut self, _name: &S, _method: M)
|
||||
fn add_async_method<A, R, M, MR>(&mut self, _name: &str, _method: M)
|
||||
where
|
||||
T: Clone,
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
|
||||
|
@ -665,30 +662,28 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'l
|
|||
mlua_panic!("asynchronous methods are not supported for non-static userdata")
|
||||
}
|
||||
|
||||
fn add_function<S, A, R, F>(&mut self, name: &S, function: F)
|
||||
fn add_function<A, R, F>(&mut self, name: &str, function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
self.methods.push((
|
||||
name.as_ref().to_vec(),
|
||||
name.into(),
|
||||
NonStaticMethod::Function(Box::new(move |lua, args| {
|
||||
function(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
})),
|
||||
));
|
||||
}
|
||||
|
||||
fn add_function_mut<S, A, R, F>(&mut self, name: &S, mut function: F)
|
||||
fn add_function_mut<A, R, F>(&mut self, name: &str, mut function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
self.methods.push((
|
||||
name.as_ref().to_vec(),
|
||||
name.into(),
|
||||
NonStaticMethod::FunctionMut(Box::new(move |lua, args| {
|
||||
function(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
})),
|
||||
|
@ -696,9 +691,8 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'l
|
|||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
fn add_async_function<S, A, R, F, FR>(&mut self, _name: &S, _function: F)
|
||||
fn add_async_function<A, R, F, FR>(&mut self, _name: &str, _function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
|
||||
|
@ -709,9 +703,8 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'l
|
|||
mlua_panic!("asynchronous functions are not supported for non-static userdata")
|
||||
}
|
||||
|
||||
fn add_meta_method<S, A, R, M>(&mut self, meta: S, method: M)
|
||||
fn add_meta_method<A, R, M>(&mut self, meta: impl Into<MetaMethod>, method: M)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>,
|
||||
|
@ -724,9 +717,8 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'l
|
|||
));
|
||||
}
|
||||
|
||||
fn add_meta_method_mut<S, A, R, M>(&mut self, meta: S, mut method: M)
|
||||
fn add_meta_method_mut<A, R, M>(&mut self, meta: impl Into<MetaMethod>, mut method: M)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
|
||||
|
@ -740,10 +732,9 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'l
|
|||
}
|
||||
|
||||
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
|
||||
fn add_async_meta_method<S, A, R, M, MR>(&mut self, _meta: S, _method: M)
|
||||
fn add_async_meta_method<A, R, M, MR>(&mut self, _meta: impl Into<MetaMethod>, _method: M)
|
||||
where
|
||||
T: Clone,
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
|
||||
|
@ -754,9 +745,8 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'l
|
|||
mlua_panic!("asynchronous meta methods are not supported for non-static userdata")
|
||||
}
|
||||
|
||||
fn add_meta_function<S, A, R, F>(&mut self, meta: S, function: F)
|
||||
fn add_meta_function<A, R, F>(&mut self, meta: impl Into<MetaMethod>, function: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>,
|
||||
|
@ -769,9 +759,8 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'l
|
|||
));
|
||||
}
|
||||
|
||||
fn add_meta_function_mut<S, A, R, F>(&mut self, meta: S, mut function: F)
|
||||
fn add_meta_function_mut<A, R, F>(&mut self, meta: impl Into<MetaMethod>, mut function: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>,
|
||||
|
@ -785,9 +774,8 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'l
|
|||
}
|
||||
|
||||
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
|
||||
fn add_async_meta_function<S, A, R, F, FR>(&mut self, _meta: S, _function: F)
|
||||
fn add_async_meta_function<A, R, F, FR>(&mut self, _meta: impl Into<MetaMethod>, _function: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
|
||||
|
@ -800,8 +788,8 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'l
|
|||
}
|
||||
|
||||
struct NonStaticUserDataFields<'lua, T: UserData> {
|
||||
field_getters: Vec<(Vec<u8>, NonStaticMethod<'lua, T>)>,
|
||||
field_setters: Vec<(Vec<u8>, NonStaticMethod<'lua, T>)>,
|
||||
field_getters: Vec<(String, NonStaticMethod<'lua, T>)>,
|
||||
field_setters: Vec<(String, NonStaticMethod<'lua, T>)>,
|
||||
#[allow(clippy::type_complexity)]
|
||||
meta_fields: Vec<(MetaMethod, Box<dyn Fn(&'lua Lua) -> Result<Value<'lua>>>)>,
|
||||
}
|
||||
|
@ -817,56 +805,52 @@ impl<'lua, T: UserData> Default for NonStaticUserDataFields<'lua, T> {
|
|||
}
|
||||
|
||||
impl<'lua, T: UserData> UserDataFields<'lua, T> for NonStaticUserDataFields<'lua, T> {
|
||||
fn add_field_method_get<S, R, M>(&mut self, name: &S, method: M)
|
||||
fn add_field_method_get<R, M>(&mut self, name: &str, method: M)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
R: ToLua<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T) -> Result<R>,
|
||||
{
|
||||
self.field_getters.push((
|
||||
name.as_ref().to_vec(),
|
||||
name.into(),
|
||||
NonStaticMethod::Method(Box::new(move |lua, ud, _| {
|
||||
method(lua, ud)?.to_lua_multi(lua)
|
||||
})),
|
||||
));
|
||||
}
|
||||
|
||||
fn add_field_method_set<S, A, M>(&mut self, name: &S, mut method: M)
|
||||
fn add_field_method_set<A, M>(&mut self, name: &str, mut method: M)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLua<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<()>,
|
||||
{
|
||||
self.field_setters.push((
|
||||
name.as_ref().to_vec(),
|
||||
name.into(),
|
||||
NonStaticMethod::MethodMut(Box::new(move |lua, ud, args| {
|
||||
method(lua, ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
})),
|
||||
));
|
||||
}
|
||||
|
||||
fn add_field_function_get<S, R, F>(&mut self, name: &S, function: F)
|
||||
fn add_field_function_get<R, F>(&mut self, name: &str, function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
R: ToLua<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>) -> Result<R>,
|
||||
{
|
||||
self.field_getters.push((
|
||||
name.as_ref().to_vec(),
|
||||
name.into(),
|
||||
NonStaticMethod::Function(Box::new(move |lua, args| {
|
||||
function(lua, AnyUserData::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
})),
|
||||
));
|
||||
}
|
||||
|
||||
fn add_field_function_set<S, A, F>(&mut self, name: &S, mut function: F)
|
||||
fn add_field_function_set<A, F>(&mut self, name: &str, mut function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLua<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, AnyUserData<'lua>, A) -> Result<()>,
|
||||
{
|
||||
self.field_setters.push((
|
||||
name.as_ref().to_vec(),
|
||||
name.into(),
|
||||
NonStaticMethod::FunctionMut(Box::new(move |lua, args| {
|
||||
let (ud, val) = <_>::from_lua_multi(args, lua)?;
|
||||
function(lua, ud, val)?.to_lua_multi(lua)
|
||||
|
@ -874,9 +858,8 @@ impl<'lua, T: UserData> UserDataFields<'lua, T> for NonStaticUserDataFields<'lua
|
|||
));
|
||||
}
|
||||
|
||||
fn add_meta_field_with<S, R, F>(&mut self, meta: S, f: F)
|
||||
fn add_meta_field_with<R, F>(&mut self, meta: impl Into<MetaMethod>, f: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua) -> Result<R>,
|
||||
R: ToLua<'lua>,
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@ use {
|
|||
|
||||
use crate::error::{Error, Result};
|
||||
use crate::ffi;
|
||||
use crate::types::LuaRef;
|
||||
use crate::types::{LuaOwnedRef, LuaRef};
|
||||
|
||||
/// Handle to an internal Lua string.
|
||||
///
|
||||
|
@ -20,6 +20,17 @@ use crate::types::LuaRef;
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct String<'lua>(pub(crate) LuaRef<'lua>);
|
||||
|
||||
/// Owned handle to an internal Lua string.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OwnedString(pub(crate) LuaOwnedRef);
|
||||
|
||||
impl OwnedString {
|
||||
/// Get borrowed handle to the underlying Lua string.
|
||||
pub const fn to_ref(&self) -> String {
|
||||
String(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> String<'lua> {
|
||||
/// Get a `&str` slice if the Lua string is valid UTF-8.
|
||||
///
|
||||
|
@ -122,6 +133,12 @@ impl<'lua> String<'lua> {
|
|||
let ref_thread = self.0.lua.ref_thread();
|
||||
unsafe { ffi::lua_topointer(ref_thread, self.0.index) }
|
||||
}
|
||||
|
||||
/// Convert this handle to owned version.
|
||||
#[inline]
|
||||
pub fn into_owned(self) -> OwnedString {
|
||||
OwnedString(self.0.into_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> AsRef<[u8]> for String<'lua> {
|
||||
|
|
19
src/table.rs
19
src/table.rs
|
@ -11,7 +11,7 @@ use {
|
|||
use crate::error::{Error, Result};
|
||||
use crate::ffi;
|
||||
use crate::function::Function;
|
||||
use crate::types::{Integer, LuaRef};
|
||||
use crate::types::{Integer, LuaOwnedRef, LuaRef};
|
||||
use crate::util::{assert_stack, check_stack, StackGuard};
|
||||
use crate::value::{FromLua, FromLuaMulti, Nil, ToLua, ToLuaMulti, Value};
|
||||
|
||||
|
@ -22,6 +22,17 @@ use {futures_core::future::LocalBoxFuture, futures_util::future};
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct Table<'lua>(pub(crate) LuaRef<'lua>);
|
||||
|
||||
/// Owned handle to an internal Lua table.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OwnedTable(pub(crate) LuaOwnedRef);
|
||||
|
||||
impl OwnedTable {
|
||||
/// Get borrowed handle to the underlying Lua table.
|
||||
pub const fn to_ref(&self) -> Table {
|
||||
Table(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
impl<'lua> Table<'lua> {
|
||||
/// Sets a key-value pair in the table.
|
||||
|
@ -512,6 +523,12 @@ impl<'lua> Table<'lua> {
|
|||
unsafe { ffi::lua_topointer(ref_thread, self.0.index) }
|
||||
}
|
||||
|
||||
/// Convert this handle to owned version.
|
||||
#[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.
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::os::raw::c_int;
|
|||
|
||||
use crate::error::{Error, Result};
|
||||
use crate::ffi;
|
||||
use crate::types::LuaRef;
|
||||
use crate::types::{LuaOwnedRef, LuaRef};
|
||||
use crate::util::{check_stack, error_traceback_thread, pop_error, StackGuard};
|
||||
use crate::value::{FromLuaMulti, ToLuaMulti};
|
||||
|
||||
|
@ -48,6 +48,17 @@ pub enum ThreadStatus {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct Thread<'lua>(pub(crate) LuaRef<'lua>);
|
||||
|
||||
/// Owned handle to an internal Lua thread.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OwnedThread(pub(crate) LuaOwnedRef);
|
||||
|
||||
impl OwnedThread {
|
||||
/// Get borrowed handle to the underlying Lua thread.
|
||||
pub const fn to_ref(&self) -> Thread {
|
||||
Thread(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
/// Thread (coroutine) representation as an async [`Future`] or [`Stream`].
|
||||
///
|
||||
/// Requires `feature = "async"`
|
||||
|
@ -333,6 +344,12 @@ impl<'lua> Thread<'lua> {
|
|||
protect_lua!(lua.state, 0, 0, |_| ffi::luaL_sandboxthread(thread))
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert this handle to owned version.
|
||||
#[inline]
|
||||
pub fn into_owned(self) -> OwnedThread {
|
||||
OwnedThread(self.0.into_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> PartialEq for Thread<'lua> {
|
||||
|
|
54
src/types.rs
54
src/types.rs
|
@ -180,6 +180,21 @@ impl RegistryKey {
|
|||
pub(crate) struct LuaRef<'lua> {
|
||||
pub(crate) lua: &'lua Lua,
|
||||
pub(crate) index: c_int,
|
||||
pub(crate) drop: bool,
|
||||
}
|
||||
|
||||
impl<'lua> LuaRef<'lua> {
|
||||
pub(crate) const fn new(lua: &'lua Lua, index: c_int) -> Self {
|
||||
LuaRef {
|
||||
lua,
|
||||
index,
|
||||
drop: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn into_owned(self) -> LuaOwnedRef {
|
||||
self.lua.make_owned_ref(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> fmt::Debug for LuaRef<'lua> {
|
||||
|
@ -196,7 +211,7 @@ impl<'lua> Clone for LuaRef<'lua> {
|
|||
|
||||
impl<'lua> Drop for LuaRef<'lua> {
|
||||
fn drop(&mut self) {
|
||||
if self.index > 0 {
|
||||
if self.drop {
|
||||
self.lua.drop_ref(self);
|
||||
}
|
||||
}
|
||||
|
@ -214,3 +229,40 @@ impl<'lua> PartialEq for LuaRef<'lua> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct LuaOwnedRef {
|
||||
pub(crate) lua: Lua,
|
||||
pub(crate) index: c_int,
|
||||
}
|
||||
|
||||
impl fmt::Debug for LuaOwnedRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "OwnedRef({})", self.index)
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for LuaOwnedRef {
|
||||
fn clone(&self) -> Self {
|
||||
self.lua.make_owned_ref(self.to_ref().clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for LuaOwnedRef {
|
||||
fn drop(&mut self) {
|
||||
self.lua.drop_ref(&LuaRef {
|
||||
lua: &self.lua,
|
||||
index: self.index,
|
||||
drop: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaOwnedRef {
|
||||
pub(crate) const fn to_ref(&self) -> LuaRef {
|
||||
LuaRef {
|
||||
lua: &self.lua,
|
||||
index: self.index,
|
||||
drop: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
114
src/userdata.rs
114
src/userdata.rs
|
@ -20,7 +20,7 @@ use crate::ffi;
|
|||
use crate::function::Function;
|
||||
use crate::lua::Lua;
|
||||
use crate::table::{Table, TablePairs};
|
||||
use crate::types::{Callback, LuaRef, MaybeSend};
|
||||
use crate::types::{Callback, LuaOwnedRef, LuaRef, MaybeSend};
|
||||
use crate::util::{check_stack, get_userdata, take_userdata, StackGuard};
|
||||
use crate::value::{FromLua, FromLuaMulti, ToLua, ToLuaMulti};
|
||||
|
||||
|
@ -310,9 +310,8 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
///
|
||||
/// 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<S, A, R, M>(&mut self, name: &S, method: M)
|
||||
fn add_method<A, R, M>(&mut self, name: &str, method: M)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>;
|
||||
|
@ -322,9 +321,8 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
/// Refer to [`add_method`] for more information about the implementation.
|
||||
///
|
||||
/// [`add_method`]: #method.add_method
|
||||
fn add_method_mut<S, A, R, M>(&mut self, name: &S, method: M)
|
||||
fn add_method_mut<A, R, M>(&mut self, name: &str, method: M)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>;
|
||||
|
@ -339,10 +337,9 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
/// [`add_method`]: #method.add_method
|
||||
#[cfg(feature = "async")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
|
||||
fn add_async_method<S, A, R, M, MR>(&mut self, name: &S, method: M)
|
||||
fn add_async_method<A, R, M, MR>(&mut self, name: &str, method: M)
|
||||
where
|
||||
T: Clone,
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
|
||||
|
@ -358,9 +355,8 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
/// [`AnyUserData`]: crate::AnyUserData
|
||||
/// [`add_method`]: #method.add_method
|
||||
/// [`add_method_mut`]: #method.add_method_mut
|
||||
fn add_function<S, A, R, F>(&mut self, name: &S, function: F)
|
||||
fn add_function<A, R, F>(&mut self, name: &str, function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>;
|
||||
|
@ -370,9 +366,8 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
/// This is a version of [`add_function`] that accepts a FnMut argument.
|
||||
///
|
||||
/// [`add_function`]: #method.add_function
|
||||
fn add_function_mut<S, A, R, F>(&mut self, name: &S, function: F)
|
||||
fn add_function_mut<A, R, F>(&mut self, name: &str, function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>;
|
||||
|
@ -387,9 +382,8 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
/// [`add_function`]: #method.add_function
|
||||
#[cfg(feature = "async")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
|
||||
fn add_async_function<S, A, R, F, FR>(&mut self, name: &S, function: F)
|
||||
fn add_async_function<A, R, F, FR>(&mut self, name: &str, function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
|
||||
|
@ -403,9 +397,8 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
/// side has a metatable. To prevent this, use [`add_meta_function`].
|
||||
///
|
||||
/// [`add_meta_function`]: #method.add_meta_function
|
||||
fn add_meta_method<S, A, R, M>(&mut self, meta: S, method: M)
|
||||
fn add_meta_method<A, R, M>(&mut self, meta: impl Into<MetaMethod>, method: M)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>;
|
||||
|
@ -418,9 +411,8 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
/// side has a metatable. To prevent this, use [`add_meta_function`].
|
||||
///
|
||||
/// [`add_meta_function`]: #method.add_meta_function
|
||||
fn add_meta_method_mut<S, A, R, M>(&mut self, meta: S, method: M)
|
||||
fn add_meta_method_mut<A, R, M>(&mut self, meta: impl Into<MetaMethod>, method: M)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>;
|
||||
|
@ -435,10 +427,9 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
/// [`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, A, R, M, MR>(&mut self, name: S, method: M)
|
||||
fn add_async_meta_method<A, R, M, MR>(&mut self, name: impl Into<MetaMethod>, method: M)
|
||||
where
|
||||
T: Clone,
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
|
||||
|
@ -449,9 +440,8 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
/// 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<S, A, R, F>(&mut self, meta: S, function: F)
|
||||
fn add_meta_function<A, R, F>(&mut self, meta: impl Into<MetaMethod>, function: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>;
|
||||
|
@ -461,9 +451,8 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
/// 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<S, A, R, F>(&mut self, meta: S, function: F)
|
||||
fn add_meta_function_mut<A, R, F>(&mut self, meta: impl Into<MetaMethod>, function: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>;
|
||||
|
@ -477,9 +466,8 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
/// [`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<S, A, R, F, FR>(&mut self, name: S, function: F)
|
||||
fn add_async_meta_function<A, R, F, FR>(&mut self, name: impl Into<MetaMethod>, function: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
|
||||
|
@ -490,11 +478,11 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
//
|
||||
|
||||
#[doc(hidden)]
|
||||
fn add_callback(&mut self, _name: Vec<u8>, _callback: Callback<'lua, 'static>) {}
|
||||
fn add_callback(&mut self, _name: String, _callback: Callback<'lua, 'static>) {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "async")]
|
||||
fn add_async_callback(&mut self, _name: Vec<u8>, _callback: AsyncCallback<'lua, 'static>) {}
|
||||
fn add_async_callback(&mut self, _name: String, _callback: AsyncCallback<'lua, 'static>) {}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn add_meta_callback(&mut self, _meta: MetaMethod, _callback: Callback<'lua, 'static>) {}
|
||||
|
@ -520,9 +508,8 @@ pub trait UserDataFields<'lua, T: UserData> {
|
|||
///
|
||||
/// 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<S, R, M>(&mut self, name: &S, method: M)
|
||||
fn add_field_method_get<R, M>(&mut self, name: &str, method: M)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
R: ToLua<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T) -> Result<R>;
|
||||
|
||||
|
@ -533,9 +520,8 @@ pub trait UserDataFields<'lua, T: UserData> {
|
|||
///
|
||||
/// 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<S, A, M>(&mut self, name: &S, method: M)
|
||||
fn add_field_method_set<A, M>(&mut self, name: &str, method: M)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLua<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<()>;
|
||||
|
||||
|
@ -546,9 +532,8 @@ pub trait UserDataFields<'lua, T: UserData> {
|
|||
///
|
||||
/// [`AnyUserData`]: crate::AnyUserData
|
||||
/// [`add_field_method_get`]: #method.add_field_method_get
|
||||
fn add_field_function_get<S, R, F>(&mut self, name: &S, function: F)
|
||||
fn add_field_function_get<R, F>(&mut self, name: &str, function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
R: ToLua<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>) -> Result<R>;
|
||||
|
||||
|
@ -559,9 +544,8 @@ pub trait UserDataFields<'lua, T: UserData> {
|
|||
///
|
||||
/// [`AnyUserData`]: crate::AnyUserData
|
||||
/// [`add_field_method_set`]: #method.add_field_method_set
|
||||
fn add_field_function_set<S, A, F>(&mut self, name: &S, function: F)
|
||||
fn add_field_function_set<A, F>(&mut self, name: &str, function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLua<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, AnyUserData<'lua>, A) -> Result<()>;
|
||||
|
||||
|
@ -573,21 +557,20 @@ pub trait UserDataFields<'lua, T: UserData> {
|
|||
///
|
||||
/// `mlua` will trigger an error on an attempt to define a protected metamethod,
|
||||
/// like `__gc` or `__metatable`.
|
||||
fn add_meta_field_with<S, R, F>(&mut self, meta: S, f: F)
|
||||
fn add_meta_field_with<R, F>(&mut self, meta: impl Into<MetaMethod>, f: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua) -> Result<R>,
|
||||
R: ToLua<'lua>;
|
||||
R: ToLua<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua) -> Result<R>;
|
||||
|
||||
//
|
||||
// Below are internal methods used in generated code
|
||||
//
|
||||
|
||||
#[doc(hidden)]
|
||||
fn add_field_getter(&mut self, _name: Vec<u8>, _callback: Callback<'lua, 'static>) {}
|
||||
fn add_field_getter(&mut self, _name: String, _callback: Callback<'lua, 'static>) {}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn add_field_setter(&mut self, _name: Vec<u8>, _callback: Callback<'lua, 'static>) {}
|
||||
fn add_field_setter(&mut self, _name: String, _callback: Callback<'lua, 'static>) {}
|
||||
}
|
||||
|
||||
/// Trait for custom userdata types.
|
||||
|
@ -799,6 +782,15 @@ impl Serialize for UserDataSerializeError {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct AnyUserData<'lua>(pub(crate) LuaRef<'lua>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OwnedAnyUserData(pub(crate) LuaOwnedRef);
|
||||
|
||||
impl OwnedAnyUserData {
|
||||
pub const fn to_ref(&self) -> AnyUserData {
|
||||
AnyUserData(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> AnyUserData<'lua> {
|
||||
/// Checks whether the type of this userdata is `T`.
|
||||
pub fn is<T: 'static + UserData>(&self) -> bool {
|
||||
|
@ -831,39 +823,21 @@ impl<'lua> AnyUserData<'lua> {
|
|||
self.inspect(|cell| cell.try_borrow_mut())
|
||||
}
|
||||
|
||||
/// Takes out the value of `UserData` and sets the special "destructed" metatable that prevents
|
||||
/// any further operations with this userdata.
|
||||
/// Takes the value out of this userdata.
|
||||
/// Sets the special "destructed" metatable that prevents any further operations with this userdata.
|
||||
///
|
||||
/// All associated user values will be also cleared.
|
||||
/// Keeps associated user values unchanged (they will be collected by Lua's GC).
|
||||
pub fn take<T: 'static + UserData>(&self) -> Result<T> {
|
||||
let lua = self.0.lua;
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 3)?;
|
||||
check_stack(lua.state, 2)?;
|
||||
|
||||
let type_id = lua.push_userdata_ref(&self.0)?;
|
||||
match type_id {
|
||||
Some(type_id) if type_id == TypeId::of::<T>() => {
|
||||
// Try to borrow userdata exclusively
|
||||
let _ = (*get_userdata::<UserDataCell<T>>(lua.state, -1)).try_borrow_mut()?;
|
||||
|
||||
// Clear associated user values
|
||||
#[cfg(feature = "lua54")]
|
||||
for i in 1..=USER_VALUE_MAXSLOT {
|
||||
ffi::lua_pushnil(lua.state);
|
||||
ffi::lua_setiuservalue(lua.state, -2, i as c_int);
|
||||
}
|
||||
#[cfg(any(feature = "lua53", feature = "lua52", feature = "luau"))]
|
||||
{
|
||||
ffi::lua_pushnil(lua.state);
|
||||
ffi::lua_setuservalue(lua.state, -2);
|
||||
}
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
protect_lua!(lua.state, 1, 1, fn(state) {
|
||||
ffi::lua_newtable(state);
|
||||
ffi::lua_setuservalue(state, -2);
|
||||
})?;
|
||||
|
||||
Ok(take_userdata::<UserDataCell<T>>(lua.state).into_inner())
|
||||
}
|
||||
_ => Err(Error::UserDataTypeMismatch),
|
||||
|
@ -1000,9 +974,8 @@ impl<'lua> AnyUserData<'lua> {
|
|||
/// The value can be retrieved with [`get_named_user_value`].
|
||||
///
|
||||
/// [`get_named_user_value`]: #method.get_named_user_value
|
||||
pub fn set_named_user_value<S, V>(&self, name: &S, v: V) -> Result<()>
|
||||
pub fn set_named_user_value<V>(&self, name: &str, v: V) -> Result<()>
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
V: ToLua<'lua>,
|
||||
{
|
||||
let lua = self.0.lua;
|
||||
|
@ -1014,7 +987,6 @@ impl<'lua> AnyUserData<'lua> {
|
|||
lua.push_value(v.to_lua(lua)?)?;
|
||||
|
||||
// Multiple (extra) user values are emulated by storing them in a table
|
||||
let name = name.as_ref();
|
||||
protect_lua!(lua.state, 2, 0, |state| {
|
||||
if getuservalue_table(state, -2) != ffi::LUA_TTABLE {
|
||||
// Create a new table to use as uservalue
|
||||
|
@ -1039,9 +1011,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 get_named_user_value<S, V>(&self, name: &S) -> Result<V>
|
||||
pub fn get_named_user_value<V>(&self, name: &str) -> Result<V>
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
V: FromLua<'lua>,
|
||||
{
|
||||
let lua = self.0.lua;
|
||||
|
@ -1052,7 +1023,6 @@ impl<'lua> AnyUserData<'lua> {
|
|||
lua.push_userdata_ref(&self.0)?;
|
||||
|
||||
// Multiple (extra) user values are emulated by storing them in a table
|
||||
let name = name.as_ref();
|
||||
protect_lua!(lua.state, 1, 1, |state| {
|
||||
if getuservalue_table(state, -1) != ffi::LUA_TTABLE {
|
||||
ffi::lua_pushnil(state);
|
||||
|
@ -1074,6 +1044,7 @@ impl<'lua> AnyUserData<'lua> {
|
|||
/// For `T: UserData + 'static` returned metatable is shared among all instances of type `T`.
|
||||
///
|
||||
/// [`UserDataMetatable`]: crate::UserDataMetatable
|
||||
#[inline]
|
||||
pub fn get_metatable(&self) -> Result<UserDataMetatable<'lua>> {
|
||||
self.get_raw_metatable().map(UserDataMetatable)
|
||||
}
|
||||
|
@ -1090,6 +1061,11 @@ impl<'lua> AnyUserData<'lua> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_owned(self) -> OwnedAnyUserData {
|
||||
OwnedAnyUserData(self.0.into_owned())
|
||||
}
|
||||
|
||||
pub(crate) fn equals<T: AsRef<Self>>(&self, other: T) -> Result<bool> {
|
||||
let other = other.as_ref();
|
||||
// Uses lua_rawequal() under the hood
|
||||
|
|
|
@ -24,9 +24,9 @@ use {
|
|||
};
|
||||
|
||||
pub(crate) struct StaticUserDataMethods<'lua, T: 'static + UserData> {
|
||||
pub(crate) methods: Vec<(Vec<u8>, Callback<'lua, 'static>)>,
|
||||
pub(crate) methods: Vec<(String, Callback<'lua, 'static>)>,
|
||||
#[cfg(feature = "async")]
|
||||
pub(crate) async_methods: Vec<(Vec<u8>, AsyncCallback<'lua, 'static>)>,
|
||||
pub(crate) async_methods: Vec<(String, AsyncCallback<'lua, 'static>)>,
|
||||
pub(crate) meta_methods: Vec<(MetaMethod, Callback<'lua, 'static>)>,
|
||||
#[cfg(feature = "async")]
|
||||
pub(crate) async_meta_methods: Vec<(MetaMethod, AsyncCallback<'lua, 'static>)>,
|
||||
|
@ -48,80 +48,72 @@ impl<'lua, T: 'static + UserData> Default for StaticUserDataMethods<'lua, T> {
|
|||
}
|
||||
|
||||
impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMethods<'lua, T> {
|
||||
fn add_method<S, A, R, M>(&mut self, name: &S, method: M)
|
||||
fn add_method<A, R, M>(&mut self, name: &str, method: M)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>,
|
||||
{
|
||||
self.methods
|
||||
.push((name.as_ref().to_vec(), Self::box_method(method)));
|
||||
self.methods.push((name.into(), Self::box_method(method)));
|
||||
}
|
||||
|
||||
fn add_method_mut<S, A, R, M>(&mut self, name: &S, method: M)
|
||||
fn add_method_mut<A, R, M>(&mut self, name: &str, method: M)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
|
||||
{
|
||||
self.methods
|
||||
.push((name.as_ref().to_vec(), Self::box_method_mut(method)));
|
||||
.push((name.into(), Self::box_method_mut(method)));
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
fn add_async_method<S, A, R, M, MR>(&mut self, name: &S, method: M)
|
||||
fn add_async_method<A, R, M, MR>(&mut self, name: &str, method: M)
|
||||
where
|
||||
T: Clone,
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
|
||||
MR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
self.async_methods
|
||||
.push((name.as_ref().to_vec(), Self::box_async_method(method)));
|
||||
.push((name.into(), Self::box_async_method(method)));
|
||||
}
|
||||
|
||||
fn add_function<S, A, R, F>(&mut self, name: &S, function: F)
|
||||
fn add_function<A, R, F>(&mut self, name: &str, function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
self.methods
|
||||
.push((name.as_ref().to_vec(), Self::box_function(function)));
|
||||
.push((name.into(), Self::box_function(function)));
|
||||
}
|
||||
|
||||
fn add_function_mut<S, A, R, F>(&mut self, name: &S, function: F)
|
||||
fn add_function_mut<A, R, F>(&mut self, name: &str, function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
self.methods
|
||||
.push((name.as_ref().to_vec(), Self::box_function_mut(function)));
|
||||
.push((name.into(), Self::box_function_mut(function)));
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
fn add_async_function<S, A, R, F, FR>(&mut self, name: &S, function: F)
|
||||
fn add_async_function<A, R, F, FR>(&mut self, name: &str, function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
|
||||
FR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
self.async_methods
|
||||
.push((name.as_ref().to_vec(), Self::box_async_function(function)));
|
||||
.push((name.into(), Self::box_async_function(function)));
|
||||
}
|
||||
|
||||
fn add_meta_method<S, A, R, M>(&mut self, meta: S, method: M)
|
||||
fn add_meta_method<A, R, M>(&mut self, meta: impl Into<MetaMethod>, method: M)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>,
|
||||
|
@ -130,9 +122,8 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
|
|||
.push((meta.into(), Self::box_method(method)));
|
||||
}
|
||||
|
||||
fn add_meta_method_mut<S, A, R, M>(&mut self, meta: S, method: M)
|
||||
fn add_meta_method_mut<A, R, M>(&mut self, meta: impl Into<MetaMethod>, method: M)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
|
||||
|
@ -142,10 +133,9 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
|
|||
}
|
||||
|
||||
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
|
||||
fn add_async_meta_method<S, A, R, M, MR>(&mut self, meta: S, method: M)
|
||||
fn add_async_meta_method<A, R, M, MR>(&mut self, meta: impl Into<MetaMethod>, method: M)
|
||||
where
|
||||
T: Clone,
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
|
||||
|
@ -155,9 +145,8 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
|
|||
.push((meta.into(), Self::box_async_method(method)));
|
||||
}
|
||||
|
||||
fn add_meta_function<S, A, R, F>(&mut self, meta: S, function: F)
|
||||
fn add_meta_function<A, R, F>(&mut self, meta: impl Into<MetaMethod>, function: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>,
|
||||
|
@ -166,9 +155,8 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
|
|||
.push((meta.into(), Self::box_function(function)));
|
||||
}
|
||||
|
||||
fn add_meta_function_mut<S, A, R, F>(&mut self, meta: S, function: F)
|
||||
fn add_meta_function_mut<A, R, F>(&mut self, meta: impl Into<MetaMethod>, function: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>,
|
||||
|
@ -178,9 +166,8 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
|
|||
}
|
||||
|
||||
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
|
||||
fn add_async_meta_function<S, A, R, F, FR>(&mut self, meta: S, function: F)
|
||||
fn add_async_meta_function<A, R, F, FR>(&mut self, meta: impl Into<MetaMethod>, function: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: ToLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
|
||||
|
@ -192,12 +179,12 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
|
|||
|
||||
// Below are internal methods used in generated code
|
||||
|
||||
fn add_callback(&mut self, name: Vec<u8>, callback: Callback<'lua, 'static>) {
|
||||
fn add_callback(&mut self, name: String, callback: Callback<'lua, 'static>) {
|
||||
self.methods.push((name, callback));
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
fn add_async_callback(&mut self, name: Vec<u8>, callback: AsyncCallback<'lua, 'static>) {
|
||||
fn add_async_callback(&mut self, name: String, callback: AsyncCallback<'lua, 'static>) {
|
||||
self.async_methods.push((name, callback));
|
||||
}
|
||||
|
||||
|
@ -457,8 +444,8 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
|
|||
}
|
||||
|
||||
pub(crate) struct StaticUserDataFields<'lua, T: 'static + UserData> {
|
||||
pub(crate) field_getters: Vec<(Vec<u8>, Callback<'lua, 'static>)>,
|
||||
pub(crate) field_setters: Vec<(Vec<u8>, Callback<'lua, 'static>)>,
|
||||
pub(crate) field_getters: Vec<(String, Callback<'lua, 'static>)>,
|
||||
pub(crate) field_setters: Vec<(String, Callback<'lua, 'static>)>,
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub(crate) meta_fields: Vec<(
|
||||
MetaMethod,
|
||||
|
@ -479,59 +466,52 @@ impl<'lua, T: 'static + UserData> Default for StaticUserDataFields<'lua, T> {
|
|||
}
|
||||
|
||||
impl<'lua, T: 'static + UserData> UserDataFields<'lua, T> for StaticUserDataFields<'lua, T> {
|
||||
fn add_field_method_get<S, R, M>(&mut self, name: &S, method: M)
|
||||
fn add_field_method_get<R, M>(&mut self, name: &str, method: M)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
R: ToLua<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T) -> Result<R>,
|
||||
{
|
||||
self.field_getters.push((
|
||||
name.as_ref().to_vec(),
|
||||
name.into(),
|
||||
StaticUserDataMethods::box_method(move |lua, data, ()| method(lua, data)),
|
||||
));
|
||||
}
|
||||
|
||||
fn add_field_method_set<S, A, M>(&mut self, name: &S, method: M)
|
||||
fn add_field_method_set<A, M>(&mut self, name: &str, method: M)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLua<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<()>,
|
||||
{
|
||||
self.field_setters.push((
|
||||
name.as_ref().to_vec(),
|
||||
StaticUserDataMethods::box_method_mut(method),
|
||||
));
|
||||
self.field_setters
|
||||
.push((name.into(), StaticUserDataMethods::box_method_mut(method)));
|
||||
}
|
||||
|
||||
fn add_field_function_get<S, R, F>(&mut self, name: &S, function: F)
|
||||
fn add_field_function_get<R, F>(&mut self, name: &str, function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
R: ToLua<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>) -> Result<R>,
|
||||
{
|
||||
self.field_getters.push((
|
||||
name.as_ref().to_vec(),
|
||||
name.into(),
|
||||
StaticUserDataMethods::<T>::box_function(function),
|
||||
));
|
||||
}
|
||||
|
||||
fn add_field_function_set<S, A, F>(&mut self, name: &S, mut function: F)
|
||||
fn add_field_function_set<A, F>(&mut self, name: &str, mut function: F)
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
A: FromLua<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, AnyUserData<'lua>, A) -> Result<()>,
|
||||
{
|
||||
self.field_setters.push((
|
||||
name.as_ref().to_vec(),
|
||||
name.into(),
|
||||
StaticUserDataMethods::<T>::box_function_mut(move |lua, (data, val)| {
|
||||
function(lua, data, val)
|
||||
}),
|
||||
));
|
||||
}
|
||||
|
||||
fn add_meta_field_with<S, R, F>(&mut self, meta: S, f: F)
|
||||
fn add_meta_field_with<R, F>(&mut self, meta: impl Into<MetaMethod>, f: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
R: ToLua<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua) -> Result<R>,
|
||||
{
|
||||
|
@ -559,11 +539,11 @@ impl<'lua, T: 'static + UserData> UserDataFields<'lua, T> for StaticUserDataFiel
|
|||
|
||||
// Below are internal methods
|
||||
|
||||
fn add_field_getter(&mut self, name: Vec<u8>, callback: Callback<'lua, 'static>) {
|
||||
fn add_field_getter(&mut self, name: String, callback: Callback<'lua, 'static>) {
|
||||
self.field_getters.push((name, callback));
|
||||
}
|
||||
|
||||
fn add_field_setter(&mut self, name: Vec<u8>, callback: Callback<'lua, 'static>) {
|
||||
fn add_field_setter(&mut self, name: String, callback: Callback<'lua, 'static>) {
|
||||
self.field_setters.push((name, callback));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -272,11 +272,7 @@ pub unsafe fn push_table(
|
|||
}
|
||||
|
||||
// Uses 4 stack spaces, does not call checkstack.
|
||||
pub unsafe fn rawset_field<S>(state: *mut ffi::lua_State, table: c_int, field: &S) -> Result<()>
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
{
|
||||
let field = field.as_ref();
|
||||
pub unsafe fn rawset_field(state: *mut ffi::lua_State, table: c_int, field: &str) -> Result<()> {
|
||||
ffi::lua_pushvalue(state, table);
|
||||
protect_lua!(state, 2, 0, |state| {
|
||||
ffi::lua_pushlstring(state, field.as_ptr() as *const c_char, field.len());
|
||||
|
|
|
@ -727,9 +727,9 @@ fn test_set_metatable_nil() -> Result<()> {
|
|||
fn test_named_registry_value() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
lua.set_named_registry_value::<_, i32>("test", 42)?;
|
||||
lua.set_named_registry_value::<i32>("test", 42)?;
|
||||
let f = lua.create_function(move |lua, ()| {
|
||||
assert_eq!(lua.named_registry_value::<_, i32>("test")?, 42);
|
||||
assert_eq!(lua.named_registry_value::<i32>("test")?, 42);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
|
|
|
@ -305,21 +305,19 @@ fn test_userdata_take() -> Result<()> {
|
|||
fn check_userdata_take(lua: &Lua, userdata: AnyUserData, rc: Arc<i64>) -> Result<()> {
|
||||
lua.globals().set("userdata", userdata.clone())?;
|
||||
assert_eq!(Arc::strong_count(&rc), 3);
|
||||
let userdata_copy = userdata.clone();
|
||||
{
|
||||
let _value = userdata.borrow::<MyUserdata>()?;
|
||||
// We should not be able to take userdata if it's borrowed
|
||||
match userdata_copy.take::<MyUserdata>() {
|
||||
match userdata.take::<MyUserdata>() {
|
||||
Err(Error::UserDataBorrowMutError) => {}
|
||||
r => panic!("expected `UserDataBorrowMutError` error, got {:?}", r),
|
||||
}
|
||||
}
|
||||
|
||||
let value = userdata_copy.take::<MyUserdata>()?;
|
||||
let value = userdata.take::<MyUserdata>()?;
|
||||
assert_eq!(*value.0, 18);
|
||||
drop(value);
|
||||
lua.gc_collect()?;
|
||||
assert_eq!(Arc::strong_count(&rc), 1);
|
||||
assert_eq!(Arc::strong_count(&rc), 2);
|
||||
|
||||
match userdata.borrow::<MyUserdata>() {
|
||||
Err(Error::UserDataDestructed) => {}
|
||||
|
@ -332,6 +330,13 @@ fn test_userdata_take() -> Result<()> {
|
|||
},
|
||||
r => panic!("improper return for destructed userdata: {:?}", r),
|
||||
}
|
||||
|
||||
drop(userdata);
|
||||
lua.globals().raw_remove("userdata")?;
|
||||
lua.gc_collect()?;
|
||||
lua.gc_collect()?;
|
||||
assert_eq!(Arc::strong_count(&rc), 1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -403,9 +408,9 @@ fn test_user_values() -> Result<()> {
|
|||
ud.set_named_user_value("name", "alex")?;
|
||||
ud.set_named_user_value("age", 10)?;
|
||||
|
||||
assert_eq!(ud.get_named_user_value::<_, String>("name")?, "alex");
|
||||
assert_eq!(ud.get_named_user_value::<_, i32>("age")?, 10);
|
||||
assert_eq!(ud.get_named_user_value::<_, Value>("nonexist")?, Value::Nil);
|
||||
assert_eq!(ud.get_named_user_value::<String>("name")?, "alex");
|
||||
assert_eq!(ud.get_named_user_value::<i32>("age")?, 10);
|
||||
assert_eq!(ud.get_named_user_value::<Value>("nonexist")?, Value::Nil);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue