1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
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<LuaValue> {
return lua.to_value(&self)
}
}
impl FromLua for Entry {
fn from_lua(value: LuaValue, lua: &Lua) -> LuaResult<Self> {
return lua.from_value(value);
}
}
#[derive(Default)]
pub enum Cache {
Valid(Vec<Entry>),
#[default]
Stale
}
pub struct _Lense<T: 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<Vec<Entry>, anyhow::Error>;
}
impl<T: Lense + 'static> LuaUserData for _Lense<T> {
fn add_fields<F: LuaUserDataFields<Self>>(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<Entry>| {
// 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<M: LuaUserDataMethods<Self>>(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)) );
}
}
|