ezlua 0.3.1

Ergonomic, efficient and Zero-cost rust bindings to Lua5.4
Documentation
use ezlua::prelude::*;
use serde::{Deserialize, Serialize};
use std::cell::{Ref, RefCell, RefMut};

struct Test {
    a: i32,
}

impl UserData for Test {
    type Trans = RefCell<Self>;

    fn methods(mt: UserdataRegistry<Self>) -> LuaResult<()> {
        mt.register("inc", |mut this: RefMut<Self>| this.a += 1)?;
        Ok(())
    }

    fn getter(fields: UserdataRegistry<Self>) -> LuaResult<()> {
        fields.register("a", |this: Ref<Self>| this.a)?;
        Ok(())
    }

    fn setter(fields: UserdataRegistry<Self>) -> LuaResult<()> {
        fields.register("a", |mut this: RefMut<Self>, val: i32| this.a = val)?;
        Ok(())
    }
}

#[derive(Debug, Default, Deserialize, Serialize)]
struct Config {
    name: String,
    path: String,
    timeout: u64,
    // ...
}

ezlua::impl_tolua_as_serde!(Config);
ezlua::impl_fromlua_as_serde!(Config);

fn main() {
    let s = Lua::with_open_libs();

    let uv = s.new_val(Test { a: 0 }).unwrap();
    assert_eq!(uv.type_of(), LuaType::Userdata);

    s.global().set("uv", uv).unwrap();
    let test_value = 0x11223344;
    s.global().register("test", move || test_value).unwrap();
    s.global()
        .register("toiter", || StaticIter::new(0..3))
        .unwrap();
    s.do_string(
        r#"
        local iter = toiter()
        assert(iter() == 0)
        assert(iter() == 1)
        assert(iter() == 2)
    "#,
        None,
    )
    .unwrap();

    s.do_string("assert(test() == 0x11223344)", None).unwrap();

    s.do_string("print(getmetatable(uv), type(uv))", None)
        .unwrap();
    s.do_string("assert(uv.a == 0)", None).unwrap();
    s.do_string("uv:inc(); assert(uv.a == 1)", None).unwrap();
    s.do_string("uv.a = 3; assert(uv.a == 3)", None).unwrap();
}

pub trait IntoLuaMulti {
    type Target: ToLuaMulti;

    const VALUE_COUNT: Option<usize> = Self::Target::VALUE_COUNT;

    fn value_count(&self) -> Option<usize> {
        Self::VALUE_COUNT
    }

    fn into_lua_multi(self) -> Result<Self::Target>;
}

impl<T: IntoLuaMulti> ToLuaMulti for T {
    fn value_count(&self) -> Option<usize> {
        IntoLuaMulti::value_count(self)
    }

    fn push_multi(self, lua: &State) -> Result<usize> {
        self.into_lua_multi()?.push_multi(lua)
    }
}