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(())
|
||||
}
|
||||
|
||||
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> {
|
||||
|
@ -298,7 +306,159 @@ impl<'a> FromLuaStack<'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()
|
||||
}
|
||||
}
|
||||
|
||||
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