Fix lots of bugs, add thread placeholder type, fix ValueVec when used in tuples, much more
This commit is contained in:
parent
5694d395ab
commit
35bd889b48
31
src/chunk.rs
31
src/chunk.rs
|
@ -1,6 +1,6 @@
|
||||||
use std::borrow::{Borrow, Cow};
|
use std::borrow::{Borrow, Cow};
|
||||||
|
|
||||||
use crate::{FromLua, Function, IntoLuaVec, State};
|
use crate::{FromLua, FromLuaVec, Function, IntoLuaVec, State};
|
||||||
|
|
||||||
pub struct Chunk<'a> {
|
pub struct Chunk<'a> {
|
||||||
state: &'a State,
|
state: &'a State,
|
||||||
|
@ -39,7 +39,7 @@ impl<'a> Chunk<'a> {
|
||||||
pub fn execute<A, R>(&'a self, args: A) -> crate::Result<R>
|
pub fn execute<A, R>(&'a self, args: A) -> crate::Result<R>
|
||||||
where
|
where
|
||||||
A: IntoLuaVec<'a>,
|
A: IntoLuaVec<'a>,
|
||||||
R: FromLua<'a>
|
R: FromLuaVec<'a>
|
||||||
{
|
{
|
||||||
self.state.execute_chunk::<A, R>(self, args)
|
self.state.execute_chunk::<A, R>(self, args)
|
||||||
}
|
}
|
||||||
|
@ -66,24 +66,43 @@ pub trait IntoChunkData<'a> {
|
||||||
|
|
||||||
impl<'a> IntoChunkData<'a> for &'a str {
|
impl<'a> IntoChunkData<'a> for &'a str {
|
||||||
fn into_chunk(self) -> Cow<'a, [u8]> {
|
fn into_chunk(self) -> Cow<'a, [u8]> {
|
||||||
Cow::Borrowed(self.as_bytes())
|
if self.ends_with("\n") {
|
||||||
|
Cow::Borrowed(self.as_bytes())
|
||||||
|
} else {
|
||||||
|
let s = format!("{}\n", self);
|
||||||
|
Cow::Owned(s.as_bytes().to_vec())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoChunkData<'a> for &'a String {
|
impl<'a> IntoChunkData<'a> for &'a String {
|
||||||
fn into_chunk(self) -> Cow<'a, [u8]> {
|
fn into_chunk(self) -> Cow<'a, [u8]> {
|
||||||
Cow::Borrowed(self.as_bytes())
|
let s = format!("{}\n", self);
|
||||||
|
Cow::Owned(s.as_bytes().to_vec())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoChunkData<'a> for String {
|
impl<'a> IntoChunkData<'a> for String {
|
||||||
fn into_chunk(self) -> Cow<'a, [u8]> {
|
fn into_chunk(self) -> Cow<'a, [u8]> {
|
||||||
Cow::Owned(self.as_bytes().to_vec())
|
let s = if self.ends_with("\n") {
|
||||||
|
self
|
||||||
|
} else {
|
||||||
|
format!("{self}\n")
|
||||||
|
};
|
||||||
|
|
||||||
|
Cow::Owned(s.as_bytes().to_vec())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoChunkData<'a> for &'a [u8] {
|
impl<'a> IntoChunkData<'a> for &'a [u8] {
|
||||||
fn into_chunk(self) -> Cow<'a, [u8]> {
|
fn into_chunk(self) -> Cow<'a, [u8]> {
|
||||||
Cow::Borrowed(self)
|
if self.ends_with("\n".as_bytes()) {
|
||||||
|
Cow::Borrowed(self)
|
||||||
|
} else {
|
||||||
|
let mut v = self.to_vec();
|
||||||
|
v.extend_from_slice("\n".as_bytes());
|
||||||
|
|
||||||
|
Cow::Owned(v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
21
src/error.rs
21
src/error.rs
|
@ -16,8 +16,11 @@ pub enum Error {
|
||||||
MemoryAlloc,
|
MemoryAlloc,
|
||||||
#[error("Ran into a nill value on the stack")]
|
#[error("Ran into a nill value on the stack")]
|
||||||
Nil,
|
Nil,
|
||||||
#[error("Unexpected type, expected {0} but got {1}")]
|
#[error("Type mismatch, expected {expected} but got {got}")]
|
||||||
UnexpectedType(String, String),
|
TypeMismatch {
|
||||||
|
expected: String,
|
||||||
|
got: String,
|
||||||
|
},
|
||||||
#[error("bad argument #{arg_index}{} to `{}` ({error})",
|
#[error("bad argument #{arg_index}{} to `{}` ({error})",
|
||||||
.arg_name.clone().map(|a| format!(" (name: {})", a)).unwrap_or("".to_string()),
|
.arg_name.clone().map(|a| format!(" (name: {})", a)).unwrap_or("".to_string()),
|
||||||
.func.clone().unwrap_or("Unknown".to_string())
|
.func.clone().unwrap_or("Unknown".to_string())
|
||||||
|
@ -47,6 +50,8 @@ pub enum Error {
|
||||||
#[source]
|
#[source]
|
||||||
error: Arc<Error>,
|
error: Arc<Error>,
|
||||||
},
|
},
|
||||||
|
#[error("{0}")]
|
||||||
|
Other(Arc<dyn std::error::Error + Send + Sync>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
|
@ -54,8 +59,11 @@ impl Error {
|
||||||
Self::Runtime(msg.to_string())
|
Self::Runtime(msg.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unexpected_type(expected: &str, got: &str) -> Self {
|
pub fn type_mismatch<S: AsRef<str>>(expected: S, got: S) -> Self {
|
||||||
Self::UnexpectedType(expected.to_string(), got.to_string())
|
Self::TypeMismatch {
|
||||||
|
expected: expected.as_ref().to_string(),
|
||||||
|
got: got.as_ref().to_string(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Throw the error in lua.
|
/// Throw the error in lua.
|
||||||
|
@ -67,6 +75,11 @@ impl Error {
|
||||||
lua::luaL_error(lua, msg_c);
|
lua::luaL_error(lua, msg_c);
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a `Error::other` from an unknown error type
|
||||||
|
pub fn other<T: std::error::Error + Send + Sync + 'static>(e: T) -> Self {
|
||||||
|
Self::Other(Arc::new(e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A result for use with lua functions
|
/// A result for use with lua functions
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{AsLua, FromLua, FromLuaStack, IntoLuaVec, LuaRef, PushToLuaStack, StackGuard, State, Value, ValueVec};
|
use crate::{AsLua, Error, FromLua, FromLuaStack, FromLuaVec, IntoLuaVec, LuaRef, PushToLuaStack, StackGuard, State, Value, ValueVec};
|
||||||
|
|
||||||
use mlua_sys as lua;
|
use mlua_sys as lua;
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ impl<'a> Function<'a> {
|
||||||
pub fn exec<A, R>(&self, args: A) -> crate::Result<R>
|
pub fn exec<A, R>(&self, args: A) -> crate::Result<R>
|
||||||
where
|
where
|
||||||
A: IntoLuaVec<'a>,
|
A: IntoLuaVec<'a>,
|
||||||
R: FromLua<'a>,
|
R: FromLuaVec<'a>,
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
let _g = StackGuard::new(self.state);
|
let _g = StackGuard::new(self.state);
|
||||||
|
@ -61,7 +61,11 @@ impl<'a> Function<'a> {
|
||||||
self.push_to_lua_stack(self.state)?;
|
self.push_to_lua_stack(self.state)?;
|
||||||
args_val.push_to_lua_stack(self.state)?;
|
args_val.push_to_lua_stack(self.state)?;
|
||||||
|
|
||||||
match lua::lua_pcall(s, args_len, lua::LUA_MULTRET, handler_idx) {
|
State::print_stack(self.state);
|
||||||
|
|
||||||
|
let val_count = R::value_num().unwrap_or(lua::LUA_MULTRET as usize);
|
||||||
|
|
||||||
|
match lua::lua_pcall(s, args_len, val_count as i32, handler_idx) {
|
||||||
lua::LUA_ERRRUN => {
|
lua::LUA_ERRRUN => {
|
||||||
let er = self.state.get_error_str();
|
let er = self.state.get_error_str();
|
||||||
return Err(crate::Error::runtime(er));
|
return Err(crate::Error::runtime(er));
|
||||||
|
@ -77,29 +81,39 @@ impl<'a> Function<'a> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ret_count = lua::lua_gettop(s);
|
State::print_stack(self.state);
|
||||||
|
|
||||||
|
/* let ret_count = lua::lua_gettop(s);
|
||||||
let val = if ret_count > 1 {
|
let val = if ret_count > 1 {
|
||||||
let vals = ValueVec::from_lua_stack(self.state)?;
|
let vals = ValueVec::from_lua_stack(self.state)?;
|
||||||
Value::Variable(vals)
|
Value::Multi(vals)
|
||||||
} else if ret_count == 1 {
|
} else if ret_count == 1 {
|
||||||
Value::from_lua_stack(self.state)?
|
Value::from_lua_stack(self.state)?
|
||||||
} else {
|
} else {
|
||||||
Value::None
|
Value::None
|
||||||
|
}; */
|
||||||
|
|
||||||
|
let vals = if R::value_num().is_some() {
|
||||||
|
ValueVec::from_stack_limit(self.state, val_count)?
|
||||||
|
} else {
|
||||||
|
ValueVec::from_lua_stack(self.state)?
|
||||||
};
|
};
|
||||||
|
|
||||||
R::from_lua(self.state, val)
|
R::from_lua_value_vec(self.state, vals)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AsLua<'a> for Function<'a> {
|
impl<'a> AsLua<'a> for Function<'a> {
|
||||||
fn as_lua(&self, _lua: &'a State) -> crate::Result<crate::Value<'a>> {
|
fn as_lua(self, _lua: &'a State) -> crate::Result<crate::Value<'a>> {
|
||||||
Ok(crate::Value::Function(self.clone()))
|
Ok(crate::Value::Function(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromLua<'a> for Function<'a> {
|
impl<'a> FromLua<'a> for Function<'a> {
|
||||||
fn from_lua(_lua: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
fn from_lua(_lua: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
||||||
|
let tyname = val.type_name();
|
||||||
val.into_function()
|
val.into_function()
|
||||||
|
.ok_or(Error::type_mismatch("Function", &tyname))
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -35,11 +35,11 @@ impl<'a> StackGuard<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn lua_error_guard<F, R>(lua: &State, func: F) -> R
|
pub unsafe fn lua_error_guard<'a, F, R>(lua: &'a State, func: F) -> R
|
||||||
where
|
where
|
||||||
F: Fn() -> crate::Result<R>
|
F: Fn(&'a State) -> crate::Result<R>
|
||||||
{
|
{
|
||||||
match func() {
|
match func(lua) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => e.throw_lua(lua.state_ptr())
|
Err(e) => e.throw_lua(lua.state_ptr())
|
||||||
}
|
}
|
||||||
|
|
19
src/lib.rs
19
src/lib.rs
|
@ -16,7 +16,10 @@ pub mod guard;
|
||||||
pub use guard::*;
|
pub use guard::*;
|
||||||
|
|
||||||
pub mod userdata;
|
pub mod userdata;
|
||||||
use userdata::*;
|
pub use userdata::*;
|
||||||
|
|
||||||
|
pub mod thread;
|
||||||
|
pub use thread::*;
|
||||||
|
|
||||||
pub mod util;
|
pub mod util;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
|
@ -69,8 +72,8 @@ impl<'a, T: PushToLuaStack<'a>> PushToLuaStack<'a> for Option<T> {
|
||||||
macro_rules! impl_as_lua_number {
|
macro_rules! impl_as_lua_number {
|
||||||
($ty: ident) => {
|
($ty: ident) => {
|
||||||
impl<'a> AsLua<'a> for $ty {
|
impl<'a> AsLua<'a> for $ty {
|
||||||
fn as_lua(&self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
fn as_lua(self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
||||||
Ok(Value::Number(*self as f64))
|
Ok(Value::Number(self as f64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,9 +81,9 @@ macro_rules! impl_as_lua_number {
|
||||||
fn from_lua(_lua: &State, val: Value) -> crate::Result<Self> {
|
fn from_lua(_lua: &State, val: Value) -> crate::Result<Self> {
|
||||||
match val {
|
match val {
|
||||||
Value::Number(v) => Ok(v as $ty),
|
Value::Number(v) => Ok(v as $ty),
|
||||||
_ => Err(Error::UnexpectedType(
|
_ => Err(Error::type_mismatch(
|
||||||
"Number".to_string(),
|
"Number",
|
||||||
val.type_name().to_string(),
|
&val.type_name(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,7 +124,9 @@ impl<'a> PushToLuaStack<'a> for String {
|
||||||
|
|
||||||
impl<'a> FromLua<'a> for String {
|
impl<'a> FromLua<'a> for String {
|
||||||
fn from_lua(_lua: &State, val: Value) -> crate::Result<Self> {
|
fn from_lua(_lua: &State, val: Value) -> crate::Result<Self> {
|
||||||
val.as_string().cloned()
|
Ok(val.as_string()
|
||||||
|
.ok_or(Error::type_mismatch("String", &val.type_name()))?
|
||||||
|
.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
src/lref.rs
13
src/lref.rs
|
@ -1,6 +1,6 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{Error, PushToLuaStack, Result, State};
|
use crate::{Error, PushToLuaStack, Result, StackGuard, State};
|
||||||
|
|
||||||
use mlua_sys as lua;
|
use mlua_sys as lua;
|
||||||
|
|
||||||
|
@ -18,9 +18,8 @@ pub struct LuaRef<'a> {
|
||||||
impl<'a> Drop for LuaRef<'a> {
|
impl<'a> Drop for LuaRef<'a> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let s = self.state.state_ptr();
|
|
||||||
|
|
||||||
if Arc::strong_count(&self.lref) == 1 {
|
if Arc::strong_count(&self.lref) == 1 {
|
||||||
|
let s = self.state.state_ptr();
|
||||||
lua::luaL_unref(s, lua::LUA_REGISTRYINDEX, *self.lref);
|
lua::luaL_unref(s, lua::LUA_REGISTRYINDEX, *self.lref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,13 +49,19 @@ impl<'a> LuaRef<'a> {
|
||||||
impl<'a> PushToLuaStack<'a> for LuaRef<'a> {
|
impl<'a> PushToLuaStack<'a> for LuaRef<'a> {
|
||||||
unsafe fn push_to_lua_stack(&self, state: &State) -> Result<()> {
|
unsafe fn push_to_lua_stack(&self, state: &State) -> Result<()> {
|
||||||
let s = state.state_ptr();
|
let s = state.state_ptr();
|
||||||
|
|
||||||
state.ensure_stack(1)?;
|
state.ensure_stack(1)?;
|
||||||
|
|
||||||
let top = lua::lua_gettop(s);
|
let top = lua::lua_gettop(s);
|
||||||
let ty = lua::lua_rawgeti(s, lua::LUA_REGISTRYINDEX, *self.lref as i64);
|
let ty = lua::lua_rawgeti(s, lua::LUA_REGISTRYINDEX, *self.lref as i64);
|
||||||
let new_top = lua::lua_gettop(s);
|
let new_top = lua::lua_gettop(s);
|
||||||
|
|
||||||
|
// make sure that the ref was actually made
|
||||||
if ty == lua::LUA_TNIL || ty == lua::LUA_TNONE || top == new_top {
|
if ty == lua::LUA_TNIL || ty == lua::LUA_TNONE || top == new_top {
|
||||||
|
// nil may have been pushed to the stack, remove it
|
||||||
|
if new_top > top {
|
||||||
|
lua::lua_pop(s, 1);
|
||||||
|
}
|
||||||
|
|
||||||
return Err(Error::Nil);
|
return Err(Error::Nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
230
src/state.rs
230
src/state.rs
|
@ -1,7 +1,7 @@
|
||||||
use core::ffi;
|
use core::ffi;
|
||||||
use std::{alloc::{self, Layout}, any::TypeId, cell::RefCell, collections::HashMap, ffi::{CStr, CString}, mem, ptr::{self, NonNull}, str::Utf8Error, sync::Arc};
|
use std::{alloc::{self, Layout}, any::TypeId, cell::RefCell, collections::HashMap, ffi::{CStr, CString}, mem, ptr::{self, NonNull}, str::Utf8Error, sync::Arc};
|
||||||
|
|
||||||
use lua::lua_gc;
|
use lua::{lua_State, lua_gc};
|
||||||
use mlua_sys as lua;
|
use mlua_sys as lua;
|
||||||
|
|
||||||
use crate::{lua_error_guard, proxy::UserdataProxy, AnyUserdata, AsLua, Chunk, Error, FromLua, FromLuaStack, FromLuaVec, Function, IntoChunkData, IntoLuaVec, LuaRef, MetaMethod, PushToLuaStack, Result, StackGuard, Table, Userdata, UserdataBuilder, Value, ValueVec};
|
use crate::{lua_error_guard, proxy::UserdataProxy, AnyUserdata, AsLua, Chunk, Error, FromLua, FromLuaStack, FromLuaVec, Function, IntoChunkData, IntoLuaVec, LuaRef, MetaMethod, PushToLuaStack, Result, StackGuard, Table, Userdata, UserdataBuilder, Value, ValueVec};
|
||||||
|
@ -65,8 +65,21 @@ impl StdLibraries {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A helper function that returns an instance that contains all libraries
|
||||||
pub fn all() -> Self {
|
pub fn all() -> Self {
|
||||||
todo!()
|
let mut v = Self::new();
|
||||||
|
let libs = &mut v.libs;
|
||||||
|
libs.push(StdLibrary::Coroutine);
|
||||||
|
libs.push(StdLibrary::Table);
|
||||||
|
libs.push(StdLibrary::Io);
|
||||||
|
libs.push(StdLibrary::Os);
|
||||||
|
libs.push(StdLibrary::String);
|
||||||
|
libs.push(StdLibrary::Utf8);
|
||||||
|
libs.push(StdLibrary::Math);
|
||||||
|
libs.push(StdLibrary::Debug);
|
||||||
|
libs.push(StdLibrary::Package);
|
||||||
|
|
||||||
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(&mut self, lib: StdLibrary) {
|
pub fn load(&mut self, lib: StdLibrary) {
|
||||||
|
@ -85,64 +98,110 @@ impl<const N: usize> From<&[StdLibrary; N]> for StdLibraries {
|
||||||
/// A struct that is used as an upvalue for creating Lua callable functions
|
/// A struct that is used as an upvalue for creating Lua callable functions
|
||||||
struct ClosureData<'a> {
|
struct ClosureData<'a> {
|
||||||
wrapper_fn: Box<dyn Fn(&'a State, i32) -> i32>,
|
wrapper_fn: Box<dyn Fn(&'a State, i32) -> i32>,
|
||||||
state: &'a State,
|
state: NonNull<State>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
//#[derive(Default)]
|
||||||
pub struct ExtraSpace<'a> {
|
pub struct ExtraSpace<'a> {
|
||||||
pub userdata_metatables: HashMap<TypeId, LuaRef<'a>>,
|
pub userdata_metatables: HashMap<TypeId, LuaRef<'a>>,
|
||||||
|
pub state_ptr: StatePtr
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ExtraSpace<'a> {
|
||||||
|
pub fn new(state: &State) -> Self {
|
||||||
|
Self {
|
||||||
|
userdata_metatables: Default::default(),
|
||||||
|
state_ptr: state.ptr.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct StatePtr {
|
||||||
|
lua: Arc<NonNull<lua::lua_State>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
lua: NonNull<lua::lua_State>,
|
ptr: StatePtr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for State {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for State {
|
impl Drop for State {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let extra = self.get_extra_space_ptr();
|
println!("State count: {}", Arc::strong_count(&self.ptr.lua));
|
||||||
|
if Arc::strong_count(&self.ptr.lua) == 2 { // this owned arc, and the one in extra
|
||||||
|
let extra = self.get_extra_space_ptr();
|
||||||
|
|
||||||
{
|
{
|
||||||
// clear the refs to anything in lua before we close it and
|
// clear the refs to anything in lua before we close it and
|
||||||
// attempt to drop extra after
|
// attempt to drop extra after
|
||||||
let extra = &mut *extra;
|
let extra = &mut *extra;
|
||||||
extra.userdata_metatables.clear();
|
extra.userdata_metatables.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
lua::lua_close(self.state_ptr());
|
||||||
|
extra.drop_in_place();
|
||||||
|
|
||||||
|
// must be dealloced since it wasn't memory created from lua (i.e. userdata)
|
||||||
|
alloc::dealloc(extra.cast(), Layout::new::<ExtraSpace>());
|
||||||
}
|
}
|
||||||
|
|
||||||
lua::lua_close(self.lua.as_ptr());
|
|
||||||
extra.drop_in_place();
|
|
||||||
|
|
||||||
// must be dealloced since it wasn't memory created from lua (i.e. userdata)
|
|
||||||
alloc::dealloc(extra.cast(), Layout::new::<ExtraSpace>());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn extra_space<'a>(state: *mut lua::lua_State) -> *mut ExtraSpace<'a> {
|
||||||
|
let extra = lua::lua_getextraspace(state)
|
||||||
|
.cast::<*mut ExtraSpace>();
|
||||||
|
*extra
|
||||||
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let s = Self {
|
let s = Self {
|
||||||
lua: unsafe { NonNull::new_unchecked(lua::luaL_newstate()) }
|
ptr: StatePtr {
|
||||||
|
lua: Arc::new(unsafe { NonNull::new_unchecked(lua::luaL_newstate()) })
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
s.alloc_extra_space();
|
s.alloc_extra_space();
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new Lua State, exposes the provides libraries in the state
|
||||||
|
pub fn new_with_libraries<L: Into<StdLibraries>>(libs: L) -> Self {
|
||||||
|
let s = Self::new();
|
||||||
|
|
||||||
|
s.expose_libraries(libs);
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_ptr(lua: *mut lua::lua_State) -> Self {
|
pub fn from_ptr(lua: *mut lua::lua_State) -> Self {
|
||||||
Self {
|
unsafe {
|
||||||
lua: unsafe { NonNull::new_unchecked(lua) }
|
let extra = lua::lua_getextraspace(lua)
|
||||||
|
.cast::<*mut ExtraSpace>();
|
||||||
|
let extra = *extra;
|
||||||
|
|
||||||
|
Self {
|
||||||
|
ptr: (*extra).state_ptr.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn state_ptr(&self) -> *mut lua::lua_State {
|
pub(crate) fn state_ptr(&self) -> *mut lua::lua_State {
|
||||||
self.lua.as_ptr()
|
self.ptr.lua.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_extra_space(&self) {
|
fn alloc_extra_space(&self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let extra_ptr = alloc::alloc(Layout::new::<ExtraSpace>())
|
let extra_ptr = alloc::alloc(Layout::new::<ExtraSpace>())
|
||||||
.cast::<ExtraSpace>();
|
.cast::<ExtraSpace>();
|
||||||
ptr::write(extra_ptr, ExtraSpace::default());
|
ptr::write(extra_ptr, ExtraSpace::new(self));
|
||||||
|
|
||||||
let s = self.state_ptr();
|
let s = self.state_ptr();
|
||||||
let loc = lua::lua_getextraspace(s);
|
let loc = lua::lua_getextraspace(s);
|
||||||
|
@ -192,7 +251,7 @@ impl State {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.ensure_stack(1)?;
|
self.ensure_stack(1)?;
|
||||||
let _g = StackGuard::new(self);
|
let _g = StackGuard::new(self);
|
||||||
let s = self.lua.as_ptr();
|
let s = self.state_ptr();
|
||||||
|
|
||||||
let chunk_data = chunk.into_chunk();
|
let chunk_data = chunk.into_chunk();
|
||||||
let chunk_ptr = chunk_data.as_ptr().cast();
|
let chunk_ptr = chunk_data.as_ptr().cast();
|
||||||
|
@ -221,7 +280,7 @@ impl State {
|
||||||
pub fn execute_chunk<'a, A, R>(&'a self, chunk: &'a Chunk, args: A) -> Result<R>
|
pub fn execute_chunk<'a, A, R>(&'a self, chunk: &'a Chunk, args: A) -> Result<R>
|
||||||
where
|
where
|
||||||
A: IntoLuaVec<'a>,
|
A: IntoLuaVec<'a>,
|
||||||
R: FromLua<'a>
|
R: FromLuaVec<'a>
|
||||||
{
|
{
|
||||||
let handler = self.create_function(|lua, msg: String| {
|
let handler = self.create_function(|lua, msg: String| {
|
||||||
lua.state_error_handler(msg)
|
lua.state_error_handler(msg)
|
||||||
|
@ -234,7 +293,7 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expose_libraries<L: Into<StdLibraries>>(&self, libs: L) {
|
pub fn expose_libraries<L: Into<StdLibraries>>(&self, libs: L) {
|
||||||
let lua = self.lua.as_ptr();
|
let lua = self.state_ptr();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let base = "_G\0".as_ptr().cast();
|
let base = "_G\0".as_ptr().cast();
|
||||||
|
@ -311,7 +370,7 @@ impl State {
|
||||||
pub fn create_function<'a, A, R, F>(&self, f: F) -> Result<Function>
|
pub fn create_function<'a, A, R, F>(&self, f: F) -> Result<Function>
|
||||||
where
|
where
|
||||||
A: FromLuaVec<'a>,
|
A: FromLuaVec<'a>,
|
||||||
R: AsLua<'a>, //PushToLuaStackMulti<'a>,
|
R: AsLua<'a>,
|
||||||
F: Fn(&'a State, A) -> Result<R> + 'static,
|
F: Fn(&'a State, A) -> Result<R> + 'static,
|
||||||
{
|
{
|
||||||
unsafe extern "C-unwind" fn rust_closure(s: *mut lua::lua_State) -> i32 {
|
unsafe extern "C-unwind" fn rust_closure(s: *mut lua::lua_State) -> i32 {
|
||||||
|
@ -331,9 +390,11 @@ impl State {
|
||||||
|
|
||||||
let top = lua::lua_gettop(s);
|
let top = lua::lua_gettop(s);
|
||||||
let wrap = &(*data_ptr).wrapper_fn;
|
let wrap = &(*data_ptr).wrapper_fn;
|
||||||
let s = (*data_ptr).state;
|
|
||||||
|
|
||||||
wrap(s, top)
|
let extra = extra_space(s);
|
||||||
|
let lua: &State = mem::transmute(&(*extra).state_ptr.lua);
|
||||||
|
|
||||||
|
wrap(lua, top)
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let name = CStr::from_ptr(lua::lua_typename(s, ltype));
|
let name = CStr::from_ptr(lua::lua_typename(s, ltype));
|
||||||
|
@ -349,25 +410,23 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let wrapper_fn = move |lua: &State, _narg: i32| -> i32 {
|
let wrapper_fn = move |lua: &'a State, _narg: i32| -> i32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let lua: &State = mem::transmute(lua); // transmute lifetimes
|
lua_error_guard(lua, |lua| {
|
||||||
|
let vec = ValueVec::from_lua_stack(lua).unwrap();
|
||||||
|
|
||||||
lua_error_guard(lua, || {
|
let args = A::from_lua_value_vec(lua, vec).unwrap();
|
||||||
let vec = ValueVec::from_lua_stack(lua)?;
|
|
||||||
|
|
||||||
let args = A::from_lua_value_vec(lua, vec)?;
|
let r = f(lua, args).unwrap();
|
||||||
|
let r_val = r.as_lua(lua).unwrap();
|
||||||
let r = f(lua, args)?;
|
|
||||||
let r_val = r.as_lua(lua)?;
|
|
||||||
|
|
||||||
let args_len = match &r_val {
|
let args_len = match &r_val {
|
||||||
Value::Variable(v) => v.len(),
|
Value::Multi(v) => v.len(),
|
||||||
Value::None => 0,
|
Value::None => 0,
|
||||||
_ => 1,
|
_ => 1,
|
||||||
} as _;
|
} as _;
|
||||||
|
|
||||||
r_val.push_to_lua_stack(lua)?;
|
r_val.push_to_lua_stack(lua).unwrap();
|
||||||
|
|
||||||
Ok(args_len)
|
Ok(args_len)
|
||||||
})
|
})
|
||||||
|
@ -376,12 +435,15 @@ impl State {
|
||||||
|
|
||||||
let data = ClosureData {
|
let data = ClosureData {
|
||||||
wrapper_fn: Box::new(wrapper_fn),
|
wrapper_fn: Box::new(wrapper_fn),
|
||||||
state: self,
|
state: NonNull::from(self),
|
||||||
};
|
};
|
||||||
|
|
||||||
let s = self.state_ptr();
|
let s = self.state_ptr();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let _g = StackGuard::new(self);
|
||||||
|
self.ensure_stack(3)?;
|
||||||
|
|
||||||
let ptr = lua::lua_newuserdata(s, mem::size_of::<ClosureData>());
|
let ptr = lua::lua_newuserdata(s, mem::size_of::<ClosureData>());
|
||||||
let ptr = ptr.cast();
|
let ptr = ptr.cast();
|
||||||
ptr::write(ptr, data);
|
ptr::write(ptr, data);
|
||||||
|
@ -583,7 +645,9 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
let v = Value::from_lua_stack(self)?;
|
let v = Value::from_lua_stack(self)?;
|
||||||
let s = v.into_string()?;
|
let tyname = v.type_name();
|
||||||
|
let s = v.into_string()
|
||||||
|
.ok_or(Error::type_mismatch("String", &tyname))?;
|
||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -686,9 +750,95 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inserts a value into the [Lua Registry](https://www.lua.org/manual/5.4/manual.html#4.3),
|
||||||
|
/// returning a key that can be used with [`State::registry_get`] to retrieve it.
|
||||||
|
pub fn registry_insert<'a, T: AsLua<'a>>(&'a self, val: T) -> Result<RegistryKey> {
|
||||||
|
let val = val.as_lua(self)?;
|
||||||
|
unsafe {
|
||||||
|
val.push_to_lua_stack(self)?;
|
||||||
|
|
||||||
|
let s = self.state_ptr();
|
||||||
|
let r = lua::luaL_ref(s, lua::LUA_REGISTRYINDEX);
|
||||||
|
if r == lua::LUA_REFNIL {
|
||||||
|
Err(Error::Nil)
|
||||||
|
} else {
|
||||||
|
Ok(RegistryKey(r))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieves a value from the [Lua Registry](https://www.lua.org/manual/5.4/manual.html#4.3)
|
||||||
|
/// however, this does not remove it from the registry. See [`State::registry_remove`] for that.
|
||||||
|
pub fn registry_get<'a, T: FromLua<'a>>(&'a self, key: RegistryKey) -> Result<T> {
|
||||||
|
unsafe {
|
||||||
|
let _g = StackGuard::new(self);
|
||||||
|
let s = self.state_ptr();
|
||||||
|
self.ensure_stack(1)?;
|
||||||
|
|
||||||
|
let top = lua::lua_gettop(s);
|
||||||
|
let ty = lua::lua_rawgeti(s, lua::LUA_REGISTRYINDEX, key.0 as i64);
|
||||||
|
let new_top = lua::lua_gettop(s);
|
||||||
|
|
||||||
|
// make sure that the ref was actually made
|
||||||
|
if ty == lua::LUA_TNIL || ty == lua::LUA_TNONE || top == new_top {
|
||||||
|
return Err(Error::Nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
let val = Value::from_lua_stack(self)?;
|
||||||
|
T::from_lua(self, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a boolean indicating if the [Lua Registry](https://www.lua.org/manual/5.4/manual.html#4.3)
|
||||||
|
/// contains a value at the provided key.
|
||||||
|
pub fn registry_contains(&self, key: RegistryKey) -> Result<bool> {
|
||||||
|
unsafe {
|
||||||
|
let _g = StackGuard::new(self);
|
||||||
|
let s = self.state_ptr();
|
||||||
|
self.ensure_stack(1)?;
|
||||||
|
|
||||||
|
let top = lua::lua_gettop(s);
|
||||||
|
let ty = lua::lua_rawgeti(s, lua::LUA_REGISTRYINDEX, key.0 as i64);
|
||||||
|
let new_top = lua::lua_gettop(s);
|
||||||
|
|
||||||
|
// make sure that the ref was actually made
|
||||||
|
if ty == lua::LUA_TNIL || ty == lua::LUA_TNONE || top == new_top {
|
||||||
|
Ok(false)
|
||||||
|
} else {
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes a value from the [Lua Registry](https://www.lua.org/manual/5.4/manual.html#4.3)
|
||||||
|
/// at the provided key. Returns a boolean indicating if anything was removed.
|
||||||
|
///
|
||||||
|
/// > Note: This does not call for garbage collection of the removed value. For that you
|
||||||
|
/// must use [`State::gc_collect`].
|
||||||
|
pub fn registry_remove(&self, key: RegistryKey) -> Result<bool> {
|
||||||
|
unsafe {
|
||||||
|
if self.registry_contains(key)? {
|
||||||
|
let s = self.state_ptr();
|
||||||
|
lua::luaL_unref(s, lua::LUA_REGISTRYINDEX, key.0);
|
||||||
|
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum GcMode {
|
pub enum GcMode {
|
||||||
Incremental,
|
Incremental,
|
||||||
Generational,
|
Generational,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A struct used to represent an entry in the
|
||||||
|
/// [Lua Registry](https://www.lua.org/manual/5.4/manual.html#4.3).
|
||||||
|
//
|
||||||
|
// A LuaRef would work just as well, but this is lighter without an Arc, and without a
|
||||||
|
// reference to the state.
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct RegistryKey(i32);
|
25
src/table.rs
25
src/table.rs
|
@ -1,6 +1,6 @@
|
||||||
use mlua_sys as lua;
|
use mlua_sys as lua;
|
||||||
|
|
||||||
use crate::{ensure_type, AsLua, FromLua, FromLuaStack, LuaRef, PushToLuaStack, Result, StackGuard, State, Value};
|
use crate::{ensure_type, AsLua, Error, FromLua, FromLuaStack, LuaRef, PushToLuaStack, Result, StackGuard, State, Value};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Table<'a> {
|
pub struct Table<'a> {
|
||||||
|
@ -38,8 +38,8 @@ impl<'a> Table<'a> {
|
||||||
|
|
||||||
let s = state.state_ptr();
|
let s = state.state_ptr();
|
||||||
if lua::luaL_newmetatable(s, name_term_c) == 0 {
|
if lua::luaL_newmetatable(s, name_term_c) == 0 {
|
||||||
// lua::luaL_getmetatable does not return the type that was
|
// if no table was pushed, there is a registry conflict, so try to get the table
|
||||||
// retrieved from the registry
|
// from the registry
|
||||||
lua::lua_pushstring(s, name_term_c);
|
lua::lua_pushstring(s, name_term_c);
|
||||||
let ty = lua::lua_rawget(s, lua::LUA_REGISTRYINDEX);
|
let ty = lua::lua_rawget(s, lua::LUA_REGISTRYINDEX);
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ impl<'a> Table<'a> {
|
||||||
return Err(crate::Error::RegistryConflict(name.to_string()));
|
return Err(crate::Error::RegistryConflict(name.to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaRef::from_stack(state)?
|
LuaRef::from_stack(state)?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -306,13 +307,15 @@ impl<'a> FromLuaStack<'a> for Table<'a> {
|
||||||
|
|
||||||
impl<'a> FromLua<'a> for Table<'a> {
|
impl<'a> FromLua<'a> for Table<'a> {
|
||||||
fn from_lua(_: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
fn from_lua(_: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
||||||
|
let tyname = val.type_name();
|
||||||
val.into_table()
|
val.into_table()
|
||||||
|
.ok_or(Error::type_mismatch("Table", &tyname))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AsLua<'a> for Table<'a> {
|
impl<'a> AsLua<'a> for Table<'a> {
|
||||||
fn as_lua(&self, _: &'a State) -> crate::Result<Value<'a>> {
|
fn as_lua(self, _: &'a State) -> crate::Result<Value<'a>> {
|
||||||
Ok(Value::Table(self.clone()))
|
Ok(Value::Table(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,6 +325,8 @@ impl<'a> AsLua<'a> for Table<'a> {
|
||||||
/// also retrieve an instance of your Rust type from an instance of the Lua type. This could help
|
/// also retrieve an instance of your Rust type from an instance of the Lua type. This could help
|
||||||
/// with minimizing the amount of calls to and from Rust.
|
/// with minimizing the amount of calls to and from Rust.
|
||||||
pub trait TableProxy: Sized {
|
pub trait TableProxy: Sized {
|
||||||
|
/// Returns the name of the table
|
||||||
|
fn table_name() -> String;
|
||||||
/// Create an instance of `Self` from the table
|
/// Create an instance of `Self` from the table
|
||||||
fn from_table<'a>(lua: &'a State, table: Table<'a>) -> Result<Self>;
|
fn from_table<'a>(lua: &'a State, table: Table<'a>) -> Result<Self>;
|
||||||
/// Creates a Lua instance from `Self`
|
/// Creates a Lua instance from `Self`
|
||||||
|
@ -365,7 +370,9 @@ impl<T: TableProxy> From<T> for Proxy<T> {
|
||||||
// getting a borrow.
|
// getting a borrow.
|
||||||
impl<'a, T: TableProxy> FromLua<'a> for Proxy<T> {
|
impl<'a, T: TableProxy> FromLua<'a> for Proxy<T> {
|
||||||
fn from_lua(lua: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
fn from_lua(lua: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
||||||
let table = val.into_table()?;
|
let tyname = val.type_name();
|
||||||
|
let table = val.into_table()
|
||||||
|
.ok_or(Error::type_mismatch("Table", &tyname))?;
|
||||||
let t = T::from_table(lua, table)?;
|
let t = T::from_table(lua, table)?;
|
||||||
|
|
||||||
Ok(Self::from(t))
|
Ok(Self::from(t))
|
||||||
|
@ -373,7 +380,7 @@ impl<'a, T: TableProxy> FromLua<'a> for Proxy<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: TableProxy> AsLua<'a> for Proxy<T> {
|
impl<'a, T: TableProxy> AsLua<'a> for Proxy<T> {
|
||||||
fn as_lua(&self, lua: &'a State) -> crate::Result<Value<'a>> {
|
fn as_lua(self, lua: &'a State) -> crate::Result<Value<'a>> {
|
||||||
self.data.as_ref()
|
self.data.as_ref()
|
||||||
.ok_or(crate::Error::Nil)
|
.ok_or(crate::Error::Nil)
|
||||||
.and_then(|d| d.as_table(lua))
|
.and_then(|d| d.as_table(lua))
|
||||||
|
@ -402,6 +409,10 @@ mod tests {
|
||||||
let new_fn: Function = vec2.get("new")?;
|
let new_fn: Function = vec2.get("new")?;
|
||||||
new_fn.exec((vec2, self.x, self.y))
|
new_fn.exec((vec2, self.x, self.y))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn table_name() -> String {
|
||||||
|
"Vec2".to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
use crate::{FromLuaStack, LuaRef, PushToLuaStack};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct LuaThread<'a>(LuaRef<'a>);
|
||||||
|
|
||||||
|
impl<'a> PushToLuaStack<'a> for LuaThread<'a> {
|
||||||
|
unsafe fn push_to_lua_stack(&self, state: &'a crate::State) -> crate::Result<()> {
|
||||||
|
self.0.push_to_lua_stack(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> FromLuaStack<'a> for LuaThread<'a> {
|
||||||
|
unsafe fn from_lua_stack(state: &'a crate::State) -> crate::Result<Self> {
|
||||||
|
Ok(Self(LuaRef::from_stack(state)?))
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ use std::{cell::{Ref, RefCell, RefMut}, ffi::CStr};
|
||||||
|
|
||||||
use mlua_sys as lua;
|
use mlua_sys as lua;
|
||||||
|
|
||||||
use crate::{ensure_type, AsLua, Error, FromLua, FromLuaStack, Function, IntoLuaVec, LuaRef, MetaMethod, PushToLuaStack, StackGuard, State, Table, Userdata, Value};
|
use crate::{ensure_type, AsLua, Error, FromLua, FromLuaStack, FromLuaVec, Function, IntoLuaVec, LuaRef, MetaMethod, PushToLuaStack, StackGuard, State, Table, Userdata, Value};
|
||||||
|
|
||||||
/// A handle to some userdata on the stack
|
/// A handle to some userdata on the stack
|
||||||
//#[derive(Clone)]
|
//#[derive(Clone)]
|
||||||
|
@ -145,7 +145,7 @@ impl<'a> AnyUserdata<'a> {
|
||||||
pub fn get<K, V>(&self, key: K) -> crate::Result<V>
|
pub fn get<K, V>(&self, key: K) -> crate::Result<V>
|
||||||
where
|
where
|
||||||
K: AsLua<'a>,
|
K: AsLua<'a>,
|
||||||
V: FromLua<'a>,
|
V: FromLuaVec<'a> + FromLua<'a>,
|
||||||
{
|
{
|
||||||
let mt = self.get_metatable()?;
|
let mt = self.get_metatable()?;
|
||||||
let key = key.as_lua(self.state)?;
|
let key = key.as_lua(self.state)?;
|
||||||
|
@ -154,7 +154,7 @@ impl<'a> AnyUserdata<'a> {
|
||||||
mt.get::<_, V>(key)
|
mt.get::<_, V>(key)
|
||||||
} else if mt.has_key(MetaMethod::Index)? {
|
} else if mt.has_key(MetaMethod::Index)? {
|
||||||
let index_fn: Function = mt.get(MetaMethod::Index)?;
|
let index_fn: Function = mt.get(MetaMethod::Index)?;
|
||||||
index_fn.exec((self.as_lua(self.state)?, key,))
|
index_fn.exec((self.clone().as_lua(self.state)?, key,))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::Nil)
|
Err(Error::Nil)
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ impl<'a> AnyUserdata<'a> {
|
||||||
pub fn execute_method<A, R>(&'a self, name: &str, args: A) -> crate::Result<R>
|
pub fn execute_method<A, R>(&'a self, name: &str, args: A) -> crate::Result<R>
|
||||||
where
|
where
|
||||||
A: IntoLuaVec<'a>,
|
A: IntoLuaVec<'a>,
|
||||||
R: FromLua<'a>,
|
R: FromLuaVec<'a> + FromLua<'a>,
|
||||||
{
|
{
|
||||||
let name = name.to_string();
|
let name = name.to_string();
|
||||||
let mt = self.get_metatable()?;
|
let mt = self.get_metatable()?;
|
||||||
|
@ -186,6 +186,22 @@ impl<'a> AnyUserdata<'a> {
|
||||||
|
|
||||||
f.exec(args)
|
f.exec(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Execute a function on this userdata.
|
||||||
|
///
|
||||||
|
/// This searches for a function with `name` and executes it. This may cause an execution
|
||||||
|
/// of the `__index` meta method.
|
||||||
|
pub fn execute_function<A, R>(&'a self, name: &str, args: A) -> crate::Result<R>
|
||||||
|
where
|
||||||
|
A: IntoLuaVec<'a>,
|
||||||
|
R: FromLuaVec<'a> + FromLua<'a>,
|
||||||
|
{
|
||||||
|
let name = name.to_string();
|
||||||
|
let mt = self.get_metatable()?;
|
||||||
|
let f = mt.get::<_, Function>(name)?;
|
||||||
|
|
||||||
|
f.exec(args)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromLuaStack<'a> for AnyUserdata<'a> {
|
impl<'a> FromLuaStack<'a> for AnyUserdata<'a> {
|
||||||
|
@ -206,27 +222,33 @@ impl<'a> PushToLuaStack<'a> for AnyUserdata<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AsLua<'a> for AnyUserdata<'a> {
|
impl<'a> AsLua<'a> for AnyUserdata<'a> {
|
||||||
fn as_lua(&self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
fn as_lua(self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
||||||
Ok(Value::Userdata(self.clone()))
|
Ok(Value::Userdata(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromLua<'a> for AnyUserdata<'a> {
|
impl<'a> FromLua<'a> for AnyUserdata<'a> {
|
||||||
fn from_lua(_lua: &State, val: Value<'a>) -> crate::Result<Self> {
|
fn from_lua(_: &State, val: Value<'a>) -> crate::Result<Self> {
|
||||||
|
let tyname = val.type_name();
|
||||||
val.into_userdata()
|
val.into_userdata()
|
||||||
|
.ok_or(Error::type_mismatch("Userdata", &tyname))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Userdata + 'static> FromLua<'a> for Ref<'a, T> {
|
impl<'a, T: Userdata + 'static> FromLua<'a> for Ref<'a, T> {
|
||||||
fn from_lua(_lua: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
fn from_lua(_lua: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
||||||
let ud = val.into_userdata()?;
|
let tyname = val.type_name();
|
||||||
|
let ud = val.into_userdata()
|
||||||
|
.ok_or(Error::type_mismatch("Userdata", &tyname))?;
|
||||||
ud.as_ref::<T>()
|
ud.as_ref::<T>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Userdata + 'static> FromLua<'a> for RefMut<'a, T> {
|
impl<'a, T: Userdata + 'static> FromLua<'a> for RefMut<'a, T> {
|
||||||
fn from_lua(_lua: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
fn from_lua(_lua: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
||||||
let ud = val.into_userdata()?;
|
let tyname = val.type_name();
|
||||||
|
let ud = val.into_userdata()
|
||||||
|
.ok_or(Error::type_mismatch("Userdata", &tyname))?;
|
||||||
ud.as_mut::<T>()
|
ud.as_mut::<T>()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -90,7 +90,7 @@ impl AsRef<str> for MetaMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AsLua<'a> for MetaMethod {
|
impl<'a> AsLua<'a> for MetaMethod {
|
||||||
fn as_lua(&self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
fn as_lua(self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
||||||
let s = self.as_ref();
|
let s = self.as_ref();
|
||||||
|
|
||||||
Ok(Value::String(s.to_string()))
|
Ok(Value::String(s.to_string()))
|
||||||
|
@ -109,3 +109,10 @@ pub trait Userdata: Sized {
|
||||||
|
|
||||||
fn build<'a>(state: &State, builder: &mut UserdataBuilder<'a, Self>) -> crate::Result<()>;
|
fn build<'a>(state: &State, builder: &mut UserdataBuilder<'a, Self>) -> crate::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Userdata + 'static> AsLua<'a> for T {
|
||||||
|
fn as_lua(self, lua: &'a State) -> crate::Result<Value<'a>> {
|
||||||
|
lua.create_userdata(self)
|
||||||
|
.and_then(|v| v.as_lua(lua))
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,12 +10,6 @@ impl<T: Userdata> UserdataProxy<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Userdata> AsLua<'a> for UserdataProxy<T> {
|
|
||||||
fn as_lua(&self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Userdata> Userdata for UserdataProxy<T> {
|
impl<T: Userdata> Userdata for UserdataProxy<T> {
|
||||||
fn build<'a>(state: &State, builder: &mut UserdataBuilder<'a, Self>) -> crate::Result<()> {
|
fn build<'a>(state: &State, builder: &mut UserdataBuilder<'a, Self>) -> crate::Result<()> {
|
||||||
let mut other = UserdataBuilder::<T>::new();
|
let mut other = UserdataBuilder::<T>::new();
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub(crate) unsafe fn ensure_type(state: &State, typ: i32, idx: i32) -> crate::Re
|
||||||
let s = cstr.to_str()
|
let s = cstr.to_str()
|
||||||
.expect("Lua type has invalid bytes!");
|
.expect("Lua type has invalid bytes!");
|
||||||
|
|
||||||
Err(crate::Error::UnexpectedType(exp_s.to_string(), s.to_string()))
|
Err(crate::Error::type_mismatch(exp_s, s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
276
src/value.rs
276
src/value.rs
|
@ -1,6 +1,6 @@
|
||||||
use std::{cell::{Ref, RefMut}, collections::VecDeque, ffi::CStr, ops::{Deref, DerefMut}};
|
use std::{cell::{Ref, RefMut}, collections::VecDeque, ffi::CStr, ops::{Deref, DerefMut}};
|
||||||
|
|
||||||
use crate::{AnyUserdata, FromLuaStack, Function, Proxy, PushToLuaStack, State, Table, TableProxy, Userdata};
|
use crate::{AnyUserdata, Error, FromLuaStack, Function, LuaThread, Proxy, PushToLuaStack, State, Table, TableProxy, Userdata};
|
||||||
|
|
||||||
use mlua_sys as lua;
|
use mlua_sys as lua;
|
||||||
|
|
||||||
|
@ -10,12 +10,14 @@ pub enum Value<'a> {
|
||||||
/// This is different than Nil, which does get pushed to the stack.
|
/// This is different than Nil, which does get pushed to the stack.
|
||||||
None,
|
None,
|
||||||
Nil,
|
Nil,
|
||||||
|
Boolean(bool),
|
||||||
Number(f64),
|
Number(f64),
|
||||||
String(String),
|
String(String),
|
||||||
Function(Function<'a>),
|
Function(Function<'a>),
|
||||||
|
Thread(LuaThread<'a>),
|
||||||
Table(Table<'a>),
|
Table(Table<'a>),
|
||||||
Userdata(AnyUserdata<'a>),
|
Userdata(AnyUserdata<'a>),
|
||||||
Variable(ValueVec<'a>),
|
Multi(ValueVec<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Value<'a> {
|
impl<'a> Value<'a> {
|
||||||
|
@ -23,124 +25,110 @@ impl<'a> Value<'a> {
|
||||||
matches!(self, Value::Nil)
|
matches!(self, Value::Nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_none(&self) -> bool {
|
||||||
|
matches!(self, Value::None)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn type_name(&self) -> String {
|
pub fn type_name(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Value::None => "None".to_string(),
|
Value::None => "None".to_string(),
|
||||||
Value::Nil => "Nil".to_string(),
|
Value::Nil => "Nil".to_string(),
|
||||||
|
Value::Boolean(_) => "Boolean".to_string(),
|
||||||
Value::Number(_) => "Number".to_string(),
|
Value::Number(_) => "Number".to_string(),
|
||||||
Value::String(_) => "String".to_string(),
|
Value::String(_) => "String".to_string(),
|
||||||
Value::Function(_) => "Function".to_string(),
|
Value::Function(_) => "Function".to_string(),
|
||||||
|
Value::Thread(_) => "Thread".to_string(),
|
||||||
Value::Table(_) => "Table".to_string(),
|
Value::Table(_) => "Table".to_string(),
|
||||||
Value::Userdata(ud) => ud.name().unwrap(),
|
Value::Userdata(ud) => ud.name().unwrap(),
|
||||||
Value::Variable(_) => todo!(),
|
Value::Multi(_) => "Multi".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_number(&self) -> crate::Result<f64> {
|
pub fn as_number(&self) -> Option<f64> {
|
||||||
match self {
|
match self {
|
||||||
Value::Number(v) => Ok(*v),
|
Value::Number(v) => Some(*v),
|
||||||
_ => {
|
_ => None
|
||||||
Err(crate::Error::UnexpectedType("Number".to_string(), self.type_name().to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If `self` is an instance of Value::String, returns a borrow to it. If it is not then
|
/// If `self` is an instance of Value::String, returns a borrow to it. If it is not then
|
||||||
/// an `UnexpectedType` error is returned.
|
/// an `UnexpectedType` error is returned.
|
||||||
pub fn as_string(&self) -> crate::Result<&String> {
|
pub fn as_string(&self) -> Option<&String> {
|
||||||
match self {
|
match self {
|
||||||
Value::String(s) => Ok(s),
|
Value::String(s) => Some(s),
|
||||||
_ => {
|
_ => None
|
||||||
Err(crate::Error::UnexpectedType("String".to_string(), self.type_name().to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If `self` is an instance of Value::Function, returns a borrow to it. If it is not then
|
/// If `self` is an instance of Value::Function, returns a borrow to it. If it is not then
|
||||||
/// an `UnexpectedType` error is returned.
|
/// an `UnexpectedType` error is returned.
|
||||||
pub fn as_function(&self) -> crate::Result<Function> {
|
pub fn as_function(&self) -> Option<&Function> {
|
||||||
match self {
|
match self {
|
||||||
Value::Function(v) => Ok(v.clone()),
|
Value::Function(v) => Some(v),
|
||||||
_ => {
|
_ => None,
|
||||||
Err(crate::Error::UnexpectedType("Table".to_string(), self.type_name().to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If `self` is an instance of Value::Table, returns a borrow to it. If it is not then
|
/// If `self` is an instance of Value::Table, returns a borrow to it. If it is not then
|
||||||
/// an `UnexpectedType` error is returned.
|
/// an `UnexpectedType` error is returned.
|
||||||
pub fn as_table(&self) -> crate::Result<Table> {
|
pub fn as_table(&self) -> Option<&Table> {
|
||||||
match self {
|
match self {
|
||||||
Value::Table(v) => Ok(v.clone()),
|
Value::Table(v) => Some(v),
|
||||||
_ => {
|
_ => None,
|
||||||
Err(crate::Error::UnexpectedType("Table".to_string(), self.type_name().to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If `self` is an instance of Value::Userdata, returns a borrow to it. If it is not then
|
/// If `self` is an instance of Value::Userdata, returns a borrow to it. If it is not then
|
||||||
/// an `UnexpectedType` error is returned.
|
/// an `UnexpectedType` error is returned.
|
||||||
pub fn as_userdata(&self) -> crate::Result<AnyUserdata<'a>> {
|
pub fn as_userdata(&self) -> Option<&AnyUserdata<'a>> {
|
||||||
match self {
|
match self {
|
||||||
Value::Userdata(ud) => Ok(ud.clone()),
|
Value::Userdata(ud) => Some(ud),
|
||||||
_ => {
|
_ => None
|
||||||
Err(crate::Error::UnexpectedType("Userdata".to_string(), self.type_name().to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If `self` is an instance of Value::String, the string is returned. If it is not then
|
/// If `self` is an instance of Value::String, the string is returned. If it is not then
|
||||||
/// an `UnexpectedType` error is returned.
|
/// an `UnexpectedType` error is returned.
|
||||||
pub fn into_string(self) -> crate::Result<String> {
|
pub fn into_string(self) -> Option<String> {
|
||||||
match self {
|
match self {
|
||||||
Value::String(s) => Ok(s),
|
Value::String(s) => Some(s),
|
||||||
_ => {
|
_ => None
|
||||||
Err(crate::Error::UnexpectedType("String".to_string(), self.type_name().to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If `self` is an instance of Value::Function, the function is returned. If it is not then
|
/// If `self` is an instance of Value::Function, the function is returned. If it is not then
|
||||||
/// an `UnexpectedType` error is returned.
|
/// an `UnexpectedType` error is returned.
|
||||||
pub fn into_function(self) -> crate::Result<Function<'a>> {
|
pub fn into_function(self) -> Option<Function<'a>> {
|
||||||
match self {
|
match self {
|
||||||
Value::Function(v) => Ok(v),
|
Value::Function(v) => Some(v),
|
||||||
_ => {
|
_ => None,
|
||||||
Err(crate::Error::UnexpectedType("Function".to_string(), self.type_name().to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If `self` is an instance of Value::Table, the table is returned. If it is not then
|
/// If `self` is an instance of Value::Table, the table is returned. If it is not then
|
||||||
/// an `UnexpectedType` error is returned.
|
/// an `UnexpectedType` error is returned.
|
||||||
pub fn into_table(self) -> crate::Result<Table<'a>> {
|
pub fn into_table(self) -> Option<Table<'a>> {
|
||||||
match self {
|
match self {
|
||||||
Value::Table(v) => Ok(v),
|
Value::Table(v) => Some(v),
|
||||||
_ => {
|
_ => None,
|
||||||
Err(crate::Error::UnexpectedType("Table".to_string(), self.type_name().to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If `self` is an instance of Value::Userdata, the userdata is returned. If it is not then
|
/// If `self` is an instance of Value::Userdata, the userdata is returned. If it is not then
|
||||||
/// an `UnexpectedType` error is returned.
|
/// an `UnexpectedType` error is returned.
|
||||||
pub fn into_userdata(self) -> crate::Result<AnyUserdata<'a>> {
|
pub fn into_userdata(self) -> Option<AnyUserdata<'a>> {
|
||||||
match self {
|
match self {
|
||||||
Value::Userdata(ud) => Ok(ud),
|
Value::Userdata(ud) => Some(ud),
|
||||||
_ => {
|
_ => None,
|
||||||
Err(crate::Error::UnexpectedType("Userdata".to_string(), self.type_name().to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If `self` is an instance of Value::Variadic, the ValueVec is returned. If it is not then
|
/// If `self` is an instance of Value::Variadic, the ValueVec is returned. If it is not then
|
||||||
/// an `UnexpectedType` error is returned.
|
/// an `UnexpectedType` error is returned.
|
||||||
pub fn into_value_vec(self) -> crate::Result<ValueVec<'a>> {
|
pub fn into_value_vec(self) -> Option<ValueVec<'a>> {
|
||||||
match self {
|
match self {
|
||||||
Value::Variable(v) => Ok(v),
|
Value::Multi(v) => Some(v),
|
||||||
_ => {
|
_ => None,
|
||||||
Err(crate::Error::UnexpectedType("ValueVec".to_string(), self.type_name().to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,6 +143,10 @@ impl<'a> PushToLuaStack<'a> for Value<'a> {
|
||||||
state.ensure_stack(1)?;
|
state.ensure_stack(1)?;
|
||||||
lua::lua_pushnil(s);
|
lua::lua_pushnil(s);
|
||||||
}
|
}
|
||||||
|
Value::Boolean(b) => {
|
||||||
|
state.ensure_stack(1)?;
|
||||||
|
lua::lua_pushboolean(s, *b as i32);
|
||||||
|
}
|
||||||
Value::Number(n) => {
|
Value::Number(n) => {
|
||||||
state.ensure_stack(1)?;
|
state.ensure_stack(1)?;
|
||||||
lua::lua_pushnumber(s, *n);
|
lua::lua_pushnumber(s, *n);
|
||||||
|
@ -167,9 +159,10 @@ impl<'a> PushToLuaStack<'a> for Value<'a> {
|
||||||
lua::lua_pushstring(state.state_ptr(), cstr);
|
lua::lua_pushstring(state.state_ptr(), cstr);
|
||||||
}
|
}
|
||||||
Value::Function(f) => f.push_to_lua_stack(state)?,
|
Value::Function(f) => f.push_to_lua_stack(state)?,
|
||||||
|
Value::Thread(t) => t.push_to_lua_stack(state)?,
|
||||||
Value::Table(t) => t.push_to_lua_stack(state)?,
|
Value::Table(t) => t.push_to_lua_stack(state)?,
|
||||||
Value::Userdata(ud) => ud.push_to_lua_stack(state)?,
|
Value::Userdata(ud) => ud.push_to_lua_stack(state)?,
|
||||||
Value::Variable(v) => {
|
Value::Multi(v) => {
|
||||||
for v in v.iter() {
|
for v in v.iter() {
|
||||||
v.push_to_lua_stack(state)?;
|
v.push_to_lua_stack(state)?;
|
||||||
}
|
}
|
||||||
|
@ -195,6 +188,12 @@ impl<'a> FromLuaStack<'a> for Value<'a> {
|
||||||
|
|
||||||
Ok(Value::Nil)
|
Ok(Value::Nil)
|
||||||
},
|
},
|
||||||
|
lua::LUA_TBOOLEAN => {
|
||||||
|
let b = lua::lua_toboolean(s, -1) != 0;
|
||||||
|
lua::lua_pop(s, 1);
|
||||||
|
|
||||||
|
Ok(Value::Boolean(b))
|
||||||
|
},
|
||||||
lua::LUA_TNUMBER => {
|
lua::LUA_TNUMBER => {
|
||||||
let n = lua::lua_tonumber(s, -1);
|
let n = lua::lua_tonumber(s, -1);
|
||||||
lua::lua_pop(s, 1);
|
lua::lua_pop(s, 1);
|
||||||
|
@ -214,6 +213,10 @@ impl<'a> FromLuaStack<'a> for Value<'a> {
|
||||||
Function::from_lua_stack(state)
|
Function::from_lua_stack(state)
|
||||||
.map(|f| Value::Function(f))
|
.map(|f| Value::Function(f))
|
||||||
},
|
},
|
||||||
|
lua::LUA_TTHREAD => {
|
||||||
|
LuaThread::from_lua_stack(state)
|
||||||
|
.map(|v| Value::Thread(v))
|
||||||
|
},
|
||||||
lua::LUA_TTABLE => {
|
lua::LUA_TTABLE => {
|
||||||
Table::from_lua_stack(state)
|
Table::from_lua_stack(state)
|
||||||
.map(|t| Value::Table(t))
|
.map(|t| Value::Table(t))
|
||||||
|
@ -226,7 +229,7 @@ impl<'a> FromLuaStack<'a> for Value<'a> {
|
||||||
let s = lua::lua_typename(s, ty);
|
let s = lua::lua_typename(s, ty);
|
||||||
let s = CStr::from_ptr(s);
|
let s = CStr::from_ptr(s);
|
||||||
let s = s.to_str().unwrap();
|
let s = s.to_str().unwrap();
|
||||||
unimplemented!("Not yet able to get '{}' as a value from the stack", s);
|
unimplemented!("Not yet able to get '{}' ({}) as a value from the stack", s, ty);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -235,7 +238,7 @@ impl<'a> FromLuaStack<'a> for Value<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AsLua<'a> {
|
pub trait AsLua<'a> {
|
||||||
fn as_lua(&self, lua: &'a State) -> crate::Result<Value<'a>>;
|
fn as_lua(self, lua: &'a State) -> crate::Result<Value<'a>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FromLua<'a>: Sized {
|
pub trait FromLua<'a>: Sized {
|
||||||
|
@ -251,35 +254,43 @@ pub trait FromLua<'a>: Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AsLua<'a> for () {
|
impl<'a> AsLua<'a> for () {
|
||||||
fn as_lua(&self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
fn as_lua(self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AsLua<'a> for Value<'a> {
|
impl<'a> AsLua<'a> for Value<'a> {
|
||||||
fn as_lua(&self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
fn as_lua(self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
||||||
Ok(self.clone())
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AsLua<'a> for String {
|
impl<'a> AsLua<'a> for String {
|
||||||
fn as_lua(&self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
fn as_lua(self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
||||||
Ok(Value::String(self.clone()))
|
Ok(Value::String(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AsLua<'a> for &'a str {
|
impl<'a> AsLua<'a> for &'a str {
|
||||||
fn as_lua(&self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
fn as_lua(self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
||||||
Ok(Value::String(self.to_string()))
|
Ok(Value::String(self.to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromLua<'a> for Value<'a> {
|
impl<'a> FromLua<'a> for Value<'a> {
|
||||||
fn from_lua(_lua: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
fn from_lua(_: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
||||||
Ok(val)
|
Ok(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> FromLua<'a> for ValueVec<'a> {
|
||||||
|
fn from_lua(_: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
||||||
|
let tyname = val.type_name();
|
||||||
|
val.into_value_vec()
|
||||||
|
.ok_or(Error::type_mismatch("ValueVec", &tyname))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> FromLua<'a> for () {
|
impl<'a> FromLua<'a> for () {
|
||||||
fn from_lua(_lua: &'a State, _val: Value<'a>) -> crate::Result<Self> {
|
fn from_lua(_lua: &'a State, _val: Value<'a>) -> crate::Result<Self> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -313,6 +324,13 @@ impl<'a> From<VecDeque<Value<'a>>> for ValueVec<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<Vec<Value<'a>>> for ValueVec<'a> {
|
||||||
|
fn from(value: Vec<Value<'a>>) -> Self {
|
||||||
|
Self(VecDeque::from(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a> FromLuaStack<'a> for ValueVec<'a> {
|
impl<'a> FromLuaStack<'a> for ValueVec<'a> {
|
||||||
unsafe fn from_lua_stack(state: &'a State) -> crate::Result<Self> {
|
unsafe fn from_lua_stack(state: &'a State) -> crate::Result<Self> {
|
||||||
let s = state.state_ptr();
|
let s = state.state_ptr();
|
||||||
|
@ -347,6 +365,21 @@ impl<'a> ValueVec<'a> {
|
||||||
pub fn into_iter(self) -> std::collections::vec_deque::IntoIter<Value<'a>> {
|
pub fn into_iter(self) -> std::collections::vec_deque::IntoIter<Value<'a>> {
|
||||||
self.0.into_iter()
|
self.0.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a ValueVec from the stack with a limit
|
||||||
|
pub fn from_stack_limit(state: &'a State, limit: usize) -> crate::Result<ValueVec<'a>> {
|
||||||
|
unsafe {
|
||||||
|
let s = state.state_ptr();
|
||||||
|
|
||||||
|
let mut vec = VecDeque::new();
|
||||||
|
for _ in 1..(limit + 1) {
|
||||||
|
let v = Value::from_lua_stack(state)?;
|
||||||
|
vec.push_front(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ValueVec(vec))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<Value<'a>> for ValueVec<'a> {
|
impl<'a> From<Value<'a>> for ValueVec<'a> {
|
||||||
|
@ -359,6 +392,10 @@ impl<'a> From<Value<'a>> for ValueVec<'a> {
|
||||||
|
|
||||||
/// A trait for getting something from a ValueVec from Lua
|
/// A trait for getting something from a ValueVec from Lua
|
||||||
pub trait FromLuaVec<'a>: Sized {
|
pub trait FromLuaVec<'a>: Sized {
|
||||||
|
fn value_num() -> Option<usize> {
|
||||||
|
Some(1)
|
||||||
|
}
|
||||||
|
|
||||||
fn from_lua_value_vec(state: &'a State, values: ValueVec<'a>) -> crate::Result<Self>;
|
fn from_lua_value_vec(state: &'a State, values: ValueVec<'a>) -> crate::Result<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,12 +403,16 @@ pub trait IntoLuaVec<'a>: Sized {
|
||||||
fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>>;
|
fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* impl<'a> FromLuaVec<'a> for ValueVec<'a> {
|
impl<'a> FromLuaVec<'a> for ValueVec<'a> {
|
||||||
fn from_lua_value_vec(_state: &'a State, values: ValueVec<'a>) -> crate::Result<Self> {
|
fn from_lua_value_vec(_state: &'a State, values: ValueVec<'a>) -> crate::Result<Self> {
|
||||||
Ok(values)
|
Ok(values)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_num() -> Option<usize> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
impl<'a> IntoLuaVec<'a> for ValueVec<'a> {
|
impl<'a> IntoLuaVec<'a> for ValueVec<'a> {
|
||||||
fn into_lua_value_vec(self, _state: &'a State) -> crate::Result<ValueVec<'a>> {
|
fn into_lua_value_vec(self, _state: &'a State) -> crate::Result<ValueVec<'a>> {
|
||||||
Ok(self)
|
Ok(self)
|
||||||
|
@ -389,11 +430,11 @@ impl<'a> IntoLuaVec<'a> for ValueVec<'a> {
|
||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
|
|
||||||
impl<'a> FromLuaVec<'a> for ValueVec<'a> {
|
/* impl<'a> FromLuaVec<'a> for ValueVec<'a> {
|
||||||
fn from_lua_value_vec(_state: &'a State, values: ValueVec<'a>) -> crate::Result<Self> {
|
fn from_lua_value_vec(_state: &'a State, values: ValueVec<'a>) -> crate::Result<Self> {
|
||||||
Ok(values)
|
Ok(values)
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
impl<'a> PushToLuaStack<'a> for ValueVec<'a> {
|
impl<'a> PushToLuaStack<'a> for ValueVec<'a> {
|
||||||
unsafe fn push_to_lua_stack(&self, state: &'a State) -> crate::Result<()> {
|
unsafe fn push_to_lua_stack(&self, state: &'a State) -> crate::Result<()> {
|
||||||
|
@ -421,7 +462,18 @@ macro_rules! impl_from_lua_vec_for_from_lua {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_num() -> Option<usize> {
|
||||||
|
Some(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* impl<'a> IntoLuaVec<'a> for $type<'a> {
|
||||||
|
fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>> {
|
||||||
|
Ok(ValueVec::from(self.as_lua(state)?))
|
||||||
|
}
|
||||||
|
} */
|
||||||
};
|
};
|
||||||
($type: tt) => {
|
($type: tt) => {
|
||||||
impl<'a> FromLuaVec<'a> for $type {
|
impl<'a> FromLuaVec<'a> for $type {
|
||||||
|
@ -435,7 +487,17 @@ macro_rules! impl_from_lua_vec_for_from_lua {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_num() -> Option<usize> {
|
||||||
|
Some(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* impl<'a> IntoLuaVec<'a> for $type {
|
||||||
|
fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>> {
|
||||||
|
Ok(ValueVec::from(self.as_lua(state)?))
|
||||||
|
}
|
||||||
|
} */
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,6 +518,28 @@ impl_from_lua_vec_for_from_lua!(Value, 'a);
|
||||||
impl_from_lua_vec_for_from_lua!(Function, 'a);
|
impl_from_lua_vec_for_from_lua!(Function, 'a);
|
||||||
impl_from_lua_vec_for_from_lua!(AnyUserdata, 'a);
|
impl_from_lua_vec_for_from_lua!(AnyUserdata, 'a);
|
||||||
|
|
||||||
|
/* impl<'a, T: FromLua<'a>> FromLuaVec<'a> for T {
|
||||||
|
fn from_lua_value_vec(state: &'a State, mut values: ValueVec<'a>) -> crate::Result<Self> {
|
||||||
|
if let Some(v) = values.pop_front() {
|
||||||
|
Ok(T::from_lua(state, v)?)
|
||||||
|
} else {
|
||||||
|
Err(Error::Nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
impl<'a, T: AsLua<'a>> IntoLuaVec<'a> for T {
|
||||||
|
fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>> {
|
||||||
|
let mut v = ValueVec::new();
|
||||||
|
|
||||||
|
let sval = self.as_lua(state)?;
|
||||||
|
if !sval.is_none() {
|
||||||
|
v.push_back(sval);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, T: Userdata + 'static> FromLuaVec<'a> for RefMut<'a, T> {
|
impl<'a, T: Userdata + 'static> FromLuaVec<'a> for RefMut<'a, T> {
|
||||||
fn from_lua_value_vec(state: &'a State, mut values: ValueVec<'a>) -> crate::Result<Self> {
|
fn from_lua_value_vec(state: &'a State, mut values: ValueVec<'a>) -> crate::Result<Self> {
|
||||||
|
@ -468,6 +552,10 @@ impl<'a, T: Userdata + 'static> FromLuaVec<'a> for RefMut<'a, T> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_num() -> Option<usize> {
|
||||||
|
Some(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Userdata + 'static> FromLuaVec<'a> for Ref<'a, T> {
|
impl<'a, T: Userdata + 'static> FromLuaVec<'a> for Ref<'a, T> {
|
||||||
|
@ -481,6 +569,10 @@ impl<'a, T: Userdata + 'static> FromLuaVec<'a> for Ref<'a, T> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_num() -> Option<usize> {
|
||||||
|
Some(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: TableProxy> FromLuaVec<'a> for Proxy<T> {
|
impl<'a, T: TableProxy> FromLuaVec<'a> for Proxy<T> {
|
||||||
|
@ -494,6 +586,10 @@ impl<'a, T: TableProxy> FromLuaVec<'a> for Proxy<T> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_num() -> Option<usize> {
|
||||||
|
Some(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromLuaVec<'a> for () {
|
impl<'a> FromLuaVec<'a> for () {
|
||||||
|
@ -507,18 +603,22 @@ impl<'a> FromLuaVec<'a> for () {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> IntoLuaVec<'a> for () {
|
fn value_num() -> Option<usize> {
|
||||||
fn into_lua_value_vec(self, _state: &'a State) -> crate::Result<ValueVec<'a>> {
|
Some(0)
|
||||||
Ok(ValueVec::new())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* impl<'a> IntoLuaVec<'a> for () {
|
||||||
|
fn into_lua_value_vec(self, _state: &'a State) -> crate::Result<ValueVec<'a>> {
|
||||||
|
Ok(ValueVec::new())
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
macro_rules! impl_from_lua_vec_tuple {
|
macro_rules! impl_from_lua_vec_tuple {
|
||||||
( $count: expr, $first: tt, $( $name: tt ),+ ) => (
|
( $count: expr, $last: tt, $( $name: tt ),+ ) => (
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
impl<'a, $first: FromLua<'a>, $($name: FromLua<'a>,)+> FromLuaVec<'a> for ($first, $($name,)+) {
|
impl<'a, $($name: FromLua<'a>,)* $last: FromLuaVec<'a>> FromLuaVec<'a> for ($($name,)* $last,) {
|
||||||
fn from_lua_value_vec(state: &'a State, mut values: ValueVec<'a>) -> crate::Result<Self> {
|
fn from_lua_value_vec(state: &'a State, mut values: ValueVec<'a>) -> crate::Result<Self> {
|
||||||
if values.len() != $count {
|
if values.len() != $count {
|
||||||
return Err(crate::Error::IncorrectArgCount {
|
return Err(crate::Error::IncorrectArgCount {
|
||||||
|
@ -527,36 +627,42 @@ macro_rules! impl_from_lua_vec_tuple {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let f = $first::from_lua(state, values.pop_front().unwrap())
|
|
||||||
.map_err(|e| crate::Error::ValueVecError { value_idx: 0, error: std::sync::Arc::new(e) })?;
|
|
||||||
|
|
||||||
let mut idx = 0;
|
let mut idx = -1; // will be added to 0 on the first iter of the tuple
|
||||||
let ($( $name, )+) = ( $(
|
let ($( $name, )+) = ( $(
|
||||||
$name::from_lua(state, values.pop_front().unwrap())
|
$name::from_lua(state, values.pop_front().unwrap())
|
||||||
.map_err(|e| crate::Error::ValueVecError { value_idx: {idx += 1; idx}, error: std::sync::Arc::new(e) })?,
|
.map_err(|e| crate::Error::ValueVecError { value_idx: {idx += 1; idx}, error: std::sync::Arc::new(e) })?,
|
||||||
)+ );
|
)+ );
|
||||||
|
|
||||||
Ok( (f, $( $name, )+) )
|
let f = $last::from_lua_value_vec(state, values)
|
||||||
|
.map_err(|e| crate::Error::ValueVecError { value_idx: {idx += 1; idx}, error: std::sync::Arc::new(e) })?;
|
||||||
|
|
||||||
|
Ok( ( $( $name, )* f,) )
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value_num() -> Option<usize> {
|
||||||
|
Some($count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
impl<'a, $first: AsLua<'a>, $($name: AsLua<'a>,)+> IntoLuaVec<'a> for ($first, $($name,)+) {
|
impl<'a, $($name: AsLua<'a>,)* $last: IntoLuaVec<'a>,> IntoLuaVec<'a> for ($($name,)+ $last,) {
|
||||||
fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>> {
|
fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>> {
|
||||||
let ($first, $($name,)+) = self;
|
let ($($name,)+ $last,) = self;
|
||||||
let mut vals = ValueVec::new();
|
let mut vals = ValueVec::new();
|
||||||
|
|
||||||
let v = $first.as_lua(state)
|
|
||||||
.map_err(|e| crate::Error::ValueVecError { value_idx: 0, error: std::sync::Arc::new(e) })?;
|
|
||||||
vals.push_back(v);
|
|
||||||
|
|
||||||
let mut idx = 0;
|
let mut idx = -1;
|
||||||
$(
|
$(
|
||||||
let v = $name.as_lua(state)
|
let v = $name.as_lua(state)
|
||||||
.map_err(|e| crate::Error::ValueVecError { value_idx: {idx += 1; idx}, error: std::sync::Arc::new(e) })?;
|
.map_err(|e| crate::Error::ValueVecError { value_idx: {idx += 1; idx}, error: std::sync::Arc::new(e) })?;
|
||||||
vals.push_back(v);
|
vals.push_back(v);
|
||||||
)+
|
)+
|
||||||
|
|
||||||
|
let mut v = $last.into_lua_value_vec(state)
|
||||||
|
.map_err(|e| crate::Error::ValueVecError { value_idx: {idx += 1; idx}, error: std::sync::Arc::new(e) })?;
|
||||||
|
vals.append(&mut v);
|
||||||
|
|
||||||
Ok(vals)
|
Ok(vals)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -579,6 +685,10 @@ macro_rules! impl_from_lua_vec_tuple {
|
||||||
.map_err(|e| crate::Error::ValueVecError { value_idx: 0, error: std::sync::Arc::new(e) })?;
|
.map_err(|e| crate::Error::ValueVecError { value_idx: 0, error: std::sync::Arc::new(e) })?;
|
||||||
Ok( (o,) )
|
Ok( (o,) )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_num() -> Option<usize> {
|
||||||
|
Some(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
|
|
@ -27,20 +27,42 @@ impl<'a, T: FromLua<'a> + AsLua<'a>> DerefMut for Variadic<'a, T> {
|
||||||
impl<'a, T: FromLua<'a> + AsLua<'a>> FromLua<'a> for Variadic<'a, T> {
|
impl<'a, T: FromLua<'a> + AsLua<'a>> FromLua<'a> for Variadic<'a, T> {
|
||||||
fn from_lua(lua: &'a crate::State, val: crate::Value<'a>) -> crate::Result<Self> {
|
fn from_lua(lua: &'a crate::State, val: crate::Value<'a>) -> crate::Result<Self> {
|
||||||
let mut vec = VecDeque::new();
|
let mut vec = VecDeque::new();
|
||||||
let vals = val.into_value_vec()?;
|
let tyname = val.type_name();
|
||||||
|
let vals = val.into_value_vec()
|
||||||
|
.ok_or(Error::Runtime(format!("failure to get Variadic<_> with ValueVec from {}", tyname)))?;
|
||||||
|
//.ok_or(Error::type_mismatch("Variadic<>", &tyname))?;
|
||||||
|
|
||||||
for val in vals.into_iter() {
|
for val in vals.into_iter() {
|
||||||
vec.push_back(
|
vec.push_back(
|
||||||
T::from_lua(lua, val)
|
T::from_lua(lua, val)
|
||||||
.map_err(|e| match e {
|
.map_err(|e| match e {
|
||||||
Error::UnexpectedType(ty, ret) => {
|
Error::TypeMismatch { expected: ty, got, } => {
|
||||||
let ty = format!("Variadic<{}>", ty);
|
let ty = format!("Variadic<{}> from ValueVec", ty);
|
||||||
let ret = format!("ran into {}", ret);
|
Error::TypeMismatch { expected: ty, got }
|
||||||
|
},
|
||||||
|
_ => e,
|
||||||
|
})?
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Error::UnexpectedType(ty, ret)
|
Ok(Self(vec, PhantomData))
|
||||||
},
|
}
|
||||||
_ => e,
|
}
|
||||||
})?
|
|
||||||
|
impl<'a, T: FromLua<'a> + AsLua<'a>> FromLuaVec<'a> for Variadic<'a, T> {
|
||||||
|
fn from_lua_value_vec(state: &'a crate::State, values: ValueVec<'a>) -> crate::Result<Self> {
|
||||||
|
let mut vec = VecDeque::new();
|
||||||
|
|
||||||
|
for val in values.into_iter() {
|
||||||
|
vec.push_back(
|
||||||
|
T::from_lua(state, val)
|
||||||
|
.map_err(|e| match e {
|
||||||
|
Error::TypeMismatch { expected: ty, got, } => {
|
||||||
|
let ty = format!("Variadic<{}> from ValueVec", ty);
|
||||||
|
Error::TypeMismatch { expected: ty, got }
|
||||||
|
},
|
||||||
|
_ => e,
|
||||||
|
})?
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,15 +71,18 @@ impl<'a, T: FromLua<'a> + AsLua<'a>> FromLua<'a> for Variadic<'a, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: FromLua<'a> + AsLua<'a>> AsLua<'a> for Variadic<'a, T> {
|
impl<'a, T: FromLua<'a> + AsLua<'a>> AsLua<'a> for Variadic<'a, T> {
|
||||||
fn as_lua(&self, lua: &'a crate::State) -> crate::Result<crate::Value<'a>> {
|
fn as_lua(self, lua: &'a crate::State) -> crate::Result<crate::Value<'a>> {
|
||||||
let v: Result<VecDeque<Value>, _> = self.0.iter().map(|v| v.as_lua(lua)).collect();
|
let v: Result<VecDeque<Value>, _> = self.0.into_iter()
|
||||||
Value::Variable(ValueVec::from(v?))
|
.map(|v| v.as_lua(lua))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Value::Multi(ValueVec::from(v?))
|
||||||
.as_lua(lua)
|
.as_lua(lua)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: FromLua<'a> + AsLua<'a>> FromLuaVec<'a> for Variadic<'a, T> {
|
/* impl<'a, T: FromLua<'a> + AsLua<'a>> FromLuaVec<'a> for Variadic<'a, T> {
|
||||||
fn from_lua_value_vec(state: &'a crate::State, values: crate::ValueVec<'a>) -> crate::Result<Self> {
|
fn from_lua_value_vec(state: &'a crate::State, values: crate::ValueVec<'a>) -> crate::Result<Self> {
|
||||||
Variadic::from_lua(state, Value::Variable(values))
|
Variadic::from_lua(state, Value::Multi(values))
|
||||||
}
|
}
|
||||||
}
|
} */
|
Loading…
Reference in New Issue