Skip to content

Commit

Permalink
ConsumeRead now uses HasLua
Browse files Browse the repository at this point in the history
  • Loading branch information
tomaka committed Jul 21, 2014
1 parent 3466c3d commit 321e35d
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 82 deletions.
6 changes: 3 additions & 3 deletions rust-hl-lua/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ impl<'lua, L: HasLua<'lua>> CopyRead<L> for AnyLuaValue {
}
}

impl<'a,'lua> ConsumeRead<'a,'lua> for AnyLuaValue {
fn read_from_variable(var: LoadedVariable<'a, 'lua>) -> Result<AnyLuaValue, LoadedVariable<'a, 'lua>> {
match CopyRead::read_from_lua(var.lua, -1) {
impl<'a, 'lua, L: HasLua<'lua>> ConsumeRead<'a, L> for AnyLuaValue {
fn read_from_variable(mut var: LoadedVariable<'a, L>) -> Result<AnyLuaValue, LoadedVariable<'a, L>> {
match CopyRead::read_from_lua(&mut var, -1) {
None => Err(var),
Some(a) => Ok(a)
}
Expand Down
44 changes: 24 additions & 20 deletions rust-hl-lua/src/functions_read.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use ffi;
use { Lua, ConsumeRead, CopyRead, LoadedVariable, LuaError, ExecutionError, WrongType, SyntaxError };
use {HasLua, Lua, ConsumeRead, CopyRead, LoadedVariable, LuaError, ExecutionError, WrongType, SyntaxError};

#[unstable]
pub struct LuaFunction<'a,'lua> {
variable: LoadedVariable<'a,'lua>
///
/// Lifetime `'a` represents the lifetime of the function on the stack.
/// Param `L` represents the stack the function has been loaded on and must be a `HasLua`.
pub struct LuaFunction<'a, L> {
variable: LoadedVariable<'a, L>,
}

struct ReadData {
Expand All @@ -22,14 +25,14 @@ extern fn reader(_: *mut ffi::lua_State, dataRaw: *mut ::libc::c_void, size: *mu
data.buffer.as_ptr() as *const ::libc::c_char
}

impl<'a,'lua> LuaFunction<'a,'lua> {
pub fn call<V: CopyRead<Lua<'lua>>>(&mut self) -> Result<V, LuaError> {
impl<'a, 'lua, L: HasLua<'lua>> LuaFunction<'a, L> {
pub fn call<V: CopyRead<LoadedVariable<'a, L>>>(&mut self) -> Result<V, LuaError> {
// calling pcall pops the parameters and pushes output
let pcallReturnValue = unsafe { ffi::lua_pcall(self.variable.lua.lua, 0, 1, 0) }; // TODO:
let pcallReturnValue = unsafe { ffi::lua_pcall(self.variable.use_lua(), 0, 1, 0) }; // TODO:

// if pcall succeeded, returning
if pcallReturnValue == 0 {
return match CopyRead::read_from_lua(self.variable.lua, -1) {
return match CopyRead::read_from_lua(&mut self.variable, -1) {
None => Err(WrongType),
Some(x) => Ok(x)
};
Expand All @@ -41,21 +44,22 @@ impl<'a,'lua> LuaFunction<'a,'lua> {
}

if pcallReturnValue == ffi::LUA_ERRRUN {
let errorMsg: String = CopyRead::read_from_lua(self.variable.lua, -1).expect("can't find error message at the top of the Lua stack");
unsafe { ffi::lua_pop(self.variable.lua.lua, 1) };
return Err(ExecutionError(errorMsg));
unimplemented!()
/*let errorMsg: String = CopyRead::read_from_lua(self.variable.lua, -1).expect("can't find error message at the top of the Lua stack");
unsafe { ffi::lua_pop(self.variable.use_lua(), 1) };
return Err(ExecutionError(errorMsg));*/
}

fail!("Unknown error code returned by lua_pcall: {}", pcallReturnValue)
}

pub fn load_from_reader<R: ::std::io::Reader + 'static>(lua: &'a mut Lua<'lua>, code: R)
-> Result<LuaFunction<'a,'lua>, LuaError>
pub fn load_from_reader<R: ::std::io::Reader + 'static>(lua: &'a mut L, code: R)
-> Result<LuaFunction<'a, L>, LuaError>
{
let readdata = ReadData { reader: box code, buffer: unsafe { ::std::mem::uninitialized() } };

let loadReturnValue = "chunk".with_c_str(|chunk|
unsafe { ffi::lua_load(lua.lua, reader, ::std::mem::transmute(&readdata), chunk, ::std::ptr::null()) }
unsafe { ffi::lua_load(lua.use_lua(), reader, ::std::mem::transmute(&readdata), chunk, ::std::ptr::null()) }
);

if loadReturnValue == 0 {
Expand All @@ -68,7 +72,7 @@ impl<'a,'lua> LuaFunction<'a,'lua> {
}

let errorMsg: String = CopyRead::read_from_lua(lua, -1).expect("can't find error message at the top of the Lua stack");
unsafe { ffi::lua_pop(lua.lua, 1) };
unsafe { ffi::lua_pop(lua.use_lua(), 1) };

if loadReturnValue == ffi::LUA_ERRMEM {
fail!("LUA_ERRMEM");
Expand All @@ -80,8 +84,8 @@ impl<'a,'lua> LuaFunction<'a,'lua> {
fail!("Unknown error while calling lua_load");
}

pub fn load(lua: &'a mut Lua<'lua>, code: &str)
-> Result<LuaFunction<'a,'lua>, LuaError>
pub fn load(lua: &'a mut L, code: &str)
-> Result<LuaFunction<'a, L>, LuaError>
{
let reader = ::std::io::MemReader::new(code.to_c_str().as_bytes().init().to_owned());
LuaFunction::load_from_reader(lua, reader)
Expand All @@ -95,11 +99,11 @@ impl<'a,'lua> LuaFunction<'a,'lua> {
}
}*/

impl<'a,'lua> ConsumeRead<'a,'lua> for LuaFunction<'a,'lua> {
fn read_from_variable(var: LoadedVariable<'a, 'lua>)
-> Result<LuaFunction<'a, 'lua>, LoadedVariable<'a, 'lua>>
impl<'a, 'lua, L: HasLua<'lua>> ConsumeRead<'a, L> for LuaFunction<'a, L> {
fn read_from_variable(mut var: LoadedVariable<'a, L>)
-> Result<LuaFunction<'a, L>, LoadedVariable<'a, L>>
{
if unsafe { ffi::lua_isfunction(var.lua.lua, -1) } {
if unsafe { ffi::lua_isfunction(var.use_lua(), -1) } {
Ok(LuaFunction{ variable: var })
} else {
Err(var)
Expand Down
31 changes: 16 additions & 15 deletions rust-hl-lua/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ impl<'lua> HasLua<'lua> for Lua<'lua> {
}

/// Object which allows access to a Lua variable.
struct LoadedVariable<'var, 'lua> {
lua: &'var mut Lua<'lua>,
size: uint // number of elements at the top of the stack
struct LoadedVariable<'var, L> {
lua: &'var mut L,
size: uint, // number of elements over "lua"
}

impl<'var, 'lua> HasLua<'lua> for LoadedVariable<'var, 'lua> {
impl<'var, 'lua, L: HasLua<'lua>> HasLua<'lua> for LoadedVariable<'var, L> {
fn use_lua(&mut self) -> *mut ffi::lua_State {
self.lua.lua
self.lua.use_lua()
}
}

Expand All @@ -73,9 +73,9 @@ pub trait Push<L> {

/// Should be implemented by types that can be read by consomming a LoadedVariable.
#[unstable]
pub trait ConsumeRead<'a, 'lua> {
pub trait ConsumeRead<'a, L> {
/// Returns the LoadedVariable in case of failure.
fn read_from_variable(var: LoadedVariable<'a, 'lua>) -> Result<Self, LoadedVariable<'a, 'lua>>;
fn read_from_variable(var: LoadedVariable<'a, L>) -> Result<Self, LoadedVariable<'a, L>>;
}

/// Should be implemented by whatever type can be read by copy from the Lua stack.
Expand Down Expand Up @@ -176,21 +176,21 @@ impl<'lua> Lua<'lua> {

/// Executes some Lua code on the context.
#[unstable]
pub fn execute<T: CopyRead<Lua<'lua>>>(&mut self, code: &str) -> Result<T, LuaError> {
pub fn execute<'a, T: CopyRead<LoadedVariable<'a, Lua<'lua>>>>(&'a mut self, code: &str) -> Result<T, LuaError> {
let mut f = try!(functions_read::LuaFunction::load(self, code));
f.call()
}

/// Executes some Lua code on the context.
#[unstable]
pub fn execute_from_reader<T: CopyRead<Lua<'lua>>, R: std::io::Reader + 'static>(&mut self, code: R) -> Result<T, LuaError> {
pub fn execute_from_reader<'a, T: CopyRead<LoadedVariable<'a, Lua<'lua>>>, R: std::io::Reader + 'static>(&'a mut self, code: R) -> Result<T, LuaError> {
let mut f = try!(functions_read::LuaFunction::load_from_reader(self, code));
f.call()
}

/// Loads the value of a global variable.
#[unstable]
pub fn load<'a, I: Str, V: ConsumeRead<'a, 'lua>>(&'a mut self, index: I) -> Option<V> {
pub fn load<'a, I: Str, V: ConsumeRead<'a, Lua<'lua>>>(&'a mut self, index: I) -> Option<V> {
unsafe { ffi::lua_getglobal(self.lua, index.as_slice().to_c_str().unwrap()); }
ConsumeRead::read_from_variable(LoadedVariable { lua: self, size: 1 }).ok()
}
Expand All @@ -210,7 +210,7 @@ impl<'lua> Lua<'lua> {
}

#[unstable]
pub fn load_new_table<'var>(&'var mut self) -> LuaTable<'var, 'lua> {
pub fn load_new_table<'var>(&'var mut self) -> LuaTable<'var, Lua<'lua>> {
unsafe { ffi::lua_newtable(self.lua) };
ConsumeRead::read_from_variable(LoadedVariable { lua: self, size: 1 }).ok().unwrap()
}
Expand All @@ -225,9 +225,10 @@ impl<'lua> Drop for Lua<'lua> {
}
}

#[unsafe_destructor]
impl<'a, 'lua> Drop for LoadedVariable<'a, 'lua> {
// TODO: crashes the compiler

This comment has been minimized.

Copy link
@tomaka

tomaka Jul 21, 2014

Author Owner

See rust-lang/rust#15858

A solution for this must be found before merging

/*#[unsafe_destructor]
impl<'a, 'lua, L: HasLua<'lua>> Drop for LoadedVariable<'a, L> {
fn drop(&mut self) {
unsafe { ffi::lua_pop(self.lua.lua, self.size as libc::c_int) }
unsafe { ffi::lua_pop(self.use_lua(), self.size as libc::c_int) }
}
}
}*/
60 changes: 30 additions & 30 deletions rust-hl-lua/src/lua_tables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,71 @@ use {HasLua, Lua, CopyRead, ConsumeRead, LoadedVariable, Push, Index};
use ffi;

#[unstable]
pub struct LuaTable<'var, 'lua> {
variable: LoadedVariable<'var, 'lua>
pub struct LuaTable<'var, L> {
variable: LoadedVariable<'var, L>
}

impl<'var, 'lua> HasLua<'lua> for LuaTable<'var, 'lua> {
impl<'var, 'lua, L: HasLua<'lua>> HasLua<'lua> for LuaTable<'var, L> {
fn use_lua(&mut self) -> *mut ffi::lua_State {
self.variable.use_lua()
}
}

// while the LuaTableIterator is active, the current key is constantly pushed over the table
#[unstable]
pub struct LuaTableIterator<'var, 'lua, 'table> {
table: &'table mut LuaTable<'var, 'lua>
pub struct LuaTableIterator<'var, 'table, L> {
table: &'table mut LuaTable<'var, L>
}

impl<'var, 'lua, 'table> HasLua<'lua> for LuaTableIterator<'var, 'lua, 'table> {
impl<'var, 'lua, 'table, L: HasLua<'lua>> HasLua<'lua> for LuaTableIterator<'var, 'table, L> {
fn use_lua(&mut self) -> *mut ffi::lua_State {
self.table.use_lua()
}
}

impl<'var, 'lua> ConsumeRead<'var, 'lua> for LuaTable<'var, 'lua> {
fn read_from_variable(var: LoadedVariable<'var, 'lua>)
-> Result<LuaTable<'var, 'lua>, LoadedVariable<'var, 'lua>>
impl<'var, 'lua, L: HasLua<'lua>> ConsumeRead<'var, L> for LuaTable<'var, L> {
fn read_from_variable(mut var: LoadedVariable<'var, L>)
-> Result<LuaTable<'var, L>, LoadedVariable<'var, L>>
{
if unsafe { ffi::lua_istable(var.lua.lua, -1) } {
if unsafe { ffi::lua_istable(var.use_lua(), -1) } {
Ok(LuaTable{ variable: var })
} else {
Err(var)
}
}
}

impl<'var, 'lua> LuaTable<'var, 'lua> {
impl<'var, 'lua, L: HasLua<'lua>> LuaTable<'var, L> {
pub fn iter<'me>(&'me mut self)
-> LuaTableIterator<'var, 'lua, 'me>
-> LuaTableIterator<'var, 'me, L>
{
unsafe { ffi::lua_pushnil(self.variable.lua.lua) };
unsafe { ffi::lua_pushnil(self.variable.use_lua()) };
LuaTableIterator { table: self }
}

pub fn get<R: CopyRead<LuaTable<'var, 'lua>>, I: Index<Lua<'lua>>>(&mut self, index: I) -> Option<R> {
index.push_to_lua(self.variable.lua);
unsafe { ffi::lua_gettable(self.variable.lua.lua, -2); }
pub fn get<R: CopyRead<LuaTable<'var, L>>, I: Index<LuaTable<'var, L>>>(&mut self, index: I) -> Option<R> {
index.push_to_lua(self);
unsafe { ffi::lua_gettable(self.use_lua(), -2); }
let value = CopyRead::read_from_lua(self, -1);
unsafe { ffi::lua_pop(self.variable.lua.lua, 1); }
unsafe { ffi::lua_pop(self.use_lua(), 1); }
value
}

pub fn set<I: Index<Lua<'lua>>, V: Push<Lua<'lua>>>(&mut self, index: I, value: V) {
index.push_to_lua(self.variable.lua);
value.push_to_lua(self.variable.lua);
unsafe { ffi::lua_settable(self.variable.lua.lua, -3); }
pub fn set<I: Index<LuaTable<'var, L>>, V: Push<LuaTable<'var, L>>>(&mut self, index: I, value: V) {
index.push_to_lua(self);
value.push_to_lua(self);
unsafe { ffi::lua_settable(self.use_lua(), -3); }
}

// Obtains or create the metatable of the table
pub fn get_or_create_metatable(mut self) -> LuaTable<'var, 'lua> {
let result = unsafe { ffi::lua_getmetatable(self.variable.lua.lua, -1) };
pub fn get_or_create_metatable(mut self) -> LuaTable<'var, L> {
let result = unsafe { ffi::lua_getmetatable(self.variable.use_lua(), -1) };

if result == 0 {
unsafe {
ffi::lua_newtable(self.variable.lua.lua);
ffi::lua_setmetatable(self.variable.lua.lua, -2);
let r = ffi::lua_getmetatable(self.variable.lua.lua, -1);
ffi::lua_newtable(self.variable.use_lua());
ffi::lua_setmetatable(self.variable.use_lua(), -2);
let r = ffi::lua_getmetatable(self.variable.use_lua(), -1);
assert!(r != 0);
}
}
Expand All @@ -77,22 +77,22 @@ impl<'var, 'lua> LuaTable<'var, 'lua> {
}
}

impl<'a, 'b, 'c, K: CopyRead<LuaTableIterator<'a, 'b, 'c>>, V: CopyRead<LuaTableIterator<'a, 'b, 'c>>>
Iterator<Option<(K, V)>> for LuaTableIterator<'a, 'b, 'c>
impl<'a, 'b, 'lua, L: HasLua<'lua>, K: CopyRead<LuaTableIterator<'a, 'b, L>>, V: CopyRead<LuaTableIterator<'a, 'b, L>>>
Iterator<Option<(K, V)>> for LuaTableIterator<'a, 'b, L>
{
fn next(&mut self)
-> Option<Option<(K,V)>>
{
// this call pushes the next key and value on the stack
if unsafe { ffi::lua_next(self.table.variable.lua.lua, -2) } == 0 {
if unsafe { ffi::lua_next(self.table.use_lua(), -2) } == 0 {
return None
}

let key = CopyRead::read_from_lua(self, -2);
let value = CopyRead::read_from_lua(self, -1);

// removing the value, leaving only the key on the top of the stack
unsafe { ffi::lua_pop(self.table.variable.lua.lua, 1) };
unsafe { ffi::lua_pop(self.table.use_lua(), 1) };

//
if key.is_none() || value.is_none() {
Expand Down
7 changes: 5 additions & 2 deletions rust-hl-lua/src/userdata.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ffi;
use Lua;
use HasLua;
use CopyRead;
use ConsumeRead;
use Push;
Expand All @@ -16,13 +17,15 @@ use std::any::Any;
/// * metatable: Function that fills the metatable of the object.
// TODO: the type must be Send because the Lua context is Send, but this conflicts with &str
#[experimental]
pub fn push_userdata<T: ::std::any::Any>(data: T, lua: &mut Lua, metatable: |&mut LuaTable|) -> uint {
pub fn push_userdata<'a, 'lua, T: ::std::any::Any>(data: T, lua: &'a mut Lua<'lua>, metatable: |&mut LuaTable<'a, Lua<'lua>>|) -> uint {
let typeid = format!("{}", data.get_type_id());

let luaDataRaw = unsafe { ffi::lua_newuserdata(lua.lua, ::std::mem::size_of_val(&data) as ::libc::size_t) };
let luaData: *mut T = unsafe { ::std::mem::transmute(luaDataRaw) };
unsafe { ::std::ptr::write(luaData, data) };

let lua_raw = lua.use_lua();

// creating a metatable
unsafe {
ffi::lua_newtable(lua.lua);
Expand All @@ -44,7 +47,7 @@ pub fn push_userdata<T: ::std::any::Any>(data: T, lua: &mut Lua, metatable: |&mu
::std::mem::forget(table);
}

ffi::lua_setmetatable(lua.lua, -2);
ffi::lua_setmetatable(lua_raw, -2);
}

1
Expand Down
Loading

0 comments on commit 321e35d

Please sign in to comment.