use std::{collections::HashMap, path::Path, ptr::addr_of_mut}; use mlua::{Lua, UserData}; use once_cell::sync::Lazy; use crate::lua::{ownedfunction::OwnedFunction, runnable::Runnable}; use self::native::csv::load_csv; use super::{register::SheetId, tablized::Tablized}; pub mod native; #[derive(Default)] pub struct Loader { loaders: HashMap>>, } impl Loader { pub fn new() -> Self { let mut loaders: HashMap>> = HashMap::new(); loaders.insert("csv".to_string(), Box::new(load_csv)); Self { loaders } } pub fn load_sheet(&self, path: String, lua: &Lua) -> Option { let p = Path::new(&path); if p.is_file() { let loader = self.loaders.get(p.extension()?.to_str()?)?; return match loader.run(path, lua) { Ok(table) => table.to_sheet(lua).ok(), Err(_) => None, }; } None } pub fn add(&mut self, extension: String, func: Box>) { self.loaders.insert(extension, func); } pub fn get() -> &'static mut Self { static mut GLOBAL_LOADER: Lazy = Lazy::new(Loader::new); unsafe { &mut *addr_of_mut!(GLOBAL_LOADER) } } } 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)| { Loader::get().add(extension, Box::new(func)); Ok(()) }); } }