leptos_sync_core/storage/
mod.rs1use async_trait::async_trait;
4use serde::{de::DeserializeOwned, Serialize};
5use thiserror::Error;
6
7pub mod indexeddb;
8pub mod memory;
9
10#[derive(Error, Debug)]
11pub enum StorageError {
12 #[error("Key not found: {0}")]
13 NotFound(String),
14 #[error("Serialization error: {0}")]
15 Serialization(#[from] serde_json::Error),
16 #[error("Storage operation failed: {0}")]
17 OperationFailed(String),
18 #[error("Unsupported operation: {0}")]
19 Unsupported(String),
20}
21
22#[async_trait]
24pub trait LocalStorage: Send + Sync {
25 async fn set<T: Serialize + Send + Sync>(&self, key: &str, value: &T) -> Result<(), StorageError>;
27
28 async fn get<T: DeserializeOwned + Send + Sync>(&self, key: &str) -> Result<Option<T>, StorageError>;
30
31 async fn remove(&self, key: &str) -> Result<(), StorageError>;
33
34 async fn keys(&self) -> Result<Vec<String>, StorageError>;
36
37 async fn contains_key(&self, key: &str) -> Result<bool, StorageError> {
39 let keys = self.keys().await?;
40 Ok(keys.contains(&key.to_string()))
41 }
42
43 async fn len(&self) -> Result<usize, StorageError> {
45 let keys = self.keys().await?;
46 Ok(keys.len())
47 }
48
49 async fn is_empty(&self) -> Result<bool, StorageError> {
51 self.len().await.map(|l| l == 0)
52 }
53
54 async fn clear(&self) -> Result<(), StorageError> {
56 let keys = self.keys().await?;
57 for key in keys {
58 self.remove(&key).await?;
59 }
60 Ok(())
61 }
62}
63
64#[derive(Clone)]
66pub enum Storage {
67 Memory(memory::MemoryStorage),
68 IndexedDb(indexeddb::IndexedDbStorage),
69}
70
71impl Storage {
72 pub fn memory() -> Self {
73 Self::Memory(memory::MemoryStorage::new())
74 }
75
76 pub fn indexeddb(db_name: String, store_name: String) -> Self {
77 Self::IndexedDb(indexeddb::IndexedDbStorage::new(db_name, store_name))
78 }
79}
80
81#[async_trait]
82impl LocalStorage for Storage {
83 async fn set<T: Serialize + Send + Sync>(&self, key: &str, value: &T) -> Result<(), StorageError> {
84 match self {
85 Storage::Memory(storage) => storage.set(key, value).await,
86 Storage::IndexedDb(storage) => storage.set(key, value).await,
87 }
88 }
89
90 async fn get<T: DeserializeOwned + Send + Sync>(&self, key: &str) -> Result<Option<T>, StorageError> {
91 match self {
92 Storage::Memory(storage) => storage.get(key).await,
93 Storage::IndexedDb(storage) => storage.get(key).await,
94 }
95 }
96
97 async fn remove(&self, key: &str) -> Result<(), StorageError> {
98 match self {
99 Storage::Memory(storage) => storage.remove(key).await,
100 Storage::IndexedDb(storage) => storage.remove(key).await,
101 }
102 }
103
104 async fn keys(&self) -> Result<Vec<String>, StorageError> {
105 match self {
106 Storage::Memory(storage) => storage.keys().await,
107 Storage::IndexedDb(storage) => storage.keys().await,
108 }
109 }
110
111 async fn contains_key(&self, key: &str) -> Result<bool, StorageError> {
112 match self {
113 Storage::Memory(storage) => storage.contains_key(key).await,
114 Storage::IndexedDb(storage) => storage.contains_key(key).await,
115 }
116 }
117
118 async fn len(&self) -> Result<usize, StorageError> {
119 match self {
120 Storage::Memory(storage) => storage.len().await,
121 Storage::IndexedDb(storage) => storage.len().await,
122 }
123 }
124
125 async fn is_empty(&self) -> Result<bool, StorageError> {
126 match self {
127 Storage::Memory(storage) => storage.is_empty().await,
128 Storage::IndexedDb(storage) => storage.is_empty().await,
129 }
130 }
131
132 async fn clear(&self) -> Result<(), StorageError> {
133 match self {
134 Storage::Memory(storage) => storage.clear().await,
135 Storage::IndexedDb(storage) => storage.clear().await,
136 }
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[tokio::test]
145 async fn test_storage_enum() {
146 let storage = Storage::memory();
147
148 assert!(storage.set("key1", &"value1".to_string()).await.is_ok());
150 let value = storage.get::<String>("key1").await.unwrap();
151 assert_eq!(value, Some("value1".to_string()));
152
153 assert!(storage.remove("key1").await.is_ok());
155 let value = storage.get::<String>("key1").await.unwrap();
156 assert_eq!(value, None);
157 }
158}