leptos_form_core/
cache.rs

1use ::core::future::Future;
2
3#[cfg(feature = "serde")]
4use ::serde::{de::DeserializeOwned, Serialize};
5
6pub trait Cache<CS: CacheSerializer<T>, T> {
7    type Error: Send;
8    fn get_item(&self, key: &str) -> impl Future<Output = Result<Option<T>, Self::Error>> + Send;
9    fn remove_item(&self, key: &str) -> impl Future<Output = Result<(), Self::Error>> + Send;
10    fn set_item(&self, key: &str, value: &T) -> impl Future<Output = Result<(), Self::Error>> + Send;
11}
12
13pub trait CacheSerializer<T> {
14    type Serialized;
15    type Error: Send;
16    fn serialize(value: &T) -> Result<Self::Serialized, Self::Error>;
17    fn deserialize(serialized: &Self::Serialized) -> Result<T, Self::Error>;
18}
19
20#[cfg(feature = "cache-local-storage")]
21pub struct LocalStorage<T>(pub T);
22
23#[cfg(feature = "cache-serde_json")]
24pub struct SerdeJson;
25
26#[cfg(feature = "serde")]
27pub trait SerdeSerializer {
28    type Serialized;
29    type Error: Send;
30    fn ser<T: Serialize>(value: &T) -> Result<Self::Serialized, Self::Error>;
31    fn de<T: DeserializeOwned>(value: &Self::Serialized) -> Result<T, Self::Error>;
32}
33
34#[cfg(feature = "serde")]
35impl<S: SerdeSerializer, T: DeserializeOwned + Serialize> CacheSerializer<T> for S {
36    type Serialized = S::Serialized;
37    type Error = S::Error;
38    fn serialize(value: &T) -> Result<Self::Serialized, Self::Error> {
39        S::ser(value)
40    }
41    fn deserialize(serialized: &Self::Serialized) -> Result<T, Self::Error> {
42        S::de(serialized)
43    }
44}
45
46#[cfg(feature = "cache-serde_json")]
47impl SerdeSerializer for SerdeJson {
48    type Serialized = String;
49    type Error = serde_json::Error;
50    fn ser<T: Serialize>(value: &T) -> Result<Self::Serialized, Self::Error> {
51        serde_json::to_string(value)
52    }
53    fn de<T: DeserializeOwned>(serialized: &Self::Serialized) -> Result<T, Self::Error> {
54        serde_json::from_str(serialized)
55    }
56}
57
58#[cfg(feature = "cache-local-storage")]
59impl<CS: CacheSerializer<T, Serialized = String>, T> Cache<CS, T> for LocalStorage<CS> {
60    type Error = CS::Error;
61    fn get_item(&self, key: &str) -> impl Future<Output = Result<Option<T>, CS::Error>> + Send {
62        use wasm_bindgen::UnwrapThrowExt;
63        let window = web_sys::window().unwrap_throw();
64        let local_storage = window.local_storage().unwrap_throw().unwrap_throw();
65        let serialized = local_storage.get_item(key).unwrap_throw();
66        async move {
67            let serialized = match serialized {
68                Some(serialized) => serialized,
69                None => return Ok(None),
70            };
71            CS::deserialize(&serialized).map(Some)
72        }
73    }
74    fn remove_item(&self, key: &str) -> impl Future<Output = Result<(), CS::Error>> + Send {
75        use wasm_bindgen::UnwrapThrowExt;
76        let window = web_sys::window().unwrap_throw();
77        let local_storage = window.local_storage().unwrap_throw().unwrap_throw();
78        local_storage.remove_item(key).unwrap_throw();
79        async move { Ok(()) }
80    }
81    fn set_item(&self, key: &str, value: &T) -> impl Future<Output = Result<(), CS::Error>> + Send {
82        use wasm_bindgen::UnwrapThrowExt;
83        let window = web_sys::window().unwrap_throw();
84        let local_storage = window.local_storage().unwrap_throw().unwrap_throw();
85        let res = CS::serialize(value).map(|serialized| local_storage.set_item(key, &serialized).unwrap_throw());
86        async move { res }
87    }
88}