1use 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#[cfg_attr(target_family = "wasm", async_trait(?Send))]
64#[cfg_attr(not(target_family = "wasm"), async_trait)]
65pub trait StateStore: AsyncTraitDeps {
66 type Error: fmt::Debug + Into<StoreError> + From<serde_json::Error>;
68
69 async fn get_kv_data(
75 &self,
76 key: StateStoreDataKey<'_>,
77 ) -> Result<Option<StateStoreDataValue>, Self::Error>;
78
79 async fn set_kv_data(
89 &self,
90 key: StateStoreDataKey<'_>,
91 value: StateStoreDataValue,
92 ) -> Result<(), Self::Error>;
93
94 async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error>;
100
101 async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error>;
103
104 async fn get_presence_event(
111 &self,
112 user_id: &UserId,
113 ) -> Result<Option<Raw<PresenceEvent>>, Self::Error>;
114
115 async fn get_presence_events(
121 &self,
122 user_ids: &[OwnedUserId],
123 ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error>;
124
125 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 async fn get_state_events(
147 &self,
148 room_id: &RoomId,
149 event_type: StateEventType,
150 ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error>;
151
152 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 async fn get_profile(
177 &self,
178 room_id: &RoomId,
179 user_id: &UserId,
180 ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error>;
181
182 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 async fn get_user_ids(
198 &self,
199 room_id: &RoomId,
200 memberships: RoomMemberships,
201 ) -> Result<Vec<OwnedUserId>, Self::Error>;
202
203 async fn get_room_infos(
205 &self,
206 room_load_settings: &RoomLoadSettings,
207 ) -> Result<Vec<RoomInfo>, Self::Error>;
208
209 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 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 async fn get_account_data_event(
242 &self,
243 event_type: GlobalAccountDataEventType,
244 ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error>;
245
246 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 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 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 async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error>;
308
309 async fn set_custom_value(
318 &self,
319 key: &[u8],
320 value: Vec<u8>,
321 ) -> Result<Option<Vec<u8>>, Self::Error>;
322
323 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 async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error>;
350
351 async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error>;
357
358 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 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 async fn remove_send_queue_request(
400 &self,
401 room_id: &RoomId,
402 transaction_id: &TransactionId,
403 ) -> Result<bool, Self::Error>;
404
405 async fn load_send_queue_requests(
411 &self,
412 room_id: &RoomId,
413 ) -> Result<Vec<QueuedRequest>, Self::Error>;
414
415 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 async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error>;
426
427 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 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 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 async fn remove_dependent_queued_request(
468 &self,
469 room: &RoomId,
470 own_txn_id: &ChildTransactionId,
471 ) -> Result<bool, Self::Error>;
472
473 async fn load_dependent_queued_requests(
479 &self,
480 room: &RoomId,
481 ) -> Result<Vec<DependentQueuedRequest>, Self::Error>;
482
483 async fn upsert_thread_subscription(
485 &self,
486 room: &RoomId,
487 thread_id: &EventId,
488 subscription: ThreadSubscription,
489 ) -> Result<(), Self::Error>;
490
491 async fn remove_thread_subscription(
495 &self,
496 room: &RoomId,
497 thread_id: &EventId,
498 ) -> Result<(), Self::Error>;
499
500 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#[cfg_attr(target_family = "wasm", async_trait(?Send))]
831#[cfg_attr(not(target_family = "wasm"), async_trait)]
832pub trait StateStoreExt: StateStore {
833 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 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 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 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 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 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 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 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
984pub type DynStateStore = dyn StateStore<Error = StoreError>;
986
987pub 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
1006impl<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 unsafe { Arc::from_raw(ptr_erased) }
1018 }
1019}
1020
1021#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1024pub struct ServerInfo {
1025 pub versions: Vec<String>,
1027
1028 pub unstable_features: BTreeMap<String, bool>,
1030
1031 #[serde(skip_serializing_if = "Option::is_none")]
1033 pub well_known: Option<WellKnownResponse>,
1034
1035 last_fetch_ts: f64,
1038}
1039
1040impl ServerInfo {
1041 pub const STALE_THRESHOLD: f64 = (1000 * 60 * 60 * 24 * 7) as _; 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 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 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)]
1077pub struct WellKnownResponse {
1079 pub homeserver: HomeserverInfo,
1081
1082 pub identity_server: Option<IdentityServerInfo>,
1084
1085 pub tile_server: Option<TileServerInfo>,
1087
1088 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
1103fn 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#[derive(Debug, Clone)]
1114pub enum StateStoreDataValue {
1115 SyncToken(String),
1117
1118 ServerInfo(ServerInfo),
1120
1121 Filter(String),
1123
1124 UserAvatarUrl(OwnedMxcUri),
1126
1127 RecentlyVisitedRooms(Vec<OwnedRoomId>),
1129
1130 UtdHookManagerData(GrowableBloom),
1133
1134 OneTimeKeyAlreadyUploaded,
1137
1138 ComposerDraft(ComposerDraft),
1143
1144 SeenKnockRequests(BTreeMap<OwnedEventId, OwnedUserId>),
1146}
1147
1148#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1150pub struct ComposerDraft {
1151 pub plain_text: String,
1153 pub html_text: Option<String>,
1156 pub draft_type: ComposerDraftType,
1158}
1159
1160#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1162pub enum ComposerDraftType {
1163 NewMessage,
1165 Reply {
1167 event_id: OwnedEventId,
1169 },
1170 Edit {
1172 event_id: OwnedEventId,
1174 },
1175}
1176
1177impl StateStoreDataValue {
1178 pub fn into_sync_token(self) -> Option<String> {
1180 as_variant!(self, Self::SyncToken)
1181 }
1182
1183 pub fn into_filter(self) -> Option<String> {
1185 as_variant!(self, Self::Filter)
1186 }
1187
1188 pub fn into_user_avatar_url(self) -> Option<OwnedMxcUri> {
1190 as_variant!(self, Self::UserAvatarUrl)
1191 }
1192
1193 pub fn into_recently_visited_rooms(self) -> Option<Vec<OwnedRoomId>> {
1195 as_variant!(self, Self::RecentlyVisitedRooms)
1196 }
1197
1198 pub fn into_utd_hook_manager_data(self) -> Option<GrowableBloom> {
1200 as_variant!(self, Self::UtdHookManagerData)
1201 }
1202
1203 pub fn into_composer_draft(self) -> Option<ComposerDraft> {
1205 as_variant!(self, Self::ComposerDraft)
1206 }
1207
1208 pub fn into_server_info(self) -> Option<ServerInfo> {
1210 as_variant!(self, Self::ServerInfo)
1211 }
1212
1213 pub fn into_seen_knock_requests(self) -> Option<BTreeMap<OwnedEventId, OwnedUserId>> {
1215 as_variant!(self, Self::SeenKnockRequests)
1216 }
1217}
1218
1219#[derive(Debug, Clone, Copy)]
1221pub enum StateStoreDataKey<'a> {
1222 SyncToken,
1224
1225 ServerInfo,
1227
1228 Filter(&'a str),
1230
1231 UserAvatarUrl(&'a UserId),
1233
1234 RecentlyVisitedRooms(&'a UserId),
1236
1237 UtdHookManagerData,
1240
1241 OneTimeKeyAlreadyUploaded,
1244
1245 ComposerDraft(&'a RoomId, Option<&'a EventId>),
1250
1251 SeenKnockRequests(&'a RoomId),
1253}
1254
1255impl StateStoreDataKey<'_> {
1256 pub const SYNC_TOKEN: &'static str = "sync_token";
1258
1259 pub const SERVER_INFO: &'static str = "server_capabilities"; pub const FILTER: &'static str = "filter";
1265
1266 pub const USER_AVATAR_URL: &'static str = "user_avatar_url";
1269
1270 pub const RECENTLY_VISITED_ROOMS: &'static str = "recently_visited_rooms";
1273
1274 pub const UTD_HOOK_MANAGER_DATA: &'static str = "utd_hook_manager_data";
1277
1278 pub const ONE_TIME_KEY_ALREADY_UPLOADED: &'static str = "one_time_key_already_uploaded";
1281
1282 pub const COMPOSER_DRAFT: &'static str = "composer_draft";
1285
1286 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 assert!(server_info.maybe_decode().is_none());
1306
1307 server_info.last_fetch_ts = now_timestamp_ms() - 1.0;
1309 assert!(server_info.maybe_decode().is_some());
1310 }
1311}