|
12 | 12 | // See the License for the specific language governing permissions and
|
13 | 13 | // limitations under the License
|
14 | 14 |
|
| 15 | +use gloo_utils::format::JsValueSerdeExt; |
| 16 | +use matrix_sdk_crypto::CryptoStoreError; |
| 17 | +use ruma::RoomId; |
| 18 | +use serde::{de::DeserializeOwned, Serialize}; |
| 19 | +use thiserror::Error; |
| 20 | +use wasm_bindgen::JsValue; |
| 21 | +use web_sys::IdbKeyRange; |
| 22 | + |
| 23 | +use crate::{ |
| 24 | + event_cache_store::serializer::traits::{Indexed, IndexedKey, IndexedKeyBounds}, |
| 25 | + serializer::IndexeddbSerializer, |
| 26 | +}; |
| 27 | + |
15 | 28 | mod traits;
|
16 | 29 | mod types;
|
| 30 | + |
| 31 | +#[derive(Debug, Error)] |
| 32 | +pub enum IndexeddbEventCacheStoreSerializerError { |
| 33 | + #[error("indexing: {0}")] |
| 34 | + Indexing(Box<dyn std::error::Error>), |
| 35 | + #[error("serialization: {0}")] |
| 36 | + Serialization(#[from] serde_json::Error), |
| 37 | +} |
| 38 | + |
| 39 | +impl From<serde_wasm_bindgen::Error> for IndexeddbEventCacheStoreSerializerError { |
| 40 | + fn from(e: serde_wasm_bindgen::Error) -> Self { |
| 41 | + Self::Serialization(serde::de::Error::custom(e.to_string())) |
| 42 | + } |
| 43 | +} |
| 44 | + |
| 45 | +/// A (de)serializer for an IndexedDB implementation of [`EventCacheStore`][1]. |
| 46 | +/// |
| 47 | +/// This is primarily a wrapper around [`IndexeddbSerializer`] with a |
| 48 | +/// convenience functions for (de)serializing types specific to the |
| 49 | +/// [`EventCacheStore`][1]. |
| 50 | +/// |
| 51 | +/// [1]: matrix_sdk_base::event_cache::store::EventCacheStore |
| 52 | +pub struct IndexeddbEventCacheStoreSerializer { |
| 53 | + inner: IndexeddbSerializer, |
| 54 | +} |
| 55 | + |
| 56 | +impl IndexeddbEventCacheStoreSerializer { |
| 57 | + pub fn new(inner: IndexeddbSerializer) -> Self { |
| 58 | + Self { inner } |
| 59 | + } |
| 60 | + |
| 61 | + /// Encodes an key for a [`Indexed`] type. |
| 62 | + /// |
| 63 | + /// Note that the particular key which is encoded is defined by the type |
| 64 | + /// `K`. |
| 65 | + pub fn encode_key<T, K>(&self, room_id: &RoomId, components: &K::KeyComponents) -> K |
| 66 | + where |
| 67 | + T: Indexed, |
| 68 | + K: IndexedKey<T>, |
| 69 | + { |
| 70 | + K::encode(room_id, components, &self.inner) |
| 71 | + } |
| 72 | + |
| 73 | + /// Encodes a key for a [`Indexed`] type as a [`JsValue`]. |
| 74 | + /// |
| 75 | + /// Note that the particular key which is encoded is defined by the type |
| 76 | + /// `K`. |
| 77 | + pub fn encode_key_as_value<T, K>( |
| 78 | + &self, |
| 79 | + room_id: &RoomId, |
| 80 | + components: &K::KeyComponents, |
| 81 | + ) -> Result<JsValue, serde_wasm_bindgen::Error> |
| 82 | + where |
| 83 | + T: Indexed, |
| 84 | + K: IndexedKey<T> + Serialize, |
| 85 | + { |
| 86 | + serde_wasm_bindgen::to_value(&self.encode_key::<T, K>(room_id, components)) |
| 87 | + } |
| 88 | + |
| 89 | + /// Encodes the entire key range for an [`Indexed`] type. |
| 90 | + /// |
| 91 | + /// Note that the particular key which is encoded is defined by the type |
| 92 | + /// `K`. |
| 93 | + pub fn encode_key_range<T, K>( |
| 94 | + &self, |
| 95 | + room_id: &RoomId, |
| 96 | + ) -> Result<IdbKeyRange, serde_wasm_bindgen::Error> |
| 97 | + where |
| 98 | + T: Indexed, |
| 99 | + K: IndexedKeyBounds<T> + Serialize, |
| 100 | + { |
| 101 | + let lower = serde_wasm_bindgen::to_value(&K::encode_lower(room_id, &self.inner))?; |
| 102 | + let upper = serde_wasm_bindgen::to_value(&K::encode_upper(room_id, &self.inner))?; |
| 103 | + IdbKeyRange::bound(&lower, &upper).map_err(Into::into) |
| 104 | + } |
| 105 | + |
| 106 | + /// Encodes a bounded key range for an [`Indexed`] type from `lower` to |
| 107 | + /// `upper`. |
| 108 | + /// |
| 109 | + /// Note that the particular key which is encoded is defined by the type |
| 110 | + /// `K`. |
| 111 | + pub fn encode_key_range_from_to<T, K>( |
| 112 | + &self, |
| 113 | + room_id: &RoomId, |
| 114 | + lower: &K::KeyComponents, |
| 115 | + upper: &K::KeyComponents, |
| 116 | + ) -> Result<IdbKeyRange, serde_wasm_bindgen::Error> |
| 117 | + where |
| 118 | + T: Indexed, |
| 119 | + K: IndexedKeyBounds<T> + Serialize, |
| 120 | + { |
| 121 | + let lower = serde_wasm_bindgen::to_value(&K::encode(room_id, lower, &self.inner))?; |
| 122 | + let upper = serde_wasm_bindgen::to_value(&K::encode(room_id, upper, &self.inner))?; |
| 123 | + IdbKeyRange::bound(&lower, &upper).map_err(Into::into) |
| 124 | + } |
| 125 | + |
| 126 | + /// Serializes an [`Indexed`] type into a [`JsValue`] |
| 127 | + pub fn serialize<T>( |
| 128 | + &self, |
| 129 | + room_id: &RoomId, |
| 130 | + t: &T, |
| 131 | + ) -> Result<JsValue, IndexeddbEventCacheStoreSerializerError> |
| 132 | + where |
| 133 | + T: Indexed, |
| 134 | + T::IndexedType: Serialize, |
| 135 | + T::Error: std::error::Error + 'static, |
| 136 | + { |
| 137 | + let indexed = t |
| 138 | + .to_indexed(room_id, &self.inner) |
| 139 | + .map_err(|e| IndexeddbEventCacheStoreSerializerError::Indexing(Box::new(e)))?; |
| 140 | + serde_wasm_bindgen::to_value(&indexed).map_err(Into::into) |
| 141 | + } |
| 142 | + |
| 143 | + /// Deserializes an [`Indexed`] type from a [`JsValue`] |
| 144 | + pub fn deserialize<T>( |
| 145 | + &self, |
| 146 | + value: JsValue, |
| 147 | + ) -> Result<T, IndexeddbEventCacheStoreSerializerError> |
| 148 | + where |
| 149 | + T: Indexed, |
| 150 | + T::IndexedType: DeserializeOwned, |
| 151 | + T::Error: std::error::Error + 'static, |
| 152 | + { |
| 153 | + let indexed: T::IndexedType = value.into_serde()?; |
| 154 | + T::from_indexed(indexed, &self.inner) |
| 155 | + .map_err(|e| IndexeddbEventCacheStoreSerializerError::Indexing(Box::new(e))) |
| 156 | + } |
| 157 | +} |
0 commit comments