Create TableProxy trait and some table tests
This commit is contained in:
parent
bed5091ecd
commit
7dc4380d5c
162
src/table.rs
162
src/table.rs
|
@ -279,6 +279,14 @@ impl<'a> Table<'a> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_into<T: TableProxy>(self) -> Result<T> {
|
||||||
|
T::from_table(self.state, self)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_from<T: TableProxy + Sized>(state: &'a State, proxy: T) -> Result<Table<'a>> {
|
||||||
|
proxy.as_table(state)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PushToLuaStack<'a> for Table<'a> {
|
impl<'a> PushToLuaStack<'a> for Table<'a> {
|
||||||
|
@ -298,7 +306,159 @@ impl<'a> FromLuaStack<'a> for Table<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromLua<'a> for Table<'a> {
|
impl<'a> FromLua<'a> for Table<'a> {
|
||||||
fn from_lua(_lua: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
fn from_lua(_: &'a State, val: Value<'a>) -> crate::Result<Self> {
|
||||||
val.into_table()
|
val.into_table()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> AsLua<'a> for Table<'a> {
|
||||||
|
fn as_lua(&self, _: &'a State) -> crate::Result<Value<'a>> {
|
||||||
|
Ok(Value::Table(self.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This trait is used for proxying a Rust type to and from Lua as a Lua table. In Lua, you can
|
||||||
|
/// make a representation of your Rust type, then implement this trait on the Rust type. This
|
||||||
|
/// trait allows you to put your Rust type into Lua as the type you created in Lua, and you can
|
||||||
|
/// 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.
|
||||||
|
pub trait TableProxy: Sized {
|
||||||
|
/// Create an instance of `Self` from the table
|
||||||
|
fn from_table<'a>(state: &'a State, table: Table<'a>) -> Result<Self>;
|
||||||
|
/// Creates a Lua instance from `Self`
|
||||||
|
fn as_table<'a>(&self, state: &'a State) -> Result<Table<'a>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::{tests::Vec2, Function, State, StdLibrary, Table, TableProxy};
|
||||||
|
|
||||||
|
impl TableProxy for Vec2 {
|
||||||
|
fn from_table<'a>(_state: &'a crate::State, table: crate::Table<'a>) -> crate::Result<Self> {
|
||||||
|
let x: f32 = table.get("x")?;
|
||||||
|
let y: f32 = table.get("y")?;
|
||||||
|
|
||||||
|
Ok(Vec2 {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_table<'a>(&self, state: &'a crate::State) -> crate::Result<crate::Table<'a>> {
|
||||||
|
let globals = state.globals()?;
|
||||||
|
let vec2: Table = globals.get("Vec2")?;
|
||||||
|
let new_fn: Function = vec2.get("new")?;
|
||||||
|
new_fn.exec((vec2, self.x, self.y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn table_get() -> crate::Result<()> {
|
||||||
|
let lua = State::new();
|
||||||
|
lua.expose_libraries(&[StdLibrary::Debug, StdLibrary::Package]);
|
||||||
|
|
||||||
|
let res = lua.load(
|
||||||
|
"test.lua",
|
||||||
|
r#"
|
||||||
|
text = "Hello, World"
|
||||||
|
"#)?.execute::<_, ()>(());
|
||||||
|
|
||||||
|
// pretty print the error
|
||||||
|
if let Err(err) = res {
|
||||||
|
panic!("{}", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
let globals = lua.globals()?;
|
||||||
|
let text: String = globals.get("text")?;
|
||||||
|
assert_eq!(text, "Hello, World".to_string());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn table_set() -> crate::Result<()> {
|
||||||
|
let lua = State::new();
|
||||||
|
lua.expose_libraries(&[StdLibrary::Debug, StdLibrary::Package]);
|
||||||
|
|
||||||
|
let globals = lua.globals()?;
|
||||||
|
globals.set("text", "Hello, World")?;
|
||||||
|
|
||||||
|
let res = lua.load(
|
||||||
|
"test.lua",
|
||||||
|
r#"
|
||||||
|
assert(text == "Hello, World", "The text was not set correctly")
|
||||||
|
"#)?.execute::<_, ()>(());
|
||||||
|
|
||||||
|
// pretty print the error
|
||||||
|
if let Err(err) = res {
|
||||||
|
panic!("{}", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn table_proxy() -> crate::Result<()> {
|
||||||
|
let lua = State::new();
|
||||||
|
lua.expose_libraries(&[StdLibrary::Debug, StdLibrary::Package]);
|
||||||
|
|
||||||
|
let res = lua.load(
|
||||||
|
"test.lua",
|
||||||
|
r#"
|
||||||
|
Vec2 = { x = 0.0, y = 0.0 }
|
||||||
|
Vec2.__index = Vec2
|
||||||
|
Vec2.__name = "Vec2"
|
||||||
|
|
||||||
|
function Vec2:new(x, y)
|
||||||
|
local v = {}
|
||||||
|
setmetatable(v, Vec2)
|
||||||
|
|
||||||
|
v.x = x
|
||||||
|
v.y = y
|
||||||
|
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
|
||||||
|
function Vec2:__tostring()
|
||||||
|
return "Vec2(" .. self.x .. ", " .. self.y .. ")"
|
||||||
|
end
|
||||||
|
|
||||||
|
function do_math()
|
||||||
|
return Vec2:new(15, 20)
|
||||||
|
end
|
||||||
|
"#)?.execute::<_, ()>(());
|
||||||
|
|
||||||
|
// pretty print the error
|
||||||
|
if let Err(err) = res {
|
||||||
|
panic!("{}", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
let globals = lua.globals()?;
|
||||||
|
let math_fn: Function = globals.get("do_math")?;
|
||||||
|
let lua_vec2: Table = math_fn.exec(())?;
|
||||||
|
let mut vec2 = Vec2::from_table(&lua, lua_vec2)?;
|
||||||
|
assert_eq!(vec2.x, 15.0);
|
||||||
|
assert_eq!(vec2.y, 20.0);
|
||||||
|
|
||||||
|
vec2.x *= 2.0;
|
||||||
|
vec2.y *= 2.0;
|
||||||
|
|
||||||
|
globals.set("pos", vec2.as_table(&lua)?)?;
|
||||||
|
|
||||||
|
let res = lua.load(
|
||||||
|
"test.lua",
|
||||||
|
r#"
|
||||||
|
-- Vec2 stuff is included from last chunk
|
||||||
|
|
||||||
|
assert(type(pos) == "table", "The global 'pos' is not a table like expected of 'as_table'!!")
|
||||||
|
print("pos is " .. tostring(pos))
|
||||||
|
"#)?.execute::<_, ()>(());
|
||||||
|
|
||||||
|
// pretty print the error
|
||||||
|
if let Err(err) = res {
|
||||||
|
panic!("{}", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue