flu 0.0.2

Lua 5.1 framework for Rust
Documentation
use Context;
use ffi;

use stack::Read;
use stack::Push;
use stack::Size;

#[derive(Debug, PartialEq, Eq)]
pub struct LuaRef<'a> {
    cxt: &'a Context,
    key: i32,
}

impl<'a> Drop for LuaRef<'a> {
    fn drop(&mut self) {
        unsafe {
            ffi::luaL_unref(self.cxt.handle, ffi::LUA_REGISTRYINDEX, self.key)
        }
    }
}

impl<'a> Read<'a> for LuaRef<'a> {
    fn read(cxt: &'a Context, idx: i32) -> Self {
        unsafe {
            let t = ffi::LUA_REGISTRYINDEX;

            match ffi::lua_isnil(cxt.handle, idx) {
                true => {
                    cxt.pop_discard(-1);
                    LuaRef { cxt: cxt, key: -1 }
                }
                false => {
                    ffi::lua_rawgeti(cxt.handle, t, ffi::FREELIST_REF);
                    let r = match cxt.pop::<i32>() {
                        0 => {
                            ffi::lua_objlen(cxt.handle, t) as i32 + 1
                        }
                        a @ _ => {
                            ffi::lua_rawgeti(cxt.handle, t, a);
                            ffi::lua_rawseti(cxt.handle, t, ffi::FREELIST_REF);
                            a
                        }
                    };
                    ffi::lua_rawseti(cxt.handle, t, r);

                    LuaRef { cxt: cxt, key: r }
                }
            }
        }
    }

    fn check(cxt: &'a Context, idx: i32) -> bool {
        true
    }
}

impl<'a> Push for LuaRef<'a> {
    fn push(&self, cxt: &Context) {
        unsafe {
            ffi::lua_rawgeti(cxt.handle, ffi::LUA_REGISTRYINDEX, self.key)
        }
    }
}

impl<'a> Size for LuaRef<'a> {
    fn size() -> i32 {
        0
    }
}

#[test]
fn read_ref() {
    let cxt = Context::new();

    cxt.push("Hello world!");

    {
        assert_eq!(cxt.size(), 1);

        let r = cxt.pop::<LuaRef>();

        assert_eq!(cxt.size(), 0);

        cxt.push(r);

        assert_eq!(cxt.pop::<&str>(), "Hello world!");
    }
}