Skip to main content

elemental_shared/
loader.rs

1use 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            // Save migrated value
24            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>;