rusty_store/
manager.rs

1use crate::storage::{Storage, StoreError, StoreHandle, Storing};
2
3/// `StoreManager` manages the lifecycle of a store within a specified `Storage` backend. It handles reading and writing store data, as well as providing mutable access to the store's contents.
4///
5/// The `StoreManager` is designed to work with any type that implements the `Storing` trait, allowing it to manage different kinds of store data structures. It abstracts away the complexity of directly interacting with the storage backend, providing an easy-to-use API for managing and persisting store data.
6///
7///
8///
9/// ## Example
10///
11/// ```rust
12/// use serde::{Deserialize, Serialize};
13/// use storage::{StoreManager, Storing};
14///
15/// #[derive(Serialize, Deserialize, Default, Storing)]
16/// pub struct MyStore {
17///     pub count: u32,
18/// }
19///
20/// let storage = Storage::new("APP_ID");
21///
22/// // Create a StoreManager for managing the store data
23/// let mut manager = StoreManager::<MyStore>::new(&storage, "my_store_id")
24///        .expect("Failed to create StoreManager");
25///
26/// // Get a mutable reference to the store
27/// let counter = manager.get_store_mut();
28///
29/// counter.count = 75;
30///
31/// // Save the data to the storage
32/// manager.save().expect("Failed to save count to storage");
33///
34/// let counter = manager.get_store();
35///
36/// println!("Count: {}", counter.count);
37/// ```
38#[derive(Debug, Clone)]
39pub struct StoreManager<T: Storing> {
40    store: Storage,
41    handle: StoreHandle<T>,
42}
43
44impl<T: Storing> StoreManager<T> {
45    /// Creates a new `StoreManager` by reading the store data from the provided `Storage` into the `StoreHandle`.
46    ///
47    /// This function attempts to read the store data from the storage.
48    ///
49    ///
50    /// # Example
51    ///
52    /// ```
53    /// let storage = Storage::new(app_id);
54    /// let handle = StoreHandle::<MyStore>::new("my_store_id");
55    /// let manager = StoreManager::from_handle(&storage, handle).expect("Failed to create StoreManager");
56    /// ```
57    pub fn from_handle(storage: &Storage, mut handle: StoreHandle<T>) -> Result<Self, StoreError> {
58        storage.read(&mut handle)?;
59
60        Ok(Self {
61            store: storage.clone(),
62            handle,
63        })
64    }
65
66    /// Creates a new `StoreManager` by reading the store data from the provided `Storage` into the `StoreHandle`.
67    ///
68    /// This function attempts to read the store data from the storage.
69    ///
70    ///
71    /// # Example
72    ///
73    /// ```
74    /// let storage = Storage::new("APP_ID");
75    /// let manager = StoreManager::new(&storage, "my_store_id").expect("Failed to create StoreManager");
76    /// ```
77    pub fn new(storage: &Storage, store_id: &str) -> Result<Self, StoreError> {
78        let mut handle = StoreHandle::<T>::new(store_id);
79        storage.read(&mut handle)?;
80
81        Ok(Self {
82            store: storage.clone(),
83            handle,
84        })
85    }
86
87    /// Returns a reference to the stored data.
88    pub fn get_store(&self) -> &T {
89        self.handle.get_store()
90    }
91
92    /// Returns a reference to the stored data.
93    pub fn get_store_mut(&mut self) -> &mut T {
94        self.handle.get_store_mut()
95    }
96
97    /// Reads the stored data from the storage.
98    /// This allows to get changes external to the application
99    pub fn get_store_alive(&mut self) -> Result<&T, StoreError> {
100        self.store.read(&mut self.handle)?;
101        Ok(self.handle.get_store())
102    }
103
104    /// Modifies the store and commits the changes to the storage
105    ///
106    /// # Example
107    ///
108    /// ```
109    /// let storage = Storage::new("APP_ID");
110    /// let mut manager = StoreManager::<MyStore>::new(&storage, "my_store_id")
111    ///        .expect("Failed to create StoreManager");
112    ///
113    /// manager.modify_store(|store| store.some_field = 25).expect("Failed to write store modifications");
114    /// ```
115    pub fn modify_store<F>(&mut self, mut change: F) -> Result<(), StoreError>
116    where
117        F: FnMut(&mut T),
118    {
119        let store = self.handle.get_store_mut();
120        change(store);
121        self.save()
122    }
123
124    /// This method is used to modify the store without committing changes to disk.
125    ///
126    /// # Example
127    ///
128    /// ```
129    /// let storage = Storage::new("APP_ID");
130    /// let mut manager = StoreManager::<MyStore>::new(&storage, "my_store_id")
131    ///        .expect("Failed to create StoreManager");
132    ///
133    /// manager.modify_store_uncommitted(|store| store.some_field = 25);
134    ///
135    /// manager.save().expect("Failed to save modifications");
136    /// ```
137    pub fn modify_store_uncommitted<F>(&mut self, mut change: F)
138    where
139        F: FnMut(&mut T),
140    {
141        let store = self.handle.get_store_mut();
142        change(store);
143    }
144
145    /// This method writes the current state of the store to the storage.
146    pub fn save(&mut self) -> Result<(), StoreError> {
147        self.store.write(&mut self.handle)
148    }
149}