From b747ca8af52129876b577a4f20f7105a05c6b002 Mon Sep 17 00:00:00 2001 From: Nathan Reiner Date: Sat, 10 Aug 2024 15:41:31 +0200 Subject: add global fileloader registry --- src/sheet/loader.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++ src/sheet/mod.rs | 2 ++ src/sheet/register.rs | 10 ++++++--- src/sheet/tablized.rs | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 src/sheet/loader.rs create mode 100644 src/sheet/tablized.rs (limited to 'src/sheet') diff --git a/src/sheet/loader.rs b/src/sheet/loader.rs new file mode 100644 index 0000000..613d2a5 --- /dev/null +++ b/src/sheet/loader.rs @@ -0,0 +1,55 @@ +use std::{ + collections::HashMap, + path::Path, + sync::{Mutex, MutexGuard}, +}; + +use lazy_static::lazy_static; +use mlua::{Lua, UserData}; + +use crate::lua::{ownedfunction::OwnedFunction, runnable::Runnable}; + +use super::{register::SheetId, tablized::Tablized}; + +lazy_static! { + static ref GLOBAL_LOADER: Mutex = Mutex::new(Loader::new()); +} + +#[derive(Default)] +pub struct Loader { + loaders: HashMap>>, +} + +impl Loader { + pub fn new() -> Self { + Self { + loaders: HashMap::new(), + } + } + + pub fn load_sheet(&self, path: String, lua: &Lua) -> Option { + let p = Path::new(&path); + let loader = self.loaders.get(p.extension()?.to_str()?)?; + match loader.run(path, lua) { + Ok(table) => table.to_sheet(lua).ok(), + Err(_) => None, + } + } + + pub fn add(&mut self, extension: String, func: Box>) { + self.loaders.insert(extension, func); + } + + pub fn get() -> MutexGuard<'static, Loader> { + GLOBAL_LOADER.lock().unwrap() + } +} + +impl UserData for Loader { + fn add_methods<'lua, M: mlua::prelude::LuaUserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_function("add", |_, (extension, func): (String, OwnedFunction)| { + GLOBAL_LOADER.lock().unwrap().add(extension, Box::new(func)); + Ok(()) + }); + } +} diff --git a/src/sheet/mod.rs b/src/sheet/mod.rs index ffaec94..118e2ca 100644 --- a/src/sheet/mod.rs +++ b/src/sheet/mod.rs @@ -4,6 +4,8 @@ pub mod cell; pub mod map; pub mod register; pub mod luaref; +pub mod loader; +pub mod tablized; #[derive(Debug, Default)] pub struct Sheet { diff --git a/src/sheet/register.rs b/src/sheet/register.rs index c43720d..aaf9c35 100644 --- a/src/sheet/register.rs +++ b/src/sheet/register.rs @@ -2,7 +2,7 @@ use std::sync::{Arc, RwLock}; use mlua::{Table, UserData, Value}; -use super::{cell::Cell, Sheet, luaref::SheetLuaRef}; +use super::{cell::Cell, loader::Loader, luaref::SheetLuaRef, Sheet}; static REGISTER: RwLock>>> = RwLock::new(Vec::new()); @@ -59,7 +59,7 @@ impl Register { impl UserData for Register { fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) { - methods.add_function_mut("create", |lua, table: Table| { + methods.add_function("create", |lua, table: Table| { let id = Register::create_from_table(table)?; let luaref = SheetLuaRef::new(id); if let Ok(ud) = lua.create_userdata(luaref) { @@ -69,7 +69,11 @@ impl UserData for Register { } }); - methods.add_function_mut("get", |lua, id: SheetId| { + methods.add_function("open", |lua, path: String| { + Ok(Loader::get().load_sheet(path, lua)) + }); + + methods.add_function("get", |lua, id: SheetId| { if Register::get(id).is_some() { let luaref = SheetLuaRef::new(id); if let Ok(ud) = lua.create_userdata(luaref) { diff --git a/src/sheet/tablized.rs b/src/sheet/tablized.rs new file mode 100644 index 0000000..a40af0d --- /dev/null +++ b/src/sheet/tablized.rs @@ -0,0 +1,60 @@ +use mlua::{FromLuaMulti, Lua, RegistryKey}; + +use super::{ + cell::Cell, + register::{Register, SheetId}, +}; + +pub enum Tablized { + Vector(Vec>), + Table(RegistryKey), +} + +impl Tablized { + pub fn to_sheet(&self, lua: &Lua) -> mlua::Result { + match self { + Tablized::Vector(v) => { + let rows = v.len(); + let columns = v + .iter() + .max_by_key(|v| v.len()) + .unwrap_or(&Vec::new()) + .len(); + + let id = Register::create(columns, rows); + let lock = Register::get(id).unwrap(); + let mut sheet = lock.write().unwrap(); + + for row in 0..rows { + for column in 0..columns { + if let Some(value) = v.get(row).and_then(|c| c.get(column)) { + sheet.set_cell(row, column, value.clone()) + } + } + } + + Ok(id) + } + Tablized::Table(key) => { + let table = lua.registry_value(key)?; + Register::create_from_table(table) + }, + } + } +} + +impl<'lua> FromLuaMulti<'lua> for Tablized { + fn from_lua_multi( + values: mlua::prelude::LuaMultiValue<'lua>, + lua: &'lua mlua::prelude::Lua, + ) -> mlua::prelude::LuaResult { + if let Some(value) = values.get(0) { + if value.is_table() { + let key = lua.create_registry_value(value)?; + return Ok(Self::Table(key)); + } + } + + Err(mlua::Error::runtime("table needed")) + } +} -- cgit v1.2.3-70-g09d2