matrix_sdk_base/store/
traits.rs

1// Copyright 2023 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::{
16    borrow::Borrow,
17    collections::{BTreeMap, BTreeSet, HashMap},
18    fmt,
19    sync::Arc,
20};
21
22use as_variant::as_variant;
23use async_trait::async_trait;
24use growable_bloom_filter::GrowableBloom;
25use matrix_sdk_common::AsyncTraitDeps;
26use ruma::{
27    EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedMxcUri, OwnedRoomId,
28    OwnedTransactionId, OwnedUserId, RoomId, TransactionId, UserId,
29    api::{
30        SupportedVersions,
31        client::discovery::discover_homeserver::{
32            self, HomeserverInfo, IdentityServerInfo, RtcFocusInfo, TileServerInfo,
33        },
34    },
35    events::{
36        AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, EmptyStateKey, GlobalAccountDataEvent,
37        GlobalAccountDataEventContent, GlobalAccountDataEventType, RedactContent,
38        RedactedStateEventContent, RoomAccountDataEvent, RoomAccountDataEventContent,
39        RoomAccountDataEventType, StateEventType, StaticEventContent, StaticStateEventContent,
40        presence::PresenceEvent,
41        receipt::{Receipt, ReceiptThread, ReceiptType},
42    },
43    serde::Raw,
44    time::SystemTime,
45};
46use serde::{Deserialize, Serialize};
47
48use super::{
49    ChildTransactionId, DependentQueuedRequest, DependentQueuedRequestKind, QueueWedgeError,
50    QueuedRequest, QueuedRequestKind, RoomLoadSettings, StateChanges, StoreError,
51    send_queue::SentRequestKey,
52};
53use crate::{
54    MinimalRoomMemberEvent, RoomInfo, RoomMemberships,
55    deserialized_responses::{
56        DisplayName, RawAnySyncOrStrippedState, RawMemberEvent, RawSyncOrStrippedState,
57    },
58    store::ThreadSubscription,
59};
60
61/// An abstract state store trait that can be used to implement different stores
62/// for the SDK.
63#[cfg_attr(target_family = "wasm", async_trait(?Send))]
64#[cfg_attr(not(target_family = "wasm"), async_trait)]
65pub trait StateStore: AsyncTraitDeps {
66    /// The error type used by this state store.
67    type Error: fmt::Debug + Into<StoreError> + From<serde_json::Error>;
68
69    /// Get key-value data from the store.
70    ///
71    /// # Arguments
72    ///
73    /// * `key` - The key to fetch data for.
74    async fn get_kv_data(
75        &self,
76        key: StateStoreDataKey<'_>,
77    ) -> Result<Option<StateStoreDataValue>, Self::Error>;
78
79    /// Put key-value data into the store.
80    ///
81    /// # Arguments
82    ///
83    /// * `key` - The key to identify the data in the store.
84    ///
85    /// * `value` - The data to insert.
86    ///
87    /// Panics if the key and value variants do not match.
88    async fn set_kv_data(
89        &self,
90        key: StateStoreDataKey<'_>,
91        value: StateStoreDataValue,
92    ) -> Result<(), Self::Error>;
93
94    /// Remove key-value data from the store.
95    ///
96    /// # Arguments
97    ///
98    /// * `key` - The key to remove the data for.
99    async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error>;
100
101    /// Save the set of state changes in the store.
102    async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error>;
103
104    /// Get the stored presence event for the given user.
105    ///
106    /// # Arguments
107    ///
108    /// * `user_id` - The id of the user for which we wish to fetch the presence
109    /// event for.
110    async fn get_presence_event(
111        &self,
112        user_id: &UserId,
113    ) -> Result<Option<Raw<PresenceEvent>>, Self::Error>;
114
115    /// Get the stored presence events for the given users.
116    ///
117    /// # Arguments
118    ///
119    /// * `user_ids` - The IDs of the users to fetch the presence events for.
120    async fn get_presence_events(
121        &self,
122        user_ids: &[OwnedUserId],
123    ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error>;
124
125    /// Get a state event out of the state store.
126    ///
127    /// # Arguments
128    ///
129    /// * `room_id` - The id of the room the state event was received for.
130    ///
131    /// * `event_type` - The event type of the state event.
132    async fn get_state_event(
133        &self,
134        room_id: &RoomId,
135        event_type: StateEventType,
136        state_key: &str,
137    ) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error>;
138
139    /// Get a list of state events for a given room and `StateEventType`.
140    ///
141    /// # Arguments
142    ///
143    /// * `room_id` - The id of the room to find events for.
144    ///
145    /// * `event_type` - The event type.
146    async fn get_state_events(
147        &self,
148        room_id: &RoomId,
149        event_type: StateEventType,
150    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error>;
151
152    /// Get a list of state events for a given room, `StateEventType`, and the
153    /// given state keys.
154    ///
155    /// # Arguments
156    ///
157    /// * `room_id` - The id of the room to find events for.
158    ///
159    /// * `event_type` - The event type.
160    ///
161    /// * `state_keys` - The list of state keys to find.
162    async fn get_state_events_for_keys(
163        &self,
164        room_id: &RoomId,
165        event_type: StateEventType,
166        state_keys: &[&str],
167    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error>;
168
169    /// Get the current profile for the given user in the given room.
170    ///
171    /// # Arguments
172    ///
173    /// * `room_id` - The room id the profile is used in.
174    ///
175    /// * `user_id` - The id of the user the profile belongs to.
176    async fn get_profile(
177        &self,
178        room_id: &RoomId,
179        user_id: &UserId,
180    ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error>;
181
182    /// Get the current profiles for the given users in the given room.
183    ///
184    /// # Arguments
185    ///
186    /// * `room_id` - The ID of the room the profiles are used in.
187    ///
188    /// * `user_ids` - The IDs of the users the profiles belong to.
189    async fn get_profiles<'a>(
190        &self,
191        room_id: &RoomId,
192        user_ids: &'a [OwnedUserId],
193    ) -> Result<BTreeMap<&'a UserId, MinimalRoomMemberEvent>, Self::Error>;
194
195    /// Get the user ids of members for a given room with the given memberships,
196    /// for stripped and regular rooms alike.
197    async fn get_user_ids(
198        &self,
199        room_id: &RoomId,
200        memberships: RoomMemberships,
201    ) -> Result<Vec<OwnedUserId>, Self::Error>;
202
203    /// Get a set of pure `RoomInfo`s the store knows about.
204    async fn get_room_infos(
205        &self,
206        room_load_settings: &RoomLoadSettings,
207    ) -> Result<Vec<RoomInfo>, Self::Error>;
208
209    /// Get all the users that use the given display name in the given room.
210    ///
211    /// # Arguments
212    ///
213    /// * `room_id` - The id of the room for which the display name users should
214    /// be fetched for.
215    ///
216    /// * `display_name` - The display name that the users use.
217    async fn get_users_with_display_name(
218        &self,
219        room_id: &RoomId,
220        display_name: &DisplayName,
221    ) -> Result<BTreeSet<OwnedUserId>, Self::Error>;
222
223    /// Get all the users that use the given display names in the given room.
224    ///
225    /// # Arguments
226    ///
227    /// * `room_id` - The ID of the room to fetch the display names for.
228    ///
229    /// * `display_names` - The display names that the users use.
230    async fn get_users_with_display_names<'a>(
231        &self,
232        room_id: &RoomId,
233        display_names: &'a [DisplayName],
234    ) -> Result<HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>, Self::Error>;
235
236    /// Get an event out of the account data store.
237    ///
238    /// # Arguments
239    ///
240    /// * `event_type` - The event type of the account data event.
241    async fn get_account_data_event(
242        &self,
243        event_type: GlobalAccountDataEventType,
244    ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error>;
245
246    /// Get an event out of the room account data store.
247    ///
248    /// # Arguments
249    ///
250    /// * `room_id` - The id of the room for which the room account data event
251    ///   should
252    /// be fetched.
253    ///
254    /// * `event_type` - The event type of the room account data event.
255    async fn get_room_account_data_event(
256        &self,
257        room_id: &RoomId,
258        event_type: RoomAccountDataEventType,
259    ) -> Result<Option<Raw<AnyRoomAccountDataEvent>>, Self::Error>;
260
261    /// Get an event out of the user room receipt store.
262    ///
263    /// # Arguments
264    ///
265    /// * `room_id` - The id of the room for which the receipt should be
266    ///   fetched.
267    ///
268    /// * `receipt_type` - The type of the receipt.
269    ///
270    /// * `thread` - The thread containing this receipt.
271    ///
272    /// * `user_id` - The id of the user for who the receipt should be fetched.
273    async fn get_user_room_receipt_event(
274        &self,
275        room_id: &RoomId,
276        receipt_type: ReceiptType,
277        thread: ReceiptThread,
278        user_id: &UserId,
279    ) -> Result<Option<(OwnedEventId, Receipt)>, Self::Error>;
280
281    /// Get events out of the event room receipt store.
282    ///
283    /// # Arguments
284    ///
285    /// * `room_id` - The id of the room for which the receipts should be
286    ///   fetched.
287    ///
288    /// * `receipt_type` - The type of the receipts.
289    ///
290    /// * `thread` - The thread containing this receipt.
291    ///
292    /// * `event_id` - The id of the event for which the receipts should be
293    ///   fetched.
294    async fn get_event_room_receipt_events(
295        &self,
296        room_id: &RoomId,
297        receipt_type: ReceiptType,
298        thread: ReceiptThread,
299        event_id: &EventId,
300    ) -> Result<Vec<(OwnedUserId, Receipt)>, Self::Error>;
301
302    /// Get arbitrary data from the custom store
303    ///
304    /// # Arguments
305    ///
306    /// * `key` - The key to fetch data for
307    async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error>;
308
309    /// Put arbitrary data into the custom store, return the data previously
310    /// stored
311    ///
312    /// # Arguments
313    ///
314    /// * `key` - The key to insert data into
315    ///
316    /// * `value` - The value to insert
317    async fn set_custom_value(
318        &self,
319        key: &[u8],
320        value: Vec<u8>,
321    ) -> Result<Option<Vec<u8>>, Self::Error>;
322
323    /// Put arbitrary data into the custom store, do not attempt to read any
324    /// previous data
325    ///
326    /// Optimization option for set_custom_values for stores that would perform
327    /// better withouts the extra read and the caller not needing that data
328    /// returned. Otherwise this just wraps around `set_custom_data` and
329    /// discards the result.
330    ///
331    /// # Arguments
332    ///
333    /// * `key` - The key to insert data into
334    ///
335    /// * `value` - The value to insert
336    async fn set_custom_value_no_read(
337        &self,
338        key: &[u8],
339        value: Vec<u8>,
340    ) -> Result<(), Self::Error> {
341        self.set_custom_value(key, value).await.map(|_| ())
342    }
343
344    /// Remove arbitrary data from the custom store and return it if existed
345    ///
346    /// # Arguments
347    ///
348    /// * `key` - The key to remove data from
349    async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error>;
350
351    /// Remove a room and all elements associated from the state store.
352    ///
353    /// # Arguments
354    ///
355    /// * `room_id` - The `RoomId` of the room to delete.
356    async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error>;
357
358    /// Save a request to be sent by a send queue later (e.g. sending an event).
359    ///
360    /// # Arguments
361    ///
362    /// * `room_id` - The `RoomId` of the send queue's room.
363    /// * `transaction_id` - The unique key identifying the event to be sent
364    ///   (and its transaction). Note: this is expected to be randomly generated
365    ///   and thus unique.
366    /// * `content` - Serializable event content to be sent.
367    async fn save_send_queue_request(
368        &self,
369        room_id: &RoomId,
370        transaction_id: OwnedTransactionId,
371        created_at: MilliSecondsSinceUnixEpoch,
372        request: QueuedRequestKind,
373        priority: usize,
374    ) -> Result<(), Self::Error>;
375
376    /// Updates a send queue request with the given content, and resets its
377    /// error status.
378    ///
379    /// # Arguments
380    ///
381    /// * `room_id` - The `RoomId` of the send queue's room.
382    /// * `transaction_id` - The unique key identifying the request to be sent
383    ///   (and its transaction).
384    /// * `content` - Serializable event content to replace the original one.
385    ///
386    /// Returns true if a request has been updated, or false otherwise.
387    async fn update_send_queue_request(
388        &self,
389        room_id: &RoomId,
390        transaction_id: &TransactionId,
391        content: QueuedRequestKind,
392    ) -> Result<bool, Self::Error>;
393
394    /// Remove a request previously inserted with
395    /// [`Self::save_send_queue_request`] from the database, based on its
396    /// transaction id.
397    ///
398    /// Returns true if something has been removed, or false otherwise.
399    async fn remove_send_queue_request(
400        &self,
401        room_id: &RoomId,
402        transaction_id: &TransactionId,
403    ) -> Result<bool, Self::Error>;
404
405    /// Loads all the send queue requests for the given room.
406    ///
407    /// The resulting vector of queued requests should be ordered from higher
408    /// priority to lower priority, and respect the insertion order when
409    /// priorities are equal.
410    async fn load_send_queue_requests(
411        &self,
412        room_id: &RoomId,
413    ) -> Result<Vec<QueuedRequest>, Self::Error>;
414
415    /// Updates the send queue error status (wedge) for a given send queue
416    /// request.
417    async fn update_send_queue_request_status(
418        &self,
419        room_id: &RoomId,
420        transaction_id: &TransactionId,
421        error: Option<QueueWedgeError>,
422    ) -> Result<(), Self::Error>;
423
424    /// Loads all the rooms which have any pending requests in their send queue.
425    async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error>;
426
427    /// Add a new entry to the list of dependent send queue requests for a
428    /// parent request.
429    async fn save_dependent_queued_request(
430        &self,
431        room_id: &RoomId,
432        parent_txn_id: &TransactionId,
433        own_txn_id: ChildTransactionId,
434        created_at: MilliSecondsSinceUnixEpoch,
435        content: DependentQueuedRequestKind,
436    ) -> Result<(), Self::Error>;
437
438    /// Mark a set of dependent send queue requests as ready, using a key
439    /// identifying the homeserver's response.
440    ///
441    /// ⚠ Beware! There's no verification applied that the parent key type is
442    /// compatible with the dependent event type. The invalid state may be
443    /// lazily filtered out in `load_dependent_queued_requests`.
444    ///
445    /// Returns the number of updated requests.
446    async fn mark_dependent_queued_requests_as_ready(
447        &self,
448        room_id: &RoomId,
449        parent_txn_id: &TransactionId,
450        sent_parent_key: SentRequestKey,
451    ) -> Result<usize, Self::Error>;
452
453    /// Update a dependent send queue request with the new content.
454    ///
455    /// Returns true if the request was found and could be updated.
456    async fn update_dependent_queued_request(
457        &self,
458        room_id: &RoomId,
459        own_transaction_id: &ChildTransactionId,
460        new_content: DependentQueuedRequestKind,
461    ) -> Result<bool, Self::Error>;
462
463    /// Remove a specific dependent send queue request by id.
464    ///
465    /// Returns true if the dependent send queue request has been indeed
466    /// removed.
467    async fn remove_dependent_queued_request(
468        &self,
469        room: &RoomId,
470        own_txn_id: &ChildTransactionId,
471    ) -> Result<bool, Self::Error>;
472
473    /// List all the dependent send queue requests.
474    ///
475    /// This returns absolutely all the dependent send queue requests, whether
476    /// they have a parent event id or not. As a contract for implementors, they
477    /// must be returned in insertion order.
478    async fn load_dependent_queued_requests(
479        &self,
480        room: &RoomId,
481    ) -> Result<Vec<DependentQueuedRequest>, Self::Error>;
482
483    /// Insert or update a thread subscription for a given room and thread.
484    async fn upsert_thread_subscription(
485        &self,
486        room: &RoomId,
487        thread_id: &EventId,
488        subscription: ThreadSubscription,
489    ) -> Result<(), Self::Error>;
490
491    /// Remove a previous thread subscription for a given room and thread.
492    ///
493    /// Note: removing an unknown thread subscription is a no-op.
494    async fn remove_thread_subscription(
495        &self,
496        room: &RoomId,
497        thread_id: &EventId,
498    ) -> Result<(), Self::Error>;
499
500    /// Loads the current thread subscription for a given room and thread.
501    ///
502    /// Returns `None` if there was no entry for the given room/thread pair.
503    async fn load_thread_subscription(
504        &self,
505        room: &RoomId,
506        thread_id: &EventId,
507    ) -> Result<Option<ThreadSubscription>, Self::Error>;
508}
509
510#[repr(transparent)]
511struct EraseStateStoreError<T>(T);
512
513#[cfg(not(tarpaulin_include))]
514impl<T: fmt::Debug> fmt::Debug for EraseStateStoreError<T> {
515    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
516        self.0.fmt(f)
517    }
518}
519
520#[cfg_attr(target_family = "wasm", async_trait(?Send))]
521#[cfg_attr(not(target_family = "wasm"), async_trait)]
522impl<T: StateStore> StateStore for EraseStateStoreError<T> {
523    type Error = StoreError;
524
525    async fn get_kv_data(
526        &self,
527        key: StateStoreDataKey<'_>,
528    ) -> Result<Option<StateStoreDataValue>, Self::Error> {
529        self.0.get_kv_data(key).await.map_err(Into::into)
530    }
531
532    async fn set_kv_data(
533        &self,
534        key: StateStoreDataKey<'_>,
535        value: StateStoreDataValue,
536    ) -> Result<(), Self::Error> {
537        self.0.set_kv_data(key, value).await.map_err(Into::into)
538    }
539
540    async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error> {
541        self.0.remove_kv_data(key).await.map_err(Into::into)
542    }
543
544    async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error> {
545        self.0.save_changes(changes).await.map_err(Into::into)
546    }
547
548    async fn get_presence_event(
549        &self,
550        user_id: &UserId,
551    ) -> Result<Option<Raw<PresenceEvent>>, Self::Error> {
552        self.0.get_presence_event(user_id).await.map_err(Into::into)
553    }
554
555    async fn get_presence_events(
556        &self,
557        user_ids: &[OwnedUserId],
558    ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error> {
559        self.0.get_presence_events(user_ids).await.map_err(Into::into)
560    }
561
562    async fn get_state_event(
563        &self,
564        room_id: &RoomId,
565        event_type: StateEventType,
566        state_key: &str,
567    ) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error> {
568        self.0.get_state_event(room_id, event_type, state_key).await.map_err(Into::into)
569    }
570
571    async fn get_state_events(
572        &self,
573        room_id: &RoomId,
574        event_type: StateEventType,
575    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
576        self.0.get_state_events(room_id, event_type).await.map_err(Into::into)
577    }
578
579    async fn get_state_events_for_keys(
580        &self,
581        room_id: &RoomId,
582        event_type: StateEventType,
583        state_keys: &[&str],
584    ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
585        self.0.get_state_events_for_keys(room_id, event_type, state_keys).await.map_err(Into::into)
586    }
587
588    async fn get_profile(
589        &self,
590        room_id: &RoomId,
591        user_id: &UserId,
592    ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error> {
593        self.0.get_profile(room_id, user_id).await.map_err(Into::into)
594    }
595
596    async fn get_profiles<'a>(
597        &self,
598        room_id: &RoomId,
599        user_ids: &'a [OwnedUserId],
600    ) -> Result<BTreeMap<&'a UserId, MinimalRoomMemberEvent>, Self::Error> {
601        self.0.get_profiles(room_id, user_ids).await.map_err(Into::into)
602    }
603
604    async fn get_user_ids(
605        &self,
606        room_id: &RoomId,
607        memberships: RoomMemberships,
608    ) -> Result<Vec<OwnedUserId>, Self::Error> {
609        self.0.get_user_ids(room_id, memberships).await.map_err(Into::into)
610    }
611
612    async fn get_room_infos(
613        &self,
614        room_load_settings: &RoomLoadSettings,
615    ) -> Result<Vec<RoomInfo>, Self::Error> {
616        self.0.get_room_infos(room_load_settings).await.map_err(Into::into)
617    }
618
619    async fn get_users_with_display_name(
620        &self,
621        room_id: &RoomId,
622        display_name: &DisplayName,
623    ) -> Result<BTreeSet<OwnedUserId>, Self::Error> {
624        self.0.get_users_with_display_name(room_id, display_name).await.map_err(Into::into)
625    }
626
627    async fn get_users_with_display_names<'a>(
628        &self,
629        room_id: &RoomId,
630        display_names: &'a [DisplayName],
631    ) -> Result<HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>, Self::Error> {
632        self.0.get_users_with_display_names(room_id, display_names).await.map_err(Into::into)
633    }
634
635    async fn get_account_data_event(
636        &self,
637        event_type: GlobalAccountDataEventType,
638    ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error> {
639        self.0.get_account_data_event(event_type).await.map_err(Into::into)
640    }
641
642    async fn get_room_account_data_event(
643        &self,
644        room_id: &RoomId,
645        event_type: RoomAccountDataEventType,
646    ) -> Result<Option<Raw<AnyRoomAccountDataEvent>>, Self::Error> {
647        self.0.get_room_account_data_event(room_id, event_type).await.map_err(Into::into)
648    }
649
650    async fn get_user_room_receipt_event(
651        &self,
652        room_id: &RoomId,
653        receipt_type: ReceiptType,
654        thread: ReceiptThread,
655        user_id: &UserId,
656    ) -> Result<Option<(OwnedEventId, Receipt)>, Self::Error> {
657        self.0
658            .get_user_room_receipt_event(room_id, receipt_type, thread, user_id)
659            .await
660            .map_err(Into::into)
661    }
662
663    async fn get_event_room_receipt_events(
664        &self,
665        room_id: &RoomId,
666        receipt_type: ReceiptType,
667        thread: ReceiptThread,
668        event_id: &EventId,
669    ) -> Result<Vec<(OwnedUserId, Receipt)>, Self::Error> {
670        self.0
671            .get_event_room_receipt_events(room_id, receipt_type, thread, event_id)
672            .await
673            .map_err(Into::into)
674    }
675
676    async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
677        self.0.get_custom_value(key).await.map_err(Into::into)
678    }
679
680    async fn set_custom_value(
681        &self,
682        key: &[u8],
683        value: Vec<u8>,
684    ) -> Result<Option<Vec<u8>>, Self::Error> {
685        self.0.set_custom_value(key, value).await.map_err(Into::into)
686    }
687
688    async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
689        self.0.remove_custom_value(key).await.map_err(Into::into)
690    }
691
692    async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error> {
693        self.0.remove_room(room_id).await.map_err(Into::into)
694    }
695
696    async fn save_send_queue_request(
697        &self,
698        room_id: &RoomId,
699        transaction_id: OwnedTransactionId,
700        created_at: MilliSecondsSinceUnixEpoch,
701        content: QueuedRequestKind,
702        priority: usize,
703    ) -> Result<(), Self::Error> {
704        self.0
705            .save_send_queue_request(room_id, transaction_id, created_at, content, priority)
706            .await
707            .map_err(Into::into)
708    }
709
710    async fn update_send_queue_request(
711        &self,
712        room_id: &RoomId,
713        transaction_id: &TransactionId,
714        content: QueuedRequestKind,
715    ) -> Result<bool, Self::Error> {
716        self.0.update_send_queue_request(room_id, transaction_id, content).await.map_err(Into::into)
717    }
718
719    async fn remove_send_queue_request(
720        &self,
721        room_id: &RoomId,
722        transaction_id: &TransactionId,
723    ) -> Result<bool, Self::Error> {
724        self.0.remove_send_queue_request(room_id, transaction_id).await.map_err(Into::into)
725    }
726
727    async fn load_send_queue_requests(
728        &self,
729        room_id: &RoomId,
730    ) -> Result<Vec<QueuedRequest>, Self::Error> {
731        self.0.load_send_queue_requests(room_id).await.map_err(Into::into)
732    }
733
734    async fn update_send_queue_request_status(
735        &self,
736        room_id: &RoomId,
737        transaction_id: &TransactionId,
738        error: Option<QueueWedgeError>,
739    ) -> Result<(), Self::Error> {
740        self.0
741            .update_send_queue_request_status(room_id, transaction_id, error)
742            .await
743            .map_err(Into::into)
744    }
745
746    async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error> {
747        self.0.load_rooms_with_unsent_requests().await.map_err(Into::into)
748    }
749
750    async fn save_dependent_queued_request(
751        &self,
752        room_id: &RoomId,
753        parent_txn_id: &TransactionId,
754        own_txn_id: ChildTransactionId,
755        created_at: MilliSecondsSinceUnixEpoch,
756        content: DependentQueuedRequestKind,
757    ) -> Result<(), Self::Error> {
758        self.0
759            .save_dependent_queued_request(room_id, parent_txn_id, own_txn_id, created_at, content)
760            .await
761            .map_err(Into::into)
762    }
763
764    async fn mark_dependent_queued_requests_as_ready(
765        &self,
766        room_id: &RoomId,
767        parent_txn_id: &TransactionId,
768        sent_parent_key: SentRequestKey,
769    ) -> Result<usize, Self::Error> {
770        self.0
771            .mark_dependent_queued_requests_as_ready(room_id, parent_txn_id, sent_parent_key)
772            .await
773            .map_err(Into::into)
774    }
775
776    async fn remove_dependent_queued_request(
777        &self,
778        room_id: &RoomId,
779        own_txn_id: &ChildTransactionId,
780    ) -> Result<bool, Self::Error> {
781        self.0.remove_dependent_queued_request(room_id, own_txn_id).await.map_err(Into::into)
782    }
783
784    async fn load_dependent_queued_requests(
785        &self,
786        room_id: &RoomId,
787    ) -> Result<Vec<DependentQueuedRequest>, Self::Error> {
788        self.0.load_dependent_queued_requests(room_id).await.map_err(Into::into)
789    }
790
791    async fn update_dependent_queued_request(
792        &self,
793        room_id: &RoomId,
794        own_transaction_id: &ChildTransactionId,
795        new_content: DependentQueuedRequestKind,
796    ) -> Result<bool, Self::Error> {
797        self.0
798            .update_dependent_queued_request(room_id, own_transaction_id, new_content)
799            .await
800            .map_err(Into::into)
801    }
802
803    async fn upsert_thread_subscription(
804        &self,
805        room: &RoomId,
806        thread_id: &EventId,
807        subscription: ThreadSubscription,
808    ) -> Result<(), Self::Error> {
809        self.0.upsert_thread_subscription(room, thread_id, subscription).await.map_err(Into::into)
810    }
811
812    async fn load_thread_subscription(
813        &self,
814        room: &RoomId,
815        thread_id: &EventId,
816    ) -> Result<Option<ThreadSubscription>, Self::Error> {
817        self.0.load_thread_subscription(room, thread_id).await.map_err(Into::into)
818    }
819
820    async fn remove_thread_subscription(
821        &self,
822        room: &RoomId,
823        thread_id: &EventId,
824    ) -> Result<(), Self::Error> {
825        self.0.remove_thread_subscription(room, thread_id).await.map_err(Into::into)
826    }
827}
828
829/// Convenience functionality for state stores.
830#[cfg_attr(target_family = "wasm", async_trait(?Send))]
831#[cfg_attr(not(target_family = "wasm"), async_trait)]
832pub trait StateStoreExt: StateStore {
833    /// Get a specific state event of statically-known type.
834    ///
835    /// # Arguments
836    ///
837    /// * `room_id` - The id of the room the state event was received for.
838    async fn get_state_event_static<C>(
839        &self,
840        room_id: &RoomId,
841    ) -> Result<Option<RawSyncOrStrippedState<C>>, Self::Error>
842    where
843        C: StaticEventContent<IsPrefix = ruma::events::False>
844            + StaticStateEventContent<StateKey = EmptyStateKey>
845            + RedactContent,
846        C::Redacted: RedactedStateEventContent,
847    {
848        Ok(self.get_state_event(room_id, C::TYPE.into(), "").await?.map(|raw| raw.cast()))
849    }
850
851    /// Get a specific state event of statically-known type.
852    ///
853    /// # Arguments
854    ///
855    /// * `room_id` - The id of the room the state event was received for.
856    async fn get_state_event_static_for_key<C, K>(
857        &self,
858        room_id: &RoomId,
859        state_key: &K,
860    ) -> Result<Option<RawSyncOrStrippedState<C>>, Self::Error>
861    where
862        C: StaticEventContent<IsPrefix = ruma::events::False>
863            + StaticStateEventContent
864            + RedactContent,
865        C::StateKey: Borrow<K>,
866        C::Redacted: RedactedStateEventContent,
867        K: AsRef<str> + ?Sized + Sync,
868    {
869        Ok(self
870            .get_state_event(room_id, C::TYPE.into(), state_key.as_ref())
871            .await?
872            .map(|raw| raw.cast()))
873    }
874
875    /// Get a list of state events of a statically-known type for a given room.
876    ///
877    /// # Arguments
878    ///
879    /// * `room_id` - The id of the room to find events for.
880    async fn get_state_events_static<C>(
881        &self,
882        room_id: &RoomId,
883    ) -> Result<Vec<RawSyncOrStrippedState<C>>, Self::Error>
884    where
885        C: StaticEventContent<IsPrefix = ruma::events::False>
886            + StaticStateEventContent
887            + RedactContent,
888        C::Redacted: RedactedStateEventContent,
889    {
890        // FIXME: Could be more efficient, if we had streaming store accessor functions
891        Ok(self
892            .get_state_events(room_id, C::TYPE.into())
893            .await?
894            .into_iter()
895            .map(|raw| raw.cast())
896            .collect())
897    }
898
899    /// Get a list of state events of a statically-known type for a given room
900    /// and given state keys.
901    ///
902    /// # Arguments
903    ///
904    /// * `room_id` - The id of the room to find events for.
905    ///
906    /// * `state_keys` - The list of state keys to find.
907    async fn get_state_events_for_keys_static<'a, C, K, I>(
908        &self,
909        room_id: &RoomId,
910        state_keys: I,
911    ) -> Result<Vec<RawSyncOrStrippedState<C>>, Self::Error>
912    where
913        C: StaticEventContent<IsPrefix = ruma::events::False>
914            + StaticStateEventContent
915            + RedactContent,
916        C::StateKey: Borrow<K>,
917        C::Redacted: RedactedStateEventContent,
918        K: AsRef<str> + Sized + Sync + 'a,
919        I: IntoIterator<Item = &'a K> + Send,
920        I::IntoIter: Send,
921    {
922        Ok(self
923            .get_state_events_for_keys(
924                room_id,
925                C::TYPE.into(),
926                &state_keys.into_iter().map(|k| k.as_ref()).collect::<Vec<_>>(),
927            )
928            .await?
929            .into_iter()
930            .map(|raw| raw.cast())
931            .collect())
932    }
933
934    /// Get an event of a statically-known type from the account data store.
935    async fn get_account_data_event_static<C>(
936        &self,
937    ) -> Result<Option<Raw<GlobalAccountDataEvent<C>>>, Self::Error>
938    where
939        C: StaticEventContent<IsPrefix = ruma::events::False> + GlobalAccountDataEventContent,
940    {
941        Ok(self.get_account_data_event(C::TYPE.into()).await?.map(Raw::cast_unchecked))
942    }
943
944    /// Get an event of a statically-known type from the room account data
945    /// store.
946    ///
947    /// # Arguments
948    ///
949    /// * `room_id` - The id of the room for which the room account data event
950    ///   should be fetched.
951    async fn get_room_account_data_event_static<C>(
952        &self,
953        room_id: &RoomId,
954    ) -> Result<Option<Raw<RoomAccountDataEvent<C>>>, Self::Error>
955    where
956        C: StaticEventContent<IsPrefix = ruma::events::False> + RoomAccountDataEventContent,
957    {
958        Ok(self
959            .get_room_account_data_event(room_id, C::TYPE.into())
960            .await?
961            .map(Raw::cast_unchecked))
962    }
963
964    /// Get the `MemberEvent` for the given state key in the given room id.
965    ///
966    /// # Arguments
967    ///
968    /// * `room_id` - The room id the member event belongs to.
969    ///
970    /// * `state_key` - The user id that the member event defines the state for.
971    async fn get_member_event(
972        &self,
973        room_id: &RoomId,
974        state_key: &UserId,
975    ) -> Result<Option<RawMemberEvent>, Self::Error> {
976        self.get_state_event_static_for_key(room_id, state_key).await
977    }
978}
979
980#[cfg_attr(target_family = "wasm", async_trait(?Send))]
981#[cfg_attr(not(target_family = "wasm"), async_trait)]
982impl<T: StateStore + ?Sized> StateStoreExt for T {}
983
984/// A type-erased [`StateStore`].
985pub type DynStateStore = dyn StateStore<Error = StoreError>;
986
987/// A type that can be type-erased into `Arc<dyn StateStore>`.
988///
989/// This trait is not meant to be implemented directly outside
990/// `matrix-sdk-crypto`, but it is automatically implemented for everything that
991/// implements `StateStore`.
992pub trait IntoStateStore {
993    #[doc(hidden)]
994    fn into_state_store(self) -> Arc<DynStateStore>;
995}
996
997impl<T> IntoStateStore for T
998where
999    T: StateStore + Sized + 'static,
1000{
1001    fn into_state_store(self) -> Arc<DynStateStore> {
1002        Arc::new(EraseStateStoreError(self))
1003    }
1004}
1005
1006// Turns a given `Arc<T>` into `Arc<DynStateStore>` by attaching the
1007// StateStore impl vtable of `EraseStateStoreError<T>`.
1008impl<T> IntoStateStore for Arc<T>
1009where
1010    T: StateStore + 'static,
1011{
1012    fn into_state_store(self) -> Arc<DynStateStore> {
1013        let ptr: *const T = Arc::into_raw(self);
1014        let ptr_erased = ptr as *const EraseStateStoreError<T>;
1015        // SAFETY: EraseStateStoreError is repr(transparent) so T and
1016        //         EraseStateStoreError<T> have the same layout and ABI
1017        unsafe { Arc::from_raw(ptr_erased) }
1018    }
1019}
1020
1021/// Useful server info such as data returned by the /client/versions and
1022/// .well-known/client/matrix endpoints.
1023#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1024pub struct ServerInfo {
1025    /// Versions supported by the remote server.
1026    pub versions: Vec<String>,
1027
1028    /// List of unstable features and their enablement status.
1029    pub unstable_features: BTreeMap<String, bool>,
1030
1031    /// Information about the server found in the client well-known file.
1032    #[serde(skip_serializing_if = "Option::is_none")]
1033    pub well_known: Option<WellKnownResponse>,
1034
1035    /// Last time we fetched this data from the server, in milliseconds since
1036    /// epoch.
1037    last_fetch_ts: f64,
1038}
1039
1040impl ServerInfo {
1041    /// The number of milliseconds after which the data is considered stale.
1042    pub const STALE_THRESHOLD: f64 = (1000 * 60 * 60 * 24 * 7) as _; // seven days
1043
1044    /// Encode server info into this serializable struct.
1045    pub fn new(
1046        versions: Vec<String>,
1047        unstable_features: BTreeMap<String, bool>,
1048        well_known: Option<WellKnownResponse>,
1049    ) -> Self {
1050        Self { versions, unstable_features, well_known, last_fetch_ts: now_timestamp_ms() }
1051    }
1052
1053    /// Decode server info from this serializable struct.
1054    ///
1055    /// May return `None` if the data is considered stale, after
1056    /// [`Self::STALE_THRESHOLD`] milliseconds since the last time we stored
1057    /// it.
1058    pub fn maybe_decode(&self) -> Option<Self> {
1059        if now_timestamp_ms() - self.last_fetch_ts >= Self::STALE_THRESHOLD {
1060            None
1061        } else {
1062            Some(self.clone())
1063        }
1064    }
1065
1066    /// Extracts known Matrix versions and features from the un-typed lists of
1067    /// strings.
1068    ///
1069    /// Note: Matrix versions that Ruma cannot parse, or does not know about,
1070    /// are discarded.
1071    pub fn supported_versions(&self) -> SupportedVersions {
1072        SupportedVersions::from_parts(&self.versions, &self.unstable_features)
1073    }
1074}
1075
1076#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1077/// A serialisable representation of discover_homeserver::Response.
1078pub struct WellKnownResponse {
1079    /// Information about the homeserver to connect to.
1080    pub homeserver: HomeserverInfo,
1081
1082    /// Information about the identity server to connect to.
1083    pub identity_server: Option<IdentityServerInfo>,
1084
1085    /// Information about the tile server to use to display location data.
1086    pub tile_server: Option<TileServerInfo>,
1087
1088    /// A list of the available MatrixRTC foci, ordered by priority.
1089    pub rtc_foci: Vec<RtcFocusInfo>,
1090}
1091
1092impl From<discover_homeserver::Response> for WellKnownResponse {
1093    fn from(response: discover_homeserver::Response) -> Self {
1094        Self {
1095            homeserver: response.homeserver,
1096            identity_server: response.identity_server,
1097            tile_server: response.tile_server,
1098            rtc_foci: response.rtc_foci,
1099        }
1100    }
1101}
1102
1103/// Get the current timestamp as the number of milliseconds since Unix Epoch.
1104fn now_timestamp_ms() -> f64 {
1105    SystemTime::now()
1106        .duration_since(SystemTime::UNIX_EPOCH)
1107        .expect("System clock was before 1970.")
1108        .as_secs_f64()
1109        * 1000.0
1110}
1111
1112/// A value for key-value data that should be persisted into the store.
1113#[derive(Debug, Clone)]
1114pub enum StateStoreDataValue {
1115    /// The sync token.
1116    SyncToken(String),
1117
1118    /// The server info (versions, well-known etc).
1119    ServerInfo(ServerInfo),
1120
1121    /// A filter with the given ID.
1122    Filter(String),
1123
1124    /// The user avatar url
1125    UserAvatarUrl(OwnedMxcUri),
1126
1127    /// A list of recently visited room identifiers for the current user
1128    RecentlyVisitedRooms(Vec<OwnedRoomId>),
1129
1130    /// Persistent data for
1131    /// `matrix_sdk_ui::unable_to_decrypt_hook::UtdHookManager`.
1132    UtdHookManagerData(GrowableBloom),
1133
1134    /// A unit value telling us that the client uploaded duplicate one-time
1135    /// keys.
1136    OneTimeKeyAlreadyUploaded,
1137
1138    /// A composer draft for the room.
1139    /// To learn more, see [`ComposerDraft`].
1140    ///
1141    /// [`ComposerDraft`]: Self::ComposerDraft
1142    ComposerDraft(ComposerDraft),
1143
1144    /// A list of knock request ids marked as seen in a room.
1145    SeenKnockRequests(BTreeMap<OwnedEventId, OwnedUserId>),
1146}
1147
1148/// Current draft of the composer for the room.
1149#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1150pub struct ComposerDraft {
1151    /// The draft content in plain text.
1152    pub plain_text: String,
1153    /// If the message is formatted in HTML, the HTML representation of the
1154    /// message.
1155    pub html_text: Option<String>,
1156    /// The type of draft.
1157    pub draft_type: ComposerDraftType,
1158}
1159
1160/// The type of draft of the composer.
1161#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1162pub enum ComposerDraftType {
1163    /// The draft is a new message.
1164    NewMessage,
1165    /// The draft is a reply to an event.
1166    Reply {
1167        /// The ID of the event being replied to.
1168        event_id: OwnedEventId,
1169    },
1170    /// The draft is an edit of an event.
1171    Edit {
1172        /// The ID of the event being edited.
1173        event_id: OwnedEventId,
1174    },
1175}
1176
1177impl StateStoreDataValue {
1178    /// Get this value if it is a sync token.
1179    pub fn into_sync_token(self) -> Option<String> {
1180        as_variant!(self, Self::SyncToken)
1181    }
1182
1183    /// Get this value if it is a filter.
1184    pub fn into_filter(self) -> Option<String> {
1185        as_variant!(self, Self::Filter)
1186    }
1187
1188    /// Get this value if it is a user avatar url.
1189    pub fn into_user_avatar_url(self) -> Option<OwnedMxcUri> {
1190        as_variant!(self, Self::UserAvatarUrl)
1191    }
1192
1193    /// Get this value if it is a list of recently visited rooms.
1194    pub fn into_recently_visited_rooms(self) -> Option<Vec<OwnedRoomId>> {
1195        as_variant!(self, Self::RecentlyVisitedRooms)
1196    }
1197
1198    /// Get this value if it is the data for the `UtdHookManager`.
1199    pub fn into_utd_hook_manager_data(self) -> Option<GrowableBloom> {
1200        as_variant!(self, Self::UtdHookManagerData)
1201    }
1202
1203    /// Get this value if it is a composer draft.
1204    pub fn into_composer_draft(self) -> Option<ComposerDraft> {
1205        as_variant!(self, Self::ComposerDraft)
1206    }
1207
1208    /// Get this value if it is the server info metadata.
1209    pub fn into_server_info(self) -> Option<ServerInfo> {
1210        as_variant!(self, Self::ServerInfo)
1211    }
1212
1213    /// Get this value if it is the data for the ignored join requests.
1214    pub fn into_seen_knock_requests(self) -> Option<BTreeMap<OwnedEventId, OwnedUserId>> {
1215        as_variant!(self, Self::SeenKnockRequests)
1216    }
1217}
1218
1219/// A key for key-value data.
1220#[derive(Debug, Clone, Copy)]
1221pub enum StateStoreDataKey<'a> {
1222    /// The sync token.
1223    SyncToken,
1224
1225    /// The server info,
1226    ServerInfo,
1227
1228    /// A filter with the given name.
1229    Filter(&'a str),
1230
1231    /// Avatar URL
1232    UserAvatarUrl(&'a UserId),
1233
1234    /// Recently visited room identifiers
1235    RecentlyVisitedRooms(&'a UserId),
1236
1237    /// Persistent data for
1238    /// `matrix_sdk_ui::unable_to_decrypt_hook::UtdHookManager`.
1239    UtdHookManagerData,
1240
1241    /// Data remembering if the client already reported that it has uploaded
1242    /// duplicate one-time keys.
1243    OneTimeKeyAlreadyUploaded,
1244
1245    /// A composer draft for the room.
1246    /// To learn more, see [`ComposerDraft`].
1247    ///
1248    /// [`ComposerDraft`]: Self::ComposerDraft
1249    ComposerDraft(&'a RoomId, Option<&'a EventId>),
1250
1251    /// A list of knock request ids marked as seen in a room.
1252    SeenKnockRequests(&'a RoomId),
1253}
1254
1255impl StateStoreDataKey<'_> {
1256    /// Key to use for the [`SyncToken`][Self::SyncToken] variant.
1257    pub const SYNC_TOKEN: &'static str = "sync_token";
1258
1259    /// Key to use for the [`ServerInfo`][Self::ServerInfo]
1260    /// variant.
1261    pub const SERVER_INFO: &'static str = "server_capabilities"; // Note: this is the old name, kept for backwards compatibility.
1262    //
1263    /// Key prefix to use for the [`Filter`][Self::Filter] variant.
1264    pub const FILTER: &'static str = "filter";
1265
1266    /// Key prefix to use for the [`UserAvatarUrl`][Self::UserAvatarUrl]
1267    /// variant.
1268    pub const USER_AVATAR_URL: &'static str = "user_avatar_url";
1269
1270    /// Key prefix to use for the
1271    /// [`RecentlyVisitedRooms`][Self::RecentlyVisitedRooms] variant.
1272    pub const RECENTLY_VISITED_ROOMS: &'static str = "recently_visited_rooms";
1273
1274    /// Key to use for the [`UtdHookManagerData`][Self::UtdHookManagerData]
1275    /// variant.
1276    pub const UTD_HOOK_MANAGER_DATA: &'static str = "utd_hook_manager_data";
1277
1278    /// Key to use for the flag remembering that we already reported that we
1279    /// uploaded duplicate one-time keys.
1280    pub const ONE_TIME_KEY_ALREADY_UPLOADED: &'static str = "one_time_key_already_uploaded";
1281
1282    /// Key prefix to use for the [`ComposerDraft`][Self::ComposerDraft]
1283    /// variant.
1284    pub const COMPOSER_DRAFT: &'static str = "composer_draft";
1285
1286    /// Key prefix to use for the
1287    /// [`SeenKnockRequests`][Self::SeenKnockRequests] variant.
1288    pub const SEEN_KNOCK_REQUESTS: &'static str = "seen_knock_requests";
1289}
1290
1291#[cfg(test)]
1292mod tests {
1293    use super::{ServerInfo, now_timestamp_ms};
1294
1295    #[test]
1296    fn test_stale_server_info() {
1297        let mut server_info = ServerInfo {
1298            versions: Default::default(),
1299            unstable_features: Default::default(),
1300            well_known: Default::default(),
1301            last_fetch_ts: now_timestamp_ms() - ServerInfo::STALE_THRESHOLD - 1.0,
1302        };
1303
1304        // Definitely stale.
1305        assert!(server_info.maybe_decode().is_none());
1306
1307        // Definitely not stale.
1308        server_info.last_fetch_ts = now_timestamp_ms() - 1.0;
1309        assert!(server_info.maybe_decode().is_some());
1310    }
1311}