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}