summaryrefslogtreecommitdiff
path: root/src/sheet
diff options
context:
space:
mode:
Diffstat (limited to 'src/sheet')
-rw-r--r--src/sheet/loader.rs55
-rw-r--r--src/sheet/mod.rs2
-rw-r--r--src/sheet/register.rs10
-rw-r--r--src/sheet/tablized.rs60
4 files changed, 124 insertions, 3 deletions
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<Loader> = Mutex::new(Loader::new());
+}
+
+#[derive(Default)]
+pub struct Loader {
+ loaders: HashMap<String, Box<dyn Runnable<String, Tablized>>>,
+}
+
+impl Loader {
+ pub fn new() -> Self {
+ Self {
+ loaders: HashMap::new(),
+ }
+ }
+
+ pub fn load_sheet(&self, path: String, lua: &Lua) -> Option<SheetId> {
+ 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<dyn Runnable<String, Tablized>>) {
+ 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<Vec<Arc<RwLock<Sheet>>>> = 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<Vec<Cell>>),
+ Table(RegistryKey),
+}
+
+impl Tablized {
+ pub fn to_sheet(&self, lua: &Lua) -> mlua::Result<SheetId> {
+ 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<Self> {
+ 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"))
+ }
+}