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