elemental_shared/
loader.rs1use std::sync::Arc;
2
3use crate::{
4 profile::Profile,
5 version::{Migrator, Persistor, VersionControlled},
6};
7use anyhow::Result;
8use tokio::sync::RwLock;
9
10#[derive(Clone)]
11pub struct Loader<M: Migrator<V>, V: VersionControlled, P: Persistor<V>> {
12 pub inner: Arc<RwLock<V>>,
13 pub migrator: M,
14 pub persistor: P,
15}
16
17impl<M: Migrator<V>, V: VersionControlled, P: Persistor<V>> Loader<M, V, P> {
18 pub async fn load(migrator: M, persistor: P, loader_version: usize) -> Result<Self> {
19 let mut value = persistor.load().await?.unwrap_or_default();
20
21 if !value.is_up_to_date(loader_version) {
22 value = migrator.migrate(value, loader_version)?;
23 persistor.save(&value).await?;
25 }
26
27 Ok(Self {
28 inner: Arc::new(RwLock::new(value)),
29 migrator,
30 persistor,
31 })
32 }
33
34 pub async fn cloned(&self) -> V
35 where
36 V: Clone,
37 {
38 let guard = self.inner.read().await;
39 guard.clone()
40 }
41
42 pub async fn get<T>(&self, f: impl FnOnce(&V) -> T) -> T {
43 let guard = self.inner.read().await;
44 f(&*guard)
45 }
46
47 pub async fn set(&self, f: impl FnOnce(&mut V)) -> Result<()> {
48 let mut guard = self.inner.write().await;
49 f(&mut *guard);
50 self.persistor.save(&*guard).await?;
51 Ok(())
52 }
53}
54
55pub type ProfileLoader<M, C, P> = Loader<M, Profile<C>, P>;