use crate::lock_query::LockQuery;
use crate::locks::LockValue;
use std::marker::PhantomData;
pub struct LockView<'a, T: 'static, L, F>
where
L: LockValue<T> + 'a,
F: Fn(&LockQuery<'a, T, L>) -> LockQuery<'a, T, L>,
{
builder: F,
_phantom: PhantomData<(&'a T, L)>,
}
impl<'a, T: 'static, L, F> LockView<'a, T, L, F>
where
L: LockValue<T> + 'a,
F: Fn(&LockQuery<'a, T, L>) -> LockQuery<'a, T, L>,
{
pub fn new(builder: F) -> Self {
Self {
builder,
_phantom: PhantomData,
}
}
pub fn apply(&self, base: &LockQuery<'a, T, L>) -> LockQuery<'a, T, L>
where
T: Clone,
L: Clone,
{
(self.builder)(base)
}
}
pub struct MaterializedLockView<T>
where
T: Clone,
{
data: Vec<T>,
refresh_fn: Box<dyn Fn() -> Vec<T>>,
}
impl<T> MaterializedLockView<T>
where
T: Clone,
{
pub fn new<F>(refresh_fn: F) -> Self
where
F: Fn() -> Vec<T> + 'static,
{
let data = refresh_fn();
Self {
data,
refresh_fn: Box::new(refresh_fn),
}
}
pub fn get(&self) -> &[T] {
&self.data
}
pub fn refresh(&mut self) {
self.data = (self.refresh_fn)();
}
pub fn count(&self) -> usize {
self.data.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::{Arc, RwLock};
use std::collections::HashMap;
use key_paths_derive::Keypath;
#[derive(Clone, Keypath)]
struct Product {
id: u32,
name: String,
price: f64,
active: bool,
}
#[test]
fn test_materialized_view() {
let mut map = HashMap::new();
map.insert("p1".to_string(), Arc::new(RwLock::new(Product {
id: 1,
name: "A".to_string(),
price: 100.0,
active: true,
})));
let mat_view = MaterializedLockView::new(|| {
vec![Product {
id: 1,
name: "A".to_string(),
price: 100.0,
active: true,
}]
});
assert_eq!(mat_view.count(), 1);
assert_eq!(mat_view.get()[0].name, "A");
}
}