Create a chunk struct, replace the traits created for Function with FromLua, ToLua, FromLuaVec, etc.
This commit is contained in:
parent
2848d1deee
commit
f3c0dc1930
|
@ -0,0 +1,77 @@
|
|||
use std::borrow::{Borrow, Cow};
|
||||
|
||||
use crate::{AsLua, FromLua, Function, State};
|
||||
|
||||
pub struct Chunk<'a> {
|
||||
state: &'a State,
|
||||
name: String,
|
||||
data: Cow<'a, [u8]>,
|
||||
func: Function<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Chunk<'a> {
|
||||
pub(crate) fn new(state: &'a State, name: String, data: Cow<'a, [u8]>, func: Function<'a>) -> Self {
|
||||
Self {
|
||||
state,
|
||||
name,
|
||||
data,
|
||||
func,
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a Lua Chunk from bytes
|
||||
/* pub fn from_bytes(name: &'a str, bytes: &'a [u8]) -> Self {
|
||||
Self {
|
||||
name,
|
||||
data: bytes
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a Lua Chunk from a string
|
||||
pub fn from_str(name: &'a str, text: &'a str) -> Self {
|
||||
Self {
|
||||
name,
|
||||
data: text.as_bytes(),
|
||||
}
|
||||
} */
|
||||
|
||||
/// Execute the chunk in the Lua context
|
||||
pub fn execute<A, R>(&'a self, args: A) -> crate::Result<R>
|
||||
where
|
||||
A: AsLua<'a>,
|
||||
R: FromLua<'a>
|
||||
{
|
||||
self.state.execute_chunk::<A, R>(self, args)
|
||||
}
|
||||
|
||||
/// Returns the name of the Chunk
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
/// Returns the data of the chunk
|
||||
pub fn data(&self) -> &[u8] {
|
||||
self.data.borrow()
|
||||
}
|
||||
|
||||
/// Returns a handle to the chunk's executable function
|
||||
pub fn function(&self) -> Function {
|
||||
self.func.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoChunkData<'a> {
|
||||
fn into_chunk(self) -> Cow<'a, [u8]>;
|
||||
}
|
||||
|
||||
impl<'a> IntoChunkData<'a> for &'a str {
|
||||
fn into_chunk(self) -> Cow<'a, [u8]> {
|
||||
Cow::Borrowed(self.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoChunkData<'a> for &'a [u8] {
|
||||
fn into_chunk(self) -> Cow<'a, [u8]> {
|
||||
Cow::Borrowed(self)
|
||||
}
|
||||
}
|
197
src/function.rs
197
src/function.rs
|
@ -1,13 +1,14 @@
|
|||
use std::ffi::CStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{AsLua, FromLuaStack, LuaRef, PushToLuaStack, StackGuard, State};
|
||||
use crate::{AsLua, FromLua, FromLuaStack, LuaRef, PushToLuaStack, StackGuard, State, Value, ValueVec};
|
||||
|
||||
use mlua_sys as lua;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Function<'a> {
|
||||
state: &'a State,
|
||||
lref: LuaRef
|
||||
lref: LuaRef,
|
||||
pub(crate) error_handler: Option<Arc<Function<'a>>>,
|
||||
}
|
||||
|
||||
impl<'a> FromLuaStack<'a> for Function<'a> {
|
||||
|
@ -15,6 +16,7 @@ impl<'a> FromLuaStack<'a> for Function<'a> {
|
|||
Ok(Self {
|
||||
state,
|
||||
lref: LuaRef::from_stack(state)?,
|
||||
error_handler: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -30,32 +32,66 @@ impl<'a> Function<'a> {
|
|||
Self {
|
||||
state,
|
||||
lref,
|
||||
error_handler: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exec<A, R>(&self, args: A) -> crate::Result<R>
|
||||
where
|
||||
A: PushToLuaStackMulti<'a>,
|
||||
R: FromLuaStackMulti<'a>,
|
||||
A: AsLua<'a>,
|
||||
R: FromLua<'a>,
|
||||
{
|
||||
unsafe {
|
||||
let _g = StackGuard::new(self.state);
|
||||
|
||||
self.push_to_lua_stack(self.state)?;
|
||||
args.push_args_to_lua_stack(self.state)?;
|
||||
|
||||
let arg_len = args.len() as i32;
|
||||
let res_len = R::len() as i32;
|
||||
let s = self.state.state_ptr();
|
||||
if lua::lua_pcall(s, arg_len, res_len, 0) != 0 {
|
||||
let s = lua::lua_tostring(s, -1);
|
||||
let s = CStr::from_ptr(s);
|
||||
let s = s.to_str().unwrap();
|
||||
|
||||
let args_val = args.as_lua(self.state)?;
|
||||
let args_len = match args_val {
|
||||
Value::Variable(v) => v.len(),
|
||||
Value::None => 0,
|
||||
_ => 1,
|
||||
} as _;
|
||||
|
||||
return Err(crate::Error::runtime(s));
|
||||
self.state.ensure_stack(2 + args_len)?;
|
||||
|
||||
let handler_idx = match &self.error_handler {
|
||||
Some(handler) => {
|
||||
handler.push_to_lua_stack(self.state)?;
|
||||
lua::lua_gettop(s)
|
||||
},
|
||||
None => 0,
|
||||
};
|
||||
|
||||
self.push_to_lua_stack(self.state)?;
|
||||
|
||||
let args_val = args.as_lua(self.state)?;
|
||||
args_val.push_to_lua_stack(self.state)?;
|
||||
|
||||
match lua::lua_pcall(s, args_len, lua::LUA_MULTRET, handler_idx) {
|
||||
lua::LUA_ERRRUN => {
|
||||
let er = self.state.get_error_str();
|
||||
return Err(crate::Error::runtime(er));
|
||||
},
|
||||
lua::LUA_ERRMEM => {
|
||||
return Err(crate::Error::MemoryAlloc);
|
||||
},
|
||||
lua::LUA_ERRERR => {
|
||||
let er = self.state.get_error_str();
|
||||
// if this panics, its a bug
|
||||
panic!("Failure when trying to execute error handler function! ({})", er);
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let ret_count = lua::lua_gettop(s);
|
||||
let val = if ret_count > 1 {
|
||||
let vals = ValueVec::from_lua_stack(self.state)?;
|
||||
Value::Variable(vals)
|
||||
} else {
|
||||
Value::from_lua_stack(self.state)?
|
||||
};
|
||||
|
||||
R::results_from_lua_stack(self.state)
|
||||
R::from_lua(self.state, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,129 +100,4 @@ impl<'a> AsLua<'a> for Function<'a> {
|
|||
fn as_lua(&self, _lua: &'a State) -> crate::Result<crate::Value<'a>> {
|
||||
Ok(crate::Value::Function(self.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PushToLuaStackMulti<'a> {
|
||||
fn len(&self) -> usize;
|
||||
fn push_args_to_lua_stack(&self, state: &'a State) -> crate::Result<()>;
|
||||
}
|
||||
|
||||
impl<'a, T> PushToLuaStackMulti<'a> for T
|
||||
where
|
||||
T: PushToLuaStack<'a>,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn push_args_to_lua_stack(&self, state: &'a State) -> crate::Result<()> {
|
||||
unsafe {
|
||||
self.push_to_lua_stack(state)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FromLuaStackMulti<'a>: Sized {
|
||||
fn len() -> usize;
|
||||
fn results_from_lua_stack(state: &'a State) -> crate::Result<Self>;
|
||||
}
|
||||
|
||||
impl<'a> FromLuaStackMulti<'a> for () {
|
||||
fn len() -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn results_from_lua_stack(_state: &'a State) -> crate::Result<Self> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: FromLuaStack<'a>> FromLuaStackMulti<'a> for T {
|
||||
fn len() -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn results_from_lua_stack(state: &'a State) -> crate::Result<Self> {
|
||||
unsafe { T::from_lua_stack(state) }
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_function_arg_tuple {
|
||||
( $count: expr, $first: tt, $( $name: tt ),+ ) => (
|
||||
#[allow(non_snake_case)]
|
||||
impl<'a, $first: PushToLuaStack<'a>, $($name: PushToLuaStack<'a>,)+> PushToLuaStackMulti<'a> for ($first, $($name,)+) {
|
||||
fn len(&self) -> usize {
|
||||
// this will end up generating $count - 1 - 1 - 1... hopefully the compiler will
|
||||
// optimize that out
|
||||
$count
|
||||
}
|
||||
|
||||
fn push_args_to_lua_stack(&self, state: &'a State) -> crate::Result<()> {
|
||||
let ($first, $($name,)+) = self;
|
||||
|
||||
unsafe {
|
||||
$first.push_to_lua_stack(state)?;
|
||||
$( $name.push_to_lua_stack(state)?; )+
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
impl<'a, $first: FromLuaStack<'a>, $($name: FromLuaStack<'a>,)+> FromLuaStackMulti<'a> for ($first, $($name,)+) {
|
||||
fn len() -> usize {
|
||||
$count
|
||||
}
|
||||
|
||||
fn results_from_lua_stack(state: &'a State) -> crate::Result<Self> {
|
||||
unsafe {
|
||||
let ($( $name, )+ $first) = ( $( $name::from_lua_stack(state)?, )+ $first::from_lua_stack(state)? );
|
||||
|
||||
Ok( ($first, $( $name, )+) )
|
||||
}
|
||||
//Ok(unsafe { ( $( $name::from_lua_stack(state)?, )+ $first::from_lua_stack(state)? ) })
|
||||
//Ok(unsafe { ( $first::from_lua_stack(state)?, $( $name::from_lua_stack(state)?, )+ ) })
|
||||
}
|
||||
}
|
||||
|
||||
impl_function_arg_tuple!( $count - 1, $( $name ),+ );
|
||||
);
|
||||
|
||||
// implements PushToLuaStackMulti and FromLuaStackMulti for a tuple with a single element
|
||||
( $count: expr, $only: tt ) => {
|
||||
#[allow(non_snake_case)]
|
||||
impl<'a, $only: PushToLuaStack<'a>> PushToLuaStackMulti<'a> for ($only,) {
|
||||
fn len(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn push_args_to_lua_stack(&self, state: &'a State) -> crate::Result<()> {
|
||||
let (a,) = self;
|
||||
|
||||
unsafe {
|
||||
a.push_to_lua_stack(state)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $only: FromLuaStack<'a>> FromLuaStackMulti<'a> for ($only,) {
|
||||
fn len() -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn results_from_lua_stack(state: &'a State) -> crate::Result<Self> {
|
||||
Ok(unsafe { ( $only::from_lua_stack(state)?, ) })
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// hopefully 16 is more than enough
|
||||
// if you have 16 function results, and need more than 16, you NEED help
|
||||
impl_function_arg_tuple! { 16, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16 }
|
||||
}
|
26
src/main.rs
26
src/main.rs
|
@ -23,6 +23,9 @@ use userdata::*;
|
|||
pub mod util;
|
||||
use util::*;
|
||||
|
||||
pub mod chunk;
|
||||
use chunk::*;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let lua = State::new();
|
||||
lua.expose_libraries(&[StdLibrary::Debug, StdLibrary::Package]);
|
||||
|
@ -37,8 +40,7 @@ fn main() -> Result<()> {
|
|||
let f = lua.create_function(a)?;
|
||||
globals.set("native_test", f)?;
|
||||
|
||||
//let ud = lua.create_userdata("Vec2", Vec2 { x: 0.0, y: 0.0})?;
|
||||
let ud = lua.create_userdata("Vec2", UserdataProxy::<Vec2>::new())?;
|
||||
let ud = lua.create_userdata(UserdataProxy::<Vec2>::new())?;
|
||||
globals.set("Vec2", ud)?;
|
||||
|
||||
let tbl = lua.create_table()?;
|
||||
|
@ -47,7 +49,7 @@ fn main() -> Result<()> {
|
|||
//let globals = lua.globals()?;
|
||||
globals.set("X", tbl)?;
|
||||
|
||||
let res = lua.execute(r#"
|
||||
let chunk = lua.load("text.lua", r#"
|
||||
require "util"
|
||||
|
||||
--[[function dump_table(tbl)
|
||||
|
@ -85,6 +87,7 @@ fn main() -> Result<()> {
|
|||
|
||||
cool_num = 50
|
||||
|
||||
print("Lua is about to exec native_test")
|
||||
local res = native_test(50)
|
||||
print("Lua got " .. res .. " back from rust!")
|
||||
|
||||
|
@ -119,7 +122,13 @@ fn main() -> Result<()> {
|
|||
end
|
||||
|
||||
f3(v1, v2)
|
||||
"#);
|
||||
"#)?;
|
||||
|
||||
// I don't care about the result of this execution, so I set the result as a
|
||||
// Value which can be anything
|
||||
//
|
||||
// Chunks can also be executed with: `chunk.execute(())?;`
|
||||
let res = lua.execute_chunk::<_, Value>(&chunk, ());
|
||||
|
||||
// if unwrapped, the new lines in the message would be escaped making
|
||||
// the traceback in the error difficult to read.
|
||||
|
@ -347,6 +356,7 @@ impl<'a> PushToLuaStack<'a> for &str {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct Vec3 {
|
||||
x: f32,
|
||||
y: f32,
|
||||
|
@ -354,7 +364,7 @@ pub struct Vec3 {
|
|||
}
|
||||
|
||||
impl Userdata for Vec3 {
|
||||
fn build<'a>(builder: &mut UserdataBuilder<'a, Self>) -> crate::Result<()> {
|
||||
fn build<'a>(_builder: &mut UserdataBuilder<'a, Self>) -> crate::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
@ -379,7 +389,7 @@ impl Userdata for Vec2 {
|
|||
.field_setter("y", |_, this, y: f32| this.y = y)
|
||||
|
||||
.function("new", |lua, (x, y)| {
|
||||
lua.create_userdata("Vec2", Vec2 { x, y, })
|
||||
lua.create_userdata(Vec2 { x, y, })
|
||||
})
|
||||
|
||||
// method test
|
||||
|
@ -390,7 +400,7 @@ impl Userdata for Vec2 {
|
|||
let rx = rhs.x;
|
||||
let ry = rhs.y;
|
||||
|
||||
lua.create_userdata("Vec2", Vec2 { x: lx + rx, y: ly + ry, })
|
||||
lua.create_userdata(Vec2 { x: lx + rx, y: ly + ry, })
|
||||
})
|
||||
|
||||
.meta_method(MetaMethod::Add, |lua, lhs: &Vec2, (rhs,): (&Vec2,)| {
|
||||
|
@ -400,7 +410,7 @@ impl Userdata for Vec2 {
|
|||
let rx = rhs.x;
|
||||
let ry = rhs.y;
|
||||
|
||||
lua.create_userdata("Vec2", Vec2 { x: lx + rx, y: ly + ry, })
|
||||
lua.create_userdata(Vec2 { x: lx + rx, y: ly + ry, })
|
||||
});
|
||||
|
||||
Ok(())
|
||||
|
|
82
src/state.rs
82
src/state.rs
|
@ -1,9 +1,9 @@
|
|||
use core::ffi;
|
||||
use std::{alloc::{self, Layout}, any::TypeId, collections::{HashMap, VecDeque}, ffi::{CStr, CString}, mem, ptr::{self, NonNull}, str::Utf8Error};
|
||||
use std::{alloc::{self, Layout}, any::TypeId, collections::HashMap, ffi::{CStr, CString}, mem, ptr::{self, NonNull}, str::Utf8Error, sync::Arc};
|
||||
|
||||
use mlua_sys as lua;
|
||||
|
||||
use crate::{lua_error_guard, AnyUserdata, AsLua, Error, FromLuaStack, FromLuaVec, Function, LuaRef, MetaMethod, PushToLuaStack, PushToLuaStackMulti, Result, StackGuard, Table, Userdata, UserdataBuilder, Value, ValueVec};
|
||||
use crate::{lua_error_guard, AnyUserdata, IntoChunkData, AsLua, Chunk, Error, FromLua, FromLuaStack, FromLuaVec, Function, LuaRef, MetaMethod, PushToLuaStack, Result, StackGuard, Table, Userdata, UserdataBuilder, Value, ValueVec};
|
||||
|
||||
pub fn ptr_to_string(ptr: *const i8) -> std::result::Result<String, Utf8Error> {
|
||||
let c = unsafe { CStr::from_ptr(ptr) };
|
||||
|
@ -150,7 +150,8 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn get_error_str(&self) -> &str {
|
||||
/// Returns the string of an error on the top of the stack
|
||||
pub(crate) unsafe fn get_error_str(&self) -> &str {
|
||||
let error_c = CStr::from_ptr(lua::lua_tostring(self.state_ptr(), -1));
|
||||
let error_str = error_c.to_str()
|
||||
.unwrap_or_else(|_| {
|
||||
|
@ -167,18 +168,24 @@ impl State {
|
|||
self.traceback(Some(&msg))
|
||||
}
|
||||
|
||||
pub fn execute(&self, text: &str) -> Result<()> {
|
||||
let text = format!("{}\0", text);
|
||||
|
||||
pub fn load<'a, C>(&'a self, name: &str, chunk: C) -> Result<Chunk>
|
||||
where
|
||||
C: IntoChunkData<'a> + 'a
|
||||
{
|
||||
unsafe {
|
||||
self.ensure_stack(3)?;
|
||||
self.ensure_stack(1)?;
|
||||
let _g = StackGuard::new(self);
|
||||
let s = self.lua.as_ptr();
|
||||
|
||||
let lua = self.lua.as_ptr();
|
||||
let text_c = text.as_ptr().cast();
|
||||
let chunk_data = chunk.into_chunk();
|
||||
let chunk_ptr = chunk_data.as_ptr().cast();
|
||||
|
||||
// zero terminated name
|
||||
let name_zero = format!("{}\0", name);
|
||||
let name_zero = name_zero.as_ptr().cast();
|
||||
|
||||
// Subtract one from the length to exclude the null terminator
|
||||
match lua::luaL_loadbuffer(self.state_ptr(), text_c, text.len() - 1, "test.lua\0".as_ptr().cast()) {
|
||||
match lua::luaL_loadbuffer(s, chunk_ptr, chunk_data.len() - 1, name_zero) {
|
||||
lua::LUA_ERRSYNTAX => {
|
||||
return Err(Error::Syntax(self.get_error_str().to_string()));
|
||||
},
|
||||
|
@ -188,30 +195,25 @@ impl State {
|
|||
_ => {},
|
||||
}
|
||||
|
||||
let handler = self.create_function(|lua, msg: String| {
|
||||
lua.state_error_handler(msg)
|
||||
})?;
|
||||
handler.push_to_lua_stack(self)?;
|
||||
lua::lua_insert(lua, -2);
|
||||
let func = Function::from_lua_stack(self)?;
|
||||
|
||||
match lua::lua_pcall(lua, 0, lua::LUA_MULTRET, -2) {
|
||||
lua::LUA_ERRRUN => {
|
||||
let er = self.get_error_str();
|
||||
return Err(Error::runtime(er));
|
||||
},
|
||||
lua::LUA_ERRMEM => {
|
||||
return Err(Error::MemoryAlloc);
|
||||
},
|
||||
lua::LUA_ERRERR => {
|
||||
let er = self.get_error_str();
|
||||
// if this panics, its a bug
|
||||
panic!("Failure when trying to execute error handler function! ({})", er);
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
Ok(Chunk::new(self, name.to_string(), chunk_data, func))
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
pub fn execute_chunk<'a, A, R>(&'a self, chunk: &'a Chunk, args: A) -> Result<R>
|
||||
where
|
||||
A: AsLua<'a>,
|
||||
R: FromLua<'a>
|
||||
{
|
||||
let handler = self.create_function(|lua, msg: String| {
|
||||
lua.state_error_handler(msg)
|
||||
})?;
|
||||
|
||||
let mut chunk_func = chunk.function();
|
||||
chunk_func.error_handler = Some(Arc::new(handler));
|
||||
|
||||
chunk_func.exec::<A, R>(args)
|
||||
}
|
||||
|
||||
pub fn expose_libraries<L: Into<StdLibraries>>(&self, libs: L) {
|
||||
|
@ -283,7 +285,7 @@ impl State {
|
|||
pub fn create_function<'a, A, R, F>(&self, f: F) -> Result<Function>
|
||||
where
|
||||
A: FromLuaVec<'a>,
|
||||
R: PushToLuaStackMulti<'a>,
|
||||
R: AsLua<'a>, //PushToLuaStackMulti<'a>,
|
||||
F: Fn(&'a State, A) -> Result<R> + 'static,
|
||||
{
|
||||
unsafe extern "C-unwind" fn rust_closure(s: *mut lua::lua_State) -> i32 {
|
||||
|
@ -332,11 +334,21 @@ impl State {
|
|||
|
||||
lua_error_guard(lua, || {
|
||||
let vec = ValueVec::from_lua_stack(lua)?;
|
||||
|
||||
let args = A::from_lua_value_vec(lua, vec)?;
|
||||
|
||||
let r = f(lua, args)?;
|
||||
r.push_args_to_lua_stack(lua)?;
|
||||
Ok(r.len() as i32)
|
||||
let r_val = r.as_lua(lua)?;
|
||||
|
||||
let args_len = match &r_val {
|
||||
Value::Variable(v) => v.len(),
|
||||
Value::None => 0,
|
||||
_ => 1,
|
||||
} as _;
|
||||
|
||||
r_val.push_to_lua_stack(lua)?;
|
||||
|
||||
Ok(args_len)
|
||||
})
|
||||
}
|
||||
};
|
||||
|
@ -361,7 +373,7 @@ impl State {
|
|||
}
|
||||
|
||||
/// Create userdata
|
||||
pub fn create_userdata<T: Userdata + 'static>(&self, name: &str, data: T) -> Result<AnyUserdata> {
|
||||
pub fn create_userdata<T: Userdata + 'static>(&self, data: T) -> Result<AnyUserdata> {
|
||||
unsafe {
|
||||
self.ensure_stack(2)?;
|
||||
let _g = StackGuard::new(self);
|
||||
|
|
114
src/value.rs
114
src/value.rs
|
@ -15,6 +15,7 @@ pub enum Value<'a> {
|
|||
Function(Function<'a>),
|
||||
Table(Table<'a>),
|
||||
Userdata(AnyUserdata<'a>),
|
||||
Variable(ValueVec<'a>),
|
||||
}
|
||||
|
||||
impl<'a> Value<'a> {
|
||||
|
@ -31,6 +32,7 @@ impl<'a> Value<'a> {
|
|||
Value::Function(_) => "Function".to_string(),
|
||||
Value::Table(_) => "Table".to_string(),
|
||||
Value::Userdata(ud) => ud.name().unwrap(),
|
||||
Value::Variable(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,9 +81,7 @@ impl<'a> PushToLuaStack<'a> for Value<'a> {
|
|||
let s = state.state_ptr();
|
||||
|
||||
match self {
|
||||
Value::None => {
|
||||
|
||||
},
|
||||
Value::None => { },
|
||||
Value::Nil => {
|
||||
state.ensure_stack(1)?;
|
||||
lua::lua_pushnil(s);
|
||||
|
@ -100,6 +100,11 @@ impl<'a> PushToLuaStack<'a> for Value<'a> {
|
|||
Value::Function(f) => f.push_to_lua_stack(state)?,
|
||||
Value::Table(t) => t.push_to_lua_stack(state)?,
|
||||
Value::Userdata(ud) => ud.push_to_lua_stack(state)?,
|
||||
Value::Variable(v) => {
|
||||
for v in v.iter() {
|
||||
v.push_to_lua_stack(state)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -108,10 +113,13 @@ impl<'a> PushToLuaStack<'a> for Value<'a> {
|
|||
|
||||
impl<'a> FromLuaStack<'a> for Value<'a> {
|
||||
unsafe fn from_lua_stack(state: &'a State) -> crate::Result<Self> {
|
||||
|
||||
let s = state.state_ptr();
|
||||
let ty = lua::lua_type(s, -1);
|
||||
|
||||
if lua::lua_gettop(s) == 0 {
|
||||
return Ok(Self::None);
|
||||
}
|
||||
|
||||
let ty = lua::lua_type(s, -1);
|
||||
let val = match ty {
|
||||
lua::LUA_TNIL => {
|
||||
lua::lua_pop(s, 1);
|
||||
|
@ -129,8 +137,9 @@ impl<'a> FromLuaStack<'a> for Value<'a> {
|
|||
lua::lua_pop(s, 1);
|
||||
|
||||
let cstr = CStr::from_ptr(cstr);
|
||||
let lua_str = cstr.to_str().unwrap().to_string();
|
||||
Ok(Value::String(lua_str))
|
||||
let lua_str = cstr.to_string_lossy();
|
||||
//let lua_str = cstr.to_str().unwrap().to_string();
|
||||
Ok(Value::String(lua_str.to_string()))
|
||||
},
|
||||
lua::LUA_TFUNCTION => {
|
||||
Function::from_lua_stack(state)
|
||||
|
@ -166,7 +175,25 @@ pub trait FromLua<'a>: Sized {
|
|||
|
||||
impl<'a> AsLua<'a> for () {
|
||||
fn as_lua(&self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
||||
Ok(Value::Nil)
|
||||
Ok(Value::None)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsLua<'a> for Value<'a> {
|
||||
fn as_lua(&self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
||||
Ok(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsLua<'a> for String {
|
||||
fn as_lua(&self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
||||
Ok(Value::String(self.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsLua<'a> for &'a str {
|
||||
fn as_lua(&self, _lua: &'a State) -> crate::Result<Value<'a>> {
|
||||
Ok(Value::String(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,7 +203,13 @@ impl<'a> FromLua<'a> for Value<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
impl<'a> FromLua<'a> for () {
|
||||
fn from_lua(_lua: &'a State, _val: Value<'a>) -> crate::Result<Self> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct ValueVec<'a>(VecDeque<Value<'a>>);
|
||||
|
||||
impl<'a> Deref for ValueVec<'a> {
|
||||
|
@ -238,11 +271,32 @@ pub trait FromLuaVec<'a>: Sized {
|
|||
fn from_lua_value_vec(state: &'a State, values: ValueVec<'a>) -> crate::Result<Self>;
|
||||
}
|
||||
|
||||
impl<'a> FromLuaVec<'a> for () {
|
||||
fn from_lua_value_vec(_state: &'a State, _values: ValueVec<'a>) -> crate::Result<Self> {
|
||||
Ok(())
|
||||
pub trait IntoLuaVec<'a>: Sized {
|
||||
fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>>;
|
||||
}
|
||||
|
||||
/* impl<'a> FromLuaVec<'a> for ValueVec<'a> {
|
||||
fn from_lua_value_vec(_state: &'a State, values: ValueVec<'a>) -> crate::Result<Self> {
|
||||
Ok(values)
|
||||
}
|
||||
}
|
||||
*/
|
||||
impl<'a> IntoLuaVec<'a> for ValueVec<'a> {
|
||||
fn into_lua_value_vec(self, _state: &'a State) -> crate::Result<ValueVec<'a>> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
/* impl<'a> FromLua<'a> for ValueVec<'a> {
|
||||
fn from_lua(_lua: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
||||
match val {
|
||||
Value::Variable(v) => Ok(v),
|
||||
_ => {
|
||||
Ok(ValueVec::from(val))
|
||||
}
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
impl<'a> FromLuaVec<'a> for ValueVec<'a> {
|
||||
fn from_lua_value_vec(_state: &'a State, values: ValueVec<'a>) -> crate::Result<Self> {
|
||||
|
@ -267,7 +321,6 @@ macro_rules! impl_from_lua_vec_tuple {
|
|||
( $count: expr, $first: tt, $( $name: tt ),+ ) => (
|
||||
#[allow(non_snake_case)]
|
||||
impl<'a, $first: FromLua<'a>, $($name: FromLua<'a>,)+> FromLuaVec<'a> for ($first, $($name,)+) {
|
||||
|
||||
fn from_lua_value_vec(state: &'a State, mut values: ValueVec<'a>) -> crate::Result<Self> {
|
||||
if values.len() != $count {
|
||||
return Err(crate::Error::IncorrectArgCount {
|
||||
|
@ -289,6 +342,27 @@ macro_rules! impl_from_lua_vec_tuple {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
impl<'a, $first: AsLua<'a>, $($name: AsLua<'a>,)+> IntoLuaVec<'a> for ($first, $($name,)+) {
|
||||
fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>> {
|
||||
let ($first, $($name,)+) = self;
|
||||
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 v = $name.as_lua(state)
|
||||
.map_err(|e| crate::Error::ValueVecError { value_idx: {idx += 1; idx}, error: std::sync::Arc::new(e) })?;
|
||||
vals.push_back(v);
|
||||
)+
|
||||
|
||||
Ok(vals)
|
||||
}
|
||||
}
|
||||
|
||||
impl_from_lua_vec_tuple!( $count - 1, $( $name ),+ );
|
||||
);
|
||||
|
||||
|
@ -308,6 +382,20 @@ macro_rules! impl_from_lua_vec_tuple {
|
|||
Ok( (o,) )
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
impl<'a, $only: AsLua<'a>> IntoLuaVec<'a> for ($only,) {
|
||||
fn into_lua_value_vec(self, state: &'a State) -> crate::Result<ValueVec<'a>> {
|
||||
let ($only,) = self;
|
||||
let mut vals = ValueVec::new();
|
||||
|
||||
let v = $only.as_lua(state)
|
||||
.map_err(|e| crate::Error::ValueVecError { value_idx: 0, error: std::sync::Arc::new(e) })?;
|
||||
vals.push_back(v);
|
||||
|
||||
Ok(vals)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue