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>(&self, key: &str, value: &T) -> Result<(), StorageError>;
28
29 async fn get<T: DeserializeOwned + Send + Sync>(&self, key: &str) -> Result<Option<T>, StorageError>;
31
32 async fn remove(&self, key: &str) -> Result<(), StorageError>;
34
35 async fn keys(&self) -> Result<Vec<String>, StorageError>;
37
38 async fn contains_key(&self, key: &str) -> Result<bool, StorageError> {
40 let keys = self.keys().await?;
41 Ok(keys.contains(&key.to_string()))
42 }
43
44 async fn len(&self) -> Result<usize, StorageError> {
46 let keys = self.keys().await?;
47 Ok(keys.len())
48 }
49
50 async fn is_empty(&self) -> Result<bool, StorageError> {
52 self.len().await.map(|l| l == 0)
53 }
54
55 async fn clear(&self) -> Result<(), StorageError> {
57 let keys = self.keys().await?;
58 for key in keys {
59 self.remove(&key).await?;
60 }
61 Ok(())
62 }
63}
64
65#[derive(Clone)]
67pub enum Storage {
68 Memory(memory::MemoryStorage),
69 IndexedDb(indexeddb::IndexedDbStorage),
70}
71
72impl Storage {
73 pub fn memory() -> Self {
74 Self::Memory(memory::MemoryStorage::new())
75 }
76
77 pub fn indexeddb(db_name: String, store_name: String) -> Self {
78 Self::IndexedDb(indexeddb::IndexedDbStorage::new(db_name, store_name))
79 }
80}
81
82#[async_trait]
83impl LocalStorage for Storage {
84 async fn set<T: Serialize + Send + Sync>(&self, key: &str, value: &T) -> Result<(), StorageError> {
85 match self {
86 Storage::Memory(storage) => storage.set(key, value).await,
87 Storage::IndexedDb(storage) => storage.set(key, value).await,
88 }
89 }
90
91 async fn get<T: DeserializeOwned + Send + Sync>(&self, key: &str) -> Result<Option<T>, StorageError> {
92 match self {
93 Storage::Memory(storage) => storage.get(key).await,
94 Storage::IndexedDb(storage) => storage.get(key).await,
95 }
96 }
97
98 async fn remove(&self, key: &str) -> Result<(), StorageError> {
99 match self {
100 Storage::Memory(storage) => storage.remove(key).await,
101 Storage::IndexedDb(storage) => storage.remove(key).await,
102 }
103 }
104
105 async fn keys(&self) -> Result<Vec<String>, StorageError> {
106 match self {
107 Storage::Memory(storage) => storage.keys().await,
108 Storage::IndexedDb(storage) => storage.keys().await,
109 }
110 }
111
112 async fn contains_key(&self, key: &str) -> Result<bool, StorageError> {
113 match self {
114 Storage::Memory(storage) => storage.contains_key(key).await,
115 Storage::IndexedDb(storage) => storage.contains_key(key).await,
116 }
117 }
118
119 async fn len(&self) -> Result<usize, StorageError> {
120 match self {
121 Storage::Memory(storage) => storage.len().await,
122 Storage::IndexedDb(storage) => storage.len().await,
123 }
124 }
125
126 async fn is_empty(&self) -> Result<bool, StorageError> {
127 match self {
128 Storage::Memory(storage) => storage.is_empty().await,
129 Storage::IndexedDb(storage) => storage.is_empty().await,
130 }
131 }
132
133 async fn clear(&self) -> Result<(), StorageError> {
134 match self {
135 Storage::Memory(storage) => storage.clear().await,
136 Storage::IndexedDb(storage) => storage.clear().await,
137 }
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144
145 #[tokio::test]
146 async fn test_storage_enum() {
147 let storage = Storage::memory();
148
149 assert!(storage.set("key1", &"value1".to_string()).await.is_ok());
151 let value = storage.get::<String>("key1").await.unwrap();
152 assert_eq!(value, Some("value1".to_string()));
153
154 assert!(storage.remove("key1").await.is_ok());
156 let value = storage.get::<String>("key1").await.unwrap();
157 assert_eq!(value, None);
158 }
159}