use std::sync::{Arc, RwLock}; use mlua::{Table, UserData, Value}; use super::{cell::Cell, Sheet, luaref::SheetLuaRef}; static REGISTER: RwLock>>> = RwLock::new(Vec::new()); pub type SheetId = usize; #[derive(Debug)] pub struct Register; impl Register { pub fn create(width: usize, height: usize) -> SheetId { let mut register = REGISTER.write().unwrap(); let id = register.len(); let sheet = Sheet::new(width, height, id); register.push(Arc::new(RwLock::new(sheet))); id } pub fn create_from_table(table: Table) -> mlua::Result { let mut register = REGISTER.write().unwrap(); let id = register.len(); let height = table.len()? as usize; let mut width: usize = 0; for column in table.clone().pairs::() { width = width.max(column?.1.len()? as usize) } let mut sheet = Sheet::new(width, height, id); for row_res in table.pairs::() { let (row, c) = row_res?; for column_res in c.pairs::() { let (column, cell) = column_res?; sheet.set_cell(row, column, cell) } } register.push(Arc::new(RwLock::new(sheet))); Ok(id) } pub fn get(id: SheetId) -> Option>> { let register = REGISTER.read().unwrap(); if id < register.len() { Some(Arc::clone(®ister[id])) } else { None } } } impl UserData for Register { fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) { methods.add_function_mut("create", |lua, table: Table| { let id = Register::create_from_table(table)?; let luaref = SheetLuaRef::new(id); if let Ok(ud) = lua.create_userdata(luaref) { Ok(Value::UserData(ud)) } else { Ok(Value::Nil) } }); methods.add_function_mut("get", |lua, id: SheetId| { if Register::get(id).is_some() { let luaref = SheetLuaRef::new(id); if let Ok(ud) = lua.create_userdata(luaref) { Ok(Value::UserData(ud)) } else { Ok(Value::Nil) } } else { Ok(Value::Nil) } }) } }