pub mod application; pub mod calculator; use mlua::{ prelude::*, LuaSerdeExt, }; use serde::{Serialize, Deserialize}; #[derive(Deserialize, Serialize, Clone)] pub struct Entry { pub message: String, pub exec: Option<(String, bool)>, } impl IntoLua for Entry { fn into_lua(self, lua: &Lua) -> LuaResult { return lua.to_value(&self) } } impl FromLua for Entry { fn from_lua(value: LuaValue, lua: &Lua) -> LuaResult { return lua.from_value(value); } } #[derive(Default)] pub enum Cache { Valid(Vec), #[default] Stale } pub struct _Lense(pub T); pub trait Lense { const NAME: &'static str; fn set_cache(&mut self, cache: Cache); fn get_cache(&self) -> &Cache; fn query(lua: &Lua, input: String) -> Result, anyhow::Error>; } impl LuaUserData for _Lense { fn add_fields>(fields: &mut F) { // fields.add_field_method_get("cache", |lua, this| { // let cache = this.0.get_cache(); // match cache { // Cache::Valid(cache) => Ok(cache.clone().into_lua(lua)?), // Cache::Stale => Ok(LuaNil) // } // }); // fields.add_field_method_set("cache", |_, this, cache: Vec| { // Ok(this.0.set_cache(Cache::Valid(cache))) // }); fields.add_field_method_get("stale", |_, this| Ok(matches!(this.0.get_cache(), Cache::Stale))); fields.add_field("name", T::NAME); } fn add_methods>(methods: &mut M) { methods.add_method_mut("query", |lua, this, input: String| { return Ok(match this.0.get_cache() { Cache::Valid(entries) => entries.clone(), Cache::Stale => { let entries = T::query(lua, input).map_err(LuaError::external)?; this.0.set_cache(Cache::Valid(entries.clone())); entries } }); }); methods.add_method_mut("mark_stale", |_, this, _: ()| Ok(this.0.set_cache(Cache::Stale)) ); } }