Last active
September 6, 2017 10:06
-
-
Save Ruin0x11/77bd93921e895f59dfd929a77be0f3ad to your computer and use it in GitHub Desktop.
Reading back lua userdata by copy with hlua
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[macro_use] extern crate hlua; | |
mod point; | |
use std::fmt::{self, Display}; | |
use hlua::Lua; | |
use point::Point; | |
struct State<'a> { | |
pub lua: Lua<'a>, | |
pub world: World, | |
} | |
pub fn make_grid_from_str<M, F, T>(text: &str, mut constructor: M, mut callback: F) -> T | |
where M: FnMut(Point) -> T, | |
F: FnMut(&Point, char, &mut T) { | |
let mut x = 0; | |
let mut y = 0; | |
let lines = text.split('\n').filter(|l| l.len() > 0).collect::<Vec<_>>(); | |
let height = lines.len(); | |
assert!(height > 0); | |
let width = lines[0].len(); | |
assert!(width > 0); | |
assert!(lines.iter().all(|line| line.chars().count() == width)); | |
let mut thing = constructor(Point::new(height as i32, width as i32)); | |
for line in lines { | |
for ch_at_point in line.chars() { | |
let grid_pos = Point { x: x as i32, y: y as i32 }; | |
callback(&grid_pos, ch_at_point, &mut thing); | |
x += 1; | |
} | |
y += 1; | |
x = 0; | |
} | |
thing | |
} | |
#[derive(Clone)] | |
pub struct World { | |
pub dim: Point, | |
tiles: Vec<char>, | |
} | |
impl World { | |
fn new(p: Point) -> Self { | |
let mut tiles = Vec::new(); | |
for _ in 0..p.x { | |
for _ in 0..p.y { | |
tiles.push(' '); | |
} | |
} | |
World { | |
dim: p, | |
tiles: tiles, | |
} | |
} | |
pub fn in_bounds(&self, pt: &Point) -> bool { | |
*pt >= Point::new(0, 0) && *pt < self.dim | |
} | |
pub fn width(&self) -> i32 { | |
self.dim.x | |
} | |
pub fn height(&self) -> i32 { | |
self.dim.y | |
} | |
pub fn set(&mut self, pt: &Point, val: char) { | |
if self.in_bounds(pt) { | |
let idx = (pt.y * self.dim.x + pt.x) as usize; | |
let mut v = self.tiles.get_mut(idx).unwrap(); | |
*v = val; | |
} | |
} | |
pub fn get(&self, pt: &Point) -> char { | |
if self.in_bounds(pt) { | |
let idx = (pt.y * self.dim.x + pt.x) as usize; | |
self.tiles.get(idx).unwrap().clone() | |
} else { | |
' ' | |
} | |
} | |
} | |
implement_lua_read!(World); | |
implement_lua_push!(World, |mut metatable| { | |
let mut index = metatable.empty_array("__index"); | |
// index.set("__call", hlua::function4(|w: &mut World, x: i32, y: i32, c: char| w.set(&Point::new(x, y), c))) | |
index.set("width", hlua::function1(|w: &mut World| w.width() )); | |
index.set("height", hlua::function1(|w: &mut World| w.height() )); | |
index.set("set", hlua::function4(|w: &mut World, x: i32, y: i32, c: u8) w.set(&Point::new(x,y), c as char)) | |
}); | |
pub fn get_world(s: &str) -> World { | |
let make = |p: Point| World::new(p); | |
let cb = |p: &Point, c: char, world: &mut World| { | |
world.set(p, c) | |
}; | |
make_grid_from_str(s, make, cb) | |
} | |
impl Display for World { | |
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
for i in 0..self.dim.x { | |
for j in 0..self.dim.y { | |
write!(f, "{}", self.get(&Point::new(i, j)))?; | |
} | |
write!(f, "\n")?; | |
} | |
Ok(()) | |
} | |
} | |
fn main() { | |
let mut lua = Lua::new(); | |
lua.openlibs(); | |
let mut world = get_world(" | |
..... | |
..... | |
..@.. | |
..... | |
....."); | |
let mut state = State { | |
lua: lua, | |
world: world, | |
}; | |
println!("{}", state.lua.execute::<u32>("return 6 * 4;").unwrap()); | |
// we create a fill an array named `Sound` which will be used as a class-like interface | |
{ | |
let mut world_namespace = state.lua.empty_array("World"); | |
// creating the `World.new` function | |
world_namespace.set("new", hlua::function2(|x: i32, y: i32| World::new(Point::new(x, y)))); | |
} | |
state.lua.set("w", state.world); | |
state.lua.execute::<()>(r#" | |
print("hello world from within lua!"); | |
print("width", w:width()); | |
print("height", w:height()); | |
w:set(1, 1, 36) | |
"#).unwrap(); | |
impl<'lua, L> hlua::LuaRead<L> for World | |
where L: hlua::AsMutLua<'lua> | |
{ | |
fn lua_read_at_position(lua: L, index: i32) -> Result<World, L> { | |
let val: Result<hlua::UserdataOnStack<World, _>, _> = | |
hlua::LuaRead::lua_read_at_position(lua, index); | |
val.map(|d| d.clone()) | |
} | |
} | |
let w: World = state.lua.get("w").unwrap(); | |
println!("{}", w); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
how do i do this, when my struct has a Type field?