diff --git a/crates/matrix-sdk-indexeddb/src/event_cache_store/migrations.rs b/crates/matrix-sdk-indexeddb/src/event_cache_store/migrations.rs index fbc2a9342..29fe44ad2 100644 --- a/crates/matrix-sdk-indexeddb/src/event_cache_store/migrations.rs +++ b/crates/matrix-sdk-indexeddb/src/event_cache_store/migrations.rs @@ -109,6 +109,7 @@ pub mod v1 { pub mod keys { pub const CORE: &str = "core"; + pub const ROOMS: &str = "rooms"; pub const LINKED_CHUNKS: &str = "linked_chunks"; pub const LINKED_CHUNKS_KEY_PATH: &str = "id"; pub const LINKED_CHUNKS_NEXT: &str = "linked_chunks_next"; diff --git a/crates/matrix-sdk-indexeddb/src/event_cache_store/serializer/types.rs b/crates/matrix-sdk-indexeddb/src/event_cache_store/serializer/types.rs index 93f3e4199..880d1c746 100644 --- a/crates/matrix-sdk-indexeddb/src/event_cache_store/serializer/types.rs +++ b/crates/matrix-sdk-indexeddb/src/event_cache_store/serializer/types.rs @@ -27,9 +27,19 @@ //! These types mimic the structure of the object stores and indices created in //! [`crate::event_cache_store::migrations`]. +use matrix_sdk_base::linked_chunk::ChunkIdentifier; +use matrix_sdk_crypto::CryptoStoreError; +use ruma::RoomId; use serde::{Deserialize, Serialize}; -use crate::serializer::MaybeEncrypted; +use crate::{ + event_cache_store::{ + migrations::current::keys, + serializer::traits::{Indexed, IndexedKey, IndexedKeyBounds}, + types::Chunk, + }, + serializer::{IndexeddbSerializer, MaybeEncrypted}, +}; /// Represents the [`LINKED_CHUNKS`][1] object store. /// @@ -46,6 +56,38 @@ pub struct IndexedChunk { pub content: IndexedChunkContent, } +impl Indexed for Chunk { + type IndexedType = IndexedChunk; + type Error = CryptoStoreError; + + fn to_indexed( + &self, + room_id: &RoomId, + serializer: &IndexeddbSerializer, + ) -> Result { + Ok(IndexedChunk { + id: >::encode( + room_id, + &ChunkIdentifier::new(self.identifier), + serializer, + ), + next: IndexedNextChunkIdKey::encode( + room_id, + &self.next.map(ChunkIdentifier::new), + serializer, + ), + content: serializer.maybe_encrypt_value(self)?, + }) + } + + fn from_indexed( + indexed: Self::IndexedType, + serializer: &IndexeddbSerializer, + ) -> Result { + serializer.maybe_decrypt_value(indexed.content) + } +} + /// The value associated with the [primary key](IndexedChunk::id) of the /// [`LINKED_CHUNKS`][1] object store, which is constructed from: /// @@ -56,6 +98,34 @@ pub struct IndexedChunk { #[derive(Debug, Serialize, Deserialize)] pub struct IndexedChunkIdKey(IndexedRoomId, IndexedChunkId); +impl IndexedKey for IndexedChunkIdKey { + type KeyComponents = ChunkIdentifier; + + fn encode( + room_id: &RoomId, + chunk_id: &ChunkIdentifier, + serializer: &IndexeddbSerializer, + ) -> Self { + let room_id = serializer.encode_key_as_string(keys::ROOMS, room_id); + let chunk_id = chunk_id.index(); + Self(room_id, chunk_id) + } +} + +impl IndexedKeyBounds for IndexedChunkIdKey { + fn encode_lower(room_id: &RoomId, serializer: &IndexeddbSerializer) -> Self { + >::encode(room_id, &ChunkIdentifier::new(0), serializer) + } + + fn encode_upper(room_id: &RoomId, serializer: &IndexeddbSerializer) -> Self { + >::encode( + room_id, + &ChunkIdentifier::new(js_sys::Number::MAX_SAFE_INTEGER as u64), + serializer, + ) + } +} + pub type IndexedRoomId = String; pub type IndexedChunkId = u64; pub type IndexedChunkContent = MaybeEncrypted; @@ -84,6 +154,41 @@ pub enum IndexedNextChunkIdKey { Some(IndexedChunkIdKey), } +impl IndexedKey for IndexedNextChunkIdKey { + type KeyComponents = Option; + + fn encode( + room_id: &RoomId, + next_chunk_id: &Option, + serializer: &IndexeddbSerializer, + ) -> Self { + next_chunk_id + .map(|id| { + Self::Some(>::encode( + room_id, &id, serializer, + )) + }) + .unwrap_or_else(|| { + let room_id = serializer.encode_key_as_string(keys::ROOMS, room_id); + Self::none(room_id) + }) + } +} + +impl IndexedKeyBounds for IndexedNextChunkIdKey { + fn encode_lower(room_id: &RoomId, serializer: &IndexeddbSerializer) -> Self { + >::encode(room_id, &None, serializer) + } + + fn encode_upper(room_id: &RoomId, serializer: &IndexeddbSerializer) -> Self { + >::encode( + room_id, + &Some(ChunkIdentifier::new(js_sys::Number::MAX_SAFE_INTEGER as u64)), + serializer, + ) + } +} + /// Represents the [`EVENTS`][1] object store. /// /// [1]: crate::event_cache_store::migrations::v1::create_events_object_store