diff --git a/crates/matrix-sdk-sled/src/cryptostore.rs b/crates/matrix-sdk-sled/src/cryptostore.rs index c37be9cac..fd9240e29 100644 --- a/crates/matrix-sdk-sled/src/cryptostore.rs +++ b/crates/matrix-sdk-sled/src/cryptostore.rs @@ -50,6 +50,7 @@ use sled::{ use tracing::debug; use super::OpenStoreError; +use crate::encode_key::{EncodeKey, ENCODE_SEPARATOR}; const DATABASE_VERSION: u8 = 4; @@ -64,32 +65,25 @@ const OUTBOUND_GROUP_TABLE_NAME: &str = "crypto-store-outbound-group-sessions"; const SECRET_REQUEST_BY_INFO_TABLE: &str = "crypto-store-secret-request-by-info"; const TRACKED_USERS_TABLE: &str = "crypto-store-secret-tracked-users"; -trait EncodeKey { - const SEPARATOR: u8 = 0xff; - fn encode(&self) -> Vec; -} - -impl EncodeKey for &T { +impl EncodeKey for InboundGroupSession { fn encode(&self) -> Vec { - T::encode(self) + (self.room_id(), self.sender_key(), self.session_id()).encode() } } -impl EncodeKey for Box { +impl EncodeKey for OutboundGroupSession { fn encode(&self) -> Vec { - T::encode(self) + self.room_id().encode() } } -impl EncodeKey for TransactionId { +impl EncodeKey for Session { fn encode(&self) -> Vec { - self.as_str().encode() - } -} + let sender_key = self.sender_key().to_base64(); + let session_id = self.session_id(); -impl EncodeKey for SecretName { - fn encode(&self) -> Vec { - [self.as_ref().as_bytes(), &[Self::SEPARATOR]].concat() + [sender_key.as_bytes(), &[ENCODE_SEPARATOR], session_id.as_bytes(), &[ENCODE_SEPARATOR]] + .concat() } } @@ -104,29 +98,13 @@ impl EncodeKey for SecretInfo { impl EncodeKey for RequestedKeyInfo { fn encode(&self) -> Vec { - [ - self.room_id.as_bytes(), - &[Self::SEPARATOR], - self.sender_key.as_bytes(), - &[Self::SEPARATOR], - self.algorithm.as_ref().as_bytes(), - &[Self::SEPARATOR], - self.session_id.as_bytes(), - &[Self::SEPARATOR], - ] - .concat() - } -} - -impl EncodeKey for UserId { - fn encode(&self) -> Vec { - self.as_str().encode() + (&self.room_id, &self.sender_key, &self.algorithm, &self.session_id).encode() } } impl EncodeKey for ReadOnlyDevice { fn encode(&self) -> Vec { - (self.user_id().as_str(), self.device_id().as_str()).encode() + (self.user_id(), self.device_id()).encode() } } @@ -135,7 +113,8 @@ impl EncodeSecureKey for (&UserId, &DeviceId) { let user_id = store_cipher.hash_key(table_name, self.0.as_bytes()); let device_id = store_cipher.hash_key(table_name, self.1.as_bytes()); - (user_id, device_id).encode() + [user_id.as_slice(), &[ENCODE_SEPARATOR], device_id.as_slice(), &[ENCODE_SEPARATOR]] + .concat() } } @@ -152,7 +131,7 @@ impl EncodeSecureKey for SecretName { fn encode_secure(&self, table_name: &str, store_cipher: &StoreCipher) -> Vec { let name = store_cipher.hash_key(table_name, self.as_ref().as_bytes()); - [name.as_slice(), &[Self::SEPARATOR]].concat() + [name.as_slice(), &[ENCODE_SEPARATOR]].concat() } } @@ -165,13 +144,13 @@ impl EncodeSecureKey for RequestedKeyInfo { [ room_id.as_slice(), - &[Self::SEPARATOR], + &[ENCODE_SEPARATOR], sender_key.as_slice(), - &[Self::SEPARATOR], + &[ENCODE_SEPARATOR], algorithm.as_slice(), - &[Self::SEPARATOR], + &[ENCODE_SEPARATOR], session_id.as_slice(), - &[Self::SEPARATOR], + &[ENCODE_SEPARATOR], ] .concat() } @@ -191,20 +170,10 @@ impl EncodeSecureKey for ReadOnlyDevice { } } -impl EncodeKey for Session { - fn encode(&self) -> Vec { - let sender_key = self.sender_key().to_base64(); - let session_id = self.session_id(); - - [sender_key.as_bytes(), &[Self::SEPARATOR], session_id.as_bytes(), &[Self::SEPARATOR]] - .concat() - } -} - impl EncodeSecureKey for str { fn encode_secure(&self, table_name: &str, store_cipher: &StoreCipher) -> Vec { let key = store_cipher.hash_key(table_name, self.as_bytes()); - [key.as_slice(), &[Self::SEPARATOR]].concat() + [key.as_slice(), &[ENCODE_SEPARATOR]].concat() } } @@ -218,7 +187,7 @@ impl EncodeSecureKey for RoomId { fn encode_secure(&self, table_name: &str, store_cipher: &StoreCipher) -> Vec { let room_id = store_cipher.hash_key(table_name, self.as_bytes()); - [room_id.as_slice(), &[Self::SEPARATOR]].concat() + [room_id.as_slice(), &[ENCODE_SEPARATOR]].concat() } } @@ -237,11 +206,11 @@ impl EncodeSecureKey for (&RoomId, &str, &str) { [ first.as_slice(), - &[Self::SEPARATOR], + &[ENCODE_SEPARATOR], second.as_slice(), - &[Self::SEPARATOR], + &[ENCODE_SEPARATOR], third.as_slice(), - &[Self::SEPARATOR], + &[ENCODE_SEPARATOR], ] .concat() } @@ -253,73 +222,11 @@ impl EncodeSecureKey for Session { store_cipher.hash_key(table_name, self.sender_key().to_base64().as_bytes()); let session_id = store_cipher.hash_key(table_name, self.session_id().as_bytes()); - [sender_key.as_slice(), &[Self::SEPARATOR], session_id.as_slice(), &[Self::SEPARATOR]] + [sender_key.as_slice(), &[ENCODE_SEPARATOR], session_id.as_slice(), &[ENCODE_SEPARATOR]] .concat() } } -impl EncodeKey for RoomId { - fn encode(&self) -> Vec { - self.as_str().encode() - } -} - -impl EncodeKey for String { - fn encode(&self) -> Vec { - self.as_str().encode() - } -} - -impl EncodeKey for str { - fn encode(&self) -> Vec { - [self.as_bytes(), &[Self::SEPARATOR]].concat() - } -} - -impl EncodeKey for ([u8; N], [u8; N]) { - fn encode(&self) -> Vec { - [self.0.as_slice(), &[Self::SEPARATOR], self.1.as_slice(), &[Self::SEPARATOR]].concat() - } -} - -impl EncodeKey for (&str, &str) { - fn encode(&self) -> Vec { - [self.0.as_bytes(), &[Self::SEPARATOR], self.1.as_bytes(), &[Self::SEPARATOR]].concat() - } -} - -impl EncodeKey for (&UserId, &DeviceId) { - fn encode(&self) -> Vec { - (self.0.as_str(), self.1.as_str()).encode() - } -} - -impl EncodeKey for InboundGroupSession { - fn encode(&self) -> Vec { - (self.room_id(), self.sender_key(), self.session_id()).encode() - } -} - -impl EncodeKey for OutboundGroupSession { - fn encode(&self) -> Vec { - self.room_id().encode() - } -} - -impl EncodeKey for (&RoomId, &str, &str) { - fn encode(&self) -> Vec { - [ - self.0.as_bytes(), - &[Self::SEPARATOR], - self.1.as_bytes(), - &[Self::SEPARATOR], - self.2.as_bytes(), - &[Self::SEPARATOR], - ] - .concat() - } -} - trait EncodeSecureKey { fn encode_secure(&self, table_name: &str, store_cipher: &StoreCipher) -> Vec; } diff --git a/crates/matrix-sdk-sled/src/encode_key.rs b/crates/matrix-sdk-sled/src/encode_key.rs new file mode 100644 index 000000000..1f6e1b63e --- /dev/null +++ b/crates/matrix-sdk-sled/src/encode_key.rs @@ -0,0 +1,152 @@ +use matrix_sdk_common::ruma::{ + events::{secret::request::SecretName, GlobalAccountDataEventType, StateEventType}, + DeviceId, EventId, MxcUri, RoomId, TransactionId, UserId, +}; +pub const ENCODE_SEPARATOR: u8 = 0xff; + +pub trait EncodeKey { + fn encode(&self) -> Vec; +} + +impl EncodeKey for &T { + fn encode(&self) -> Vec { + T::encode(self) + } +} + +impl EncodeKey for Box { + fn encode(&self) -> Vec { + T::encode(self) + } +} + +impl EncodeKey for str { + fn encode(&self) -> Vec { + [self.as_bytes(), &[ENCODE_SEPARATOR]].concat() + } +} + +impl EncodeKey for String { + fn encode(&self) -> Vec { + self.as_str().encode() + } +} + +impl EncodeKey for DeviceId { + fn encode(&self) -> Vec { + self.as_str().encode() + } +} + +impl EncodeKey for EventId { + fn encode(&self) -> Vec { + self.as_str().encode() + } +} + +impl EncodeKey for RoomId { + fn encode(&self) -> Vec { + self.as_str().encode() + } +} + +impl EncodeKey for TransactionId { + fn encode(&self) -> Vec { + self.as_str().encode() + } +} + +impl EncodeKey for MxcUri { + fn encode(&self) -> Vec { + let s: &str = self.as_ref(); + s.encode() + } +} + +impl EncodeKey for SecretName { + fn encode(&self) -> Vec { + let s: &str = self.as_ref(); + s.encode() + } +} + +impl EncodeKey for UserId { + fn encode(&self) -> Vec { + self.as_str().encode() + } +} + +impl EncodeKey for (A, B) +where + A: AsRef, + B: AsRef, +{ + fn encode(&self) -> Vec { + [ + self.0.as_ref().as_bytes(), + &[ENCODE_SEPARATOR], + self.1.as_ref().as_bytes(), + &[ENCODE_SEPARATOR], + ] + .concat() + } +} + +impl EncodeKey for (A, B, C) +where + A: AsRef, + B: AsRef, + C: AsRef, +{ + fn encode(&self) -> Vec { + [ + self.0.as_ref().as_bytes(), + &[ENCODE_SEPARATOR], + self.1.as_ref().as_bytes(), + &[ENCODE_SEPARATOR], + self.2.as_ref().as_bytes(), + &[ENCODE_SEPARATOR], + ] + .concat() + } +} + +impl EncodeKey for (A, B, C, D) +where + A: AsRef, + B: AsRef, + C: AsRef, + D: AsRef, +{ + fn encode(&self) -> Vec { + [ + self.0.as_ref().as_bytes(), + &[ENCODE_SEPARATOR], + self.1.as_ref().as_bytes(), + &[ENCODE_SEPARATOR], + self.2.as_ref().as_bytes(), + &[ENCODE_SEPARATOR], + self.3.as_ref().as_bytes(), + &[ENCODE_SEPARATOR], + ] + .concat() + } +} + +impl EncodeKey for StateEventType { + fn encode(&self) -> Vec { + self.to_string().encode() + } +} + +impl EncodeKey for GlobalAccountDataEventType { + fn encode(&self) -> Vec { + self.to_string().encode() + } +} + +pub fn encode_key_with_usize>(s: A, i: usize) -> Vec { + // FIXME: Not portable across architectures + [s.as_ref().as_bytes(), &[ENCODE_SEPARATOR], i.to_be_bytes().as_ref(), &[ENCODE_SEPARATOR]] + .concat() +} diff --git a/crates/matrix-sdk-sled/src/lib.rs b/crates/matrix-sdk-sled/src/lib.rs index f499260c8..5b222cd67 100644 --- a/crates/matrix-sdk-sled/src/lib.rs +++ b/crates/matrix-sdk-sled/src/lib.rs @@ -8,6 +8,7 @@ use thiserror::Error; #[cfg(feature = "encryption")] mod cryptostore; +mod encode_key; mod state_store; #[cfg(feature = "encryption")] diff --git a/crates/matrix-sdk-sled/src/state_store.rs b/crates/matrix-sdk-sled/src/state_store.rs index fb4bc2cb0..acf85f6de 100644 --- a/crates/matrix-sdk-sled/src/state_store.rs +++ b/crates/matrix-sdk-sled/src/state_store.rs @@ -61,6 +61,7 @@ use tracing::{info, warn}; #[cfg(feature = "encryption")] use super::OpenStoreError; +use crate::encode_key::{encode_key_with_usize, EncodeKey, ENCODE_SEPARATOR}; #[cfg(feature = "encryption")] pub use crate::CryptoStore; @@ -114,115 +115,6 @@ impl Into for SledStoreError { type Result = std::result::Result; -const ENCODE_SEPARATOR: u8 = 0xff; - -trait EncodeKey { - fn encode(&self) -> Vec; -} - -impl EncodeKey for &T { - fn encode(&self) -> Vec { - T::encode(self) - } -} - -impl EncodeKey for Box { - fn encode(&self) -> Vec { - T::encode(self) - } -} - -impl EncodeKey for UserId { - fn encode(&self) -> Vec { - self.as_str().encode() - } -} - -impl EncodeKey for RoomId { - fn encode(&self) -> Vec { - self.as_str().encode() - } -} - -impl EncodeKey for String { - fn encode(&self) -> Vec { - self.as_str().encode() - } -} - -impl EncodeKey for str { - fn encode(&self) -> Vec { - [self.as_bytes(), &[ENCODE_SEPARATOR]].concat() - } -} - -impl EncodeKey for (&str, &str) { - fn encode(&self) -> Vec { - [self.0.as_bytes(), &[ENCODE_SEPARATOR], self.1.as_bytes(), &[ENCODE_SEPARATOR]].concat() - } -} - -impl EncodeKey for (&str, &str, &str) { - fn encode(&self) -> Vec { - [ - self.0.as_bytes(), - &[ENCODE_SEPARATOR], - self.1.as_bytes(), - &[ENCODE_SEPARATOR], - self.2.as_bytes(), - &[ENCODE_SEPARATOR], - ] - .concat() - } -} - -impl EncodeKey for (&str, &str, &str, &str) { - fn encode(&self) -> Vec { - [ - self.0.as_bytes(), - &[ENCODE_SEPARATOR], - self.1.as_bytes(), - &[ENCODE_SEPARATOR], - self.2.as_bytes(), - &[ENCODE_SEPARATOR], - self.3.as_bytes(), - &[ENCODE_SEPARATOR], - ] - .concat() - } -} - -impl EncodeKey for StateEventType { - fn encode(&self) -> Vec { - self.to_string().encode() - } -} - -impl EncodeKey for GlobalAccountDataEventType { - fn encode(&self) -> Vec { - self.to_string().encode() - } -} - -/* impl EncodeKey for RoomAccountDataEventType { - fn encode(&self) -> Vec { - self.to_string().encode() - } -} */ - -impl EncodeKey for EventId { - fn encode(&self) -> Vec { - self.as_str().encode() - } -} - -impl EncodeKey for (&RoomId, usize) { - fn encode(&self) -> Vec { - [self.0.as_bytes(), &[ENCODE_SEPARATOR], self.1.to_be_bytes().as_ref(), &[ENCODE_SEPARATOR]] - .concat() - } -} - /// Get the value at `position` in encoded `key`. /// /// The key must have been encoded with the `EncodeKey` trait. `position` @@ -478,7 +370,7 @@ impl SledStore { let profile_changes = changes.profiles.get(room); for event in events.values() { - let key = (room.as_str(), event.state_key.as_str()).encode(); + let key = (room, &event.state_key).encode(); match event.content.membership { MembershipState::Join => { @@ -516,7 +408,7 @@ impl SledStore { for (room_id, ambiguity_maps) in &changes.ambiguity_maps { for (display_name, map) in ambiguity_maps { display_names.insert( - (room_id.as_str(), display_name.as_str()).encode(), + (room_id, display_name).encode(), self.serialize_event(&map) .map_err(ConflictableTransactionError::Abort)?, )?; @@ -534,7 +426,7 @@ impl SledStore { for (room, events) in &changes.room_account_data { for (event_type, event) in events { room_account_data.insert( - (room.as_str(), event_type.to_string().as_str()).encode(), + (room, event_type.to_string()).encode(), self.serialize_event(&event) .map_err(ConflictableTransactionError::Abort)?, )?; @@ -545,12 +437,7 @@ impl SledStore { for (event_type, events) in event_types { for (state_key, event) in events { state.insert( - ( - room.as_str(), - event_type.to_string().as_str(), - state_key.as_str(), - ) - .encode(), + (room, event_type.to_string(), state_key).encode(), self.serialize_event(&event) .map_err(ConflictableTransactionError::Abort)?, )?; @@ -585,7 +472,7 @@ impl SledStore { for (room, events) in &changes.stripped_members { for event in events.values() { stripped_members.insert( - (room.as_str(), event.state_key.as_str()).encode(), + (room, event.state_key.to_string()).encode(), self.serialize_event(&event) .map_err(ConflictableTransactionError::Abort)?, )?; @@ -596,12 +483,7 @@ impl SledStore { for (event_type, events) in event_types { for (state_key, event) in events { stripped_state.insert( - ( - room.as_str(), - event_type.to_string().as_str(), - state_key.as_str(), - ) - .encode(), + (room, event_type.to_string(), state_key).encode(), self.serialize_event(&event) .map_err(ConflictableTransactionError::Abort)?, )?; @@ -624,8 +506,7 @@ impl SledStore { for (user_id, receipt) in receipts { // Add the receipt to the room user receipts if let Some(old) = room_user_receipts.insert( - (room.as_str(), receipt_type.as_ref(), user_id.as_str()) - .encode(), + (room, receipt_type, user_id).encode(), self.serialize_event(&(event_id, receipt)) .map_err(ConflictableTransactionError::Abort)?, )? { @@ -634,25 +515,13 @@ impl SledStore { .deserialize_event(&old) .map_err(ConflictableTransactionError::Abort)?; room_event_receipts.remove( - ( - room.as_str(), - receipt_type.as_ref(), - old_event.as_str(), - user_id.as_str(), - ) - .encode(), + (room, receipt_type, old_event, user_id).encode(), )?; } // Add the receipt to the room event receipts room_event_receipts.insert( - ( - room.as_str(), - receipt_type.as_ref(), - event_id.as_str(), - user_id.as_str(), - ) - .encode(), + (room, receipt_type, event_id, user_id).encode(), self.serialize_event(receipt) .map_err(ConflictableTransactionError::Abort)?, )?; @@ -690,7 +559,7 @@ impl SledStore { state_key: &str, ) -> Result>> { let db = self.clone(); - let key = (room_id.as_str(), event_type.to_string().as_str(), state_key).encode(); + let key = (room_id, event_type.to_string(), state_key).encode(); spawn_blocking(move || { db.room_state.get(key)?.map(|e| db.deserialize_event(&e)).transpose() }) @@ -703,7 +572,7 @@ impl SledStore { event_type: StateEventType, ) -> Result>> { let db = self.clone(); - let key = (room_id.as_str(), event_type.to_string().as_str()).encode(); + let key = (room_id, event_type.to_string()).encode(); spawn_blocking(move || { db.room_state .scan_prefix(key) @@ -719,7 +588,7 @@ impl SledStore { user_id: &UserId, ) -> Result> { let db = self.clone(); - let key = (room_id.as_str(), user_id.as_str()).encode(); + let key = (room_id, user_id).encode(); spawn_blocking(move || db.profiles.get(key)?.map(|p| db.deserialize_event(&p)).transpose()) .await? } @@ -730,7 +599,7 @@ impl SledStore { state_key: &UserId, ) -> Result> { let db = self.clone(); - let key = (room_id.as_str(), state_key.as_str()).encode(); + let key = (room_id, state_key).encode(); spawn_blocking(move || db.members.get(key)?.map(|v| db.deserialize_event(&v)).transpose()) .await? } @@ -832,7 +701,7 @@ impl SledStore { display_name: &str, ) -> Result>> { let db = self.clone(); - let key = (room_id.as_str(), display_name).encode(); + let key = (room_id, display_name).encode(); spawn_blocking(move || { Ok(db .display_names @@ -862,7 +731,7 @@ impl SledStore { event_type: RoomAccountDataEventType, ) -> Result>> { let db = self.clone(); - let key = (room_id.as_str(), event_type.to_string().as_str()).encode(); + let key = (room_id, event_type.to_string()).encode(); spawn_blocking(move || { db.room_account_data.get(key)?.map(|m| db.deserialize_event(&m)).transpose() }) @@ -876,7 +745,7 @@ impl SledStore { user_id: &UserId, ) -> Result, Receipt)>> { let db = self.clone(); - let key = (room_id.as_str(), receipt_type.as_ref(), user_id.as_str()).encode(); + let key = (room_id, receipt_type, user_id).encode(); spawn_blocking(move || { db.room_user_receipts.get(key)?.map(|m| db.deserialize_event(&m)).transpose() }) @@ -890,7 +759,7 @@ impl SledStore { event_id: &EventId, ) -> StoreResult, Receipt)>> { let db = self.clone(); - let key = (room_id.as_str(), receipt_type.as_ref(), event_id.as_str()).encode(); + let key = (room_id, receipt_type, event_id).encode(); spawn_blocking(move || { db.room_event_receipts .scan_prefix(key) @@ -911,10 +780,8 @@ impl SledStore { } async fn add_media_content(&self, request: &MediaRequest, data: Vec) -> Result<()> { - self.media.insert( - (request.source.unique_key().as_str(), request.format.unique_key().as_str()).encode(), - data, - )?; + self.media + .insert((request.source.unique_key(), request.format.unique_key()).encode(), data)?; self.inner.flush_async().await?; @@ -923,8 +790,7 @@ impl SledStore { async fn get_media_content(&self, request: &MediaRequest) -> Result>> { let db = self.clone(); - let key = - (request.source.unique_key().as_str(), request.format.unique_key().as_str()).encode(); + let key = (request.source.unique_key(), request.format.unique_key()).encode(); spawn_blocking(move || Ok(db.media.get(key)?.map(|m| m.to_vec()))).await? } @@ -943,15 +809,13 @@ impl SledStore { } async fn remove_media_content(&self, request: &MediaRequest) -> Result<()> { - self.media.remove( - (request.source.unique_key().as_str(), request.format.unique_key().as_str()).encode(), - )?; + self.media.remove((request.source.unique_key(), request.format.unique_key()).encode())?; Ok(()) } async fn remove_media_content_for_uri(&self, uri: &MxcUri) -> Result<()> { - let keys = self.media.scan_prefix(uri.as_str().encode()).keys(); + let keys = self.media.scan_prefix(uri.encode()).keys(); let mut batch = sled::Batch::default(); for key in keys { @@ -1104,7 +968,7 @@ impl SledStore { info!("Found previously stored timeline for {}, with end token {:?}", r_id, end_token); let stream = stream! { - while let Ok(Some(item)) = db.room_timeline.get(&(r_id.as_ref(), position).encode()) { + while let Ok(Some(item)) = db.room_timeline.get(&encode_key_with_usize(&r_id, position)) { position += 1; yield db.deserialize_event(&item).map_err(SledStoreError::from).map_err(|e| e.into()); } @@ -1184,7 +1048,7 @@ impl SledStore { let mut delete_timeline = false; for event in &timeline.events { if let Some(event_id) = event.event_id() { - let event_key = (room_id.as_ref(), event_id.as_ref()).encode(); + let event_key = (room_id, event_id).encode(); if self.room_event_id_to_position.contains_key(event_key)? { delete_timeline = true; break; @@ -1239,7 +1103,7 @@ impl SledStore { AnySyncMessageLikeEvent::RoomRedaction(redaction), )) = event.event.deserialize() { - let redacts_key = (room_id.as_ref(), redaction.redacts.as_ref()).encode(); + let redacts_key = (room_id, redaction.redacts).encode(); if let Some(position_key) = self.room_event_id_to_position.get(redacts_key)? { @@ -1264,22 +1128,22 @@ impl SledStore { } metadata.start_position -= 1; - let key = (room_id.as_ref(), metadata.start_position).encode(); + let key = encode_key_with_usize(room_id, metadata.start_position); timeline_batch.insert(key.as_slice(), self.serialize_event(&event)?); // Only add event with id to the position map if let Some(event_id) = event.event_id() { - let event_key = (room_id.as_ref(), event_id.as_ref()).encode(); + let event_key = (room_id, event_id).encode(); event_id_to_position_batch.insert(event_key.as_slice(), key.as_slice()); } } } else { for event in &timeline.events { metadata.end_position += 1; - let key = (room_id.as_ref(), metadata.end_position).encode(); + let key = encode_key_with_usize(room_id, metadata.end_position); timeline_batch.insert(key.as_slice(), self.serialize_event(&event)?); // Only add event with id to the position map if let Some(event_id) = event.event_id() { - let event_key = (room_id.as_ref(), event_id.as_ref()).encode(); + let event_key = (room_id, event_id).encode(); event_id_to_position_batch.insert(event_key.as_slice(), key.as_slice()); } }