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 api::MatrixVersion,
28 events::{
29 presence::PresenceEvent,
30 receipt::{Receipt, ReceiptThread, ReceiptType},
31 AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, EmptyStateKey, GlobalAccountDataEvent,
32 GlobalAccountDataEventContent, GlobalAccountDataEventType, RedactContent,
33 RedactedStateEventContent, RoomAccountDataEvent, RoomAccountDataEventContent,
34 RoomAccountDataEventType, StateEventType, StaticEventContent, StaticStateEventContent,
35 },
36 serde::Raw,
37 time::SystemTime,
38 EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedMxcUri, OwnedRoomId,
39 OwnedTransactionId, OwnedUserId, RoomId, TransactionId, UserId,
40};
41use serde::{Deserialize, Serialize};
42
43use super::{
44 send_queue::SentRequestKey, ChildTransactionId, DependentQueuedRequest,
45 DependentQueuedRequestKind, QueueWedgeError, QueuedRequest, QueuedRequestKind,
46 RoomLoadSettings, StateChanges, StoreError,
47};
48use crate::{
49 deserialized_responses::{
50 DisplayName, RawAnySyncOrStrippedState, RawMemberEvent, RawSyncOrStrippedState,
51 },
52 MinimalRoomMemberEvent, RoomInfo, RoomMemberships,
53};
54
55#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
58#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
59pub trait StateStore: AsyncTraitDeps {
60 type Error: fmt::Debug + Into<StoreError> + From<serde_json::Error>;
62
63 async fn get_kv_data(
69 &self,
70 key: StateStoreDataKey<'_>,
71 ) -> Result<Option<StateStoreDataValue>, Self::Error>;
72
73 async fn set_kv_data(
83 &self,
84 key: StateStoreDataKey<'_>,
85 value: StateStoreDataValue,
86 ) -> Result<(), Self::Error>;
87
88 async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error>;
94
95 async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error>;
97
98 async fn get_presence_event(
105 &self,
106 user_id: &UserId,
107 ) -> Result<Option<Raw<PresenceEvent>>, Self::Error>;
108
109 async fn get_presence_events(
115 &self,
116 user_ids: &[OwnedUserId],
117 ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error>;
118
119 async fn get_state_event(
127 &self,
128 room_id: &RoomId,
129 event_type: StateEventType,
130 state_key: &str,
131 ) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error>;
132
133 async fn get_state_events(
141 &self,
142 room_id: &RoomId,
143 event_type: StateEventType,
144 ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error>;
145
146 async fn get_state_events_for_keys(
157 &self,
158 room_id: &RoomId,
159 event_type: StateEventType,
160 state_keys: &[&str],
161 ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error>;
162
163 async fn get_profile(
171 &self,
172 room_id: &RoomId,
173 user_id: &UserId,
174 ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error>;
175
176 async fn get_profiles<'a>(
184 &self,
185 room_id: &RoomId,
186 user_ids: &'a [OwnedUserId],
187 ) -> Result<BTreeMap<&'a UserId, MinimalRoomMemberEvent>, Self::Error>;
188
189 async fn get_user_ids(
192 &self,
193 room_id: &RoomId,
194 memberships: RoomMemberships,
195 ) -> Result<Vec<OwnedUserId>, Self::Error>;
196
197 async fn get_room_infos(
199 &self,
200 room_load_settings: &RoomLoadSettings,
201 ) -> Result<Vec<RoomInfo>, Self::Error>;
202
203 async fn get_users_with_display_name(
212 &self,
213 room_id: &RoomId,
214 display_name: &DisplayName,
215 ) -> Result<BTreeSet<OwnedUserId>, Self::Error>;
216
217 async fn get_users_with_display_names<'a>(
225 &self,
226 room_id: &RoomId,
227 display_names: &'a [DisplayName],
228 ) -> Result<HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>, Self::Error>;
229
230 async fn get_account_data_event(
236 &self,
237 event_type: GlobalAccountDataEventType,
238 ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error>;
239
240 async fn get_room_account_data_event(
250 &self,
251 room_id: &RoomId,
252 event_type: RoomAccountDataEventType,
253 ) -> Result<Option<Raw<AnyRoomAccountDataEvent>>, Self::Error>;
254
255 async fn get_user_room_receipt_event(
268 &self,
269 room_id: &RoomId,
270 receipt_type: ReceiptType,
271 thread: ReceiptThread,
272 user_id: &UserId,
273 ) -> Result<Option<(OwnedEventId, Receipt)>, Self::Error>;
274
275 async fn get_event_room_receipt_events(
289 &self,
290 room_id: &RoomId,
291 receipt_type: ReceiptType,
292 thread: ReceiptThread,
293 event_id: &EventId,
294 ) -> Result<Vec<(OwnedUserId, Receipt)>, Self::Error>;
295
296 async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error>;
302
303 async fn set_custom_value(
312 &self,
313 key: &[u8],
314 value: Vec<u8>,
315 ) -> Result<Option<Vec<u8>>, Self::Error>;
316
317 async fn set_custom_value_no_read(
331 &self,
332 key: &[u8],
333 value: Vec<u8>,
334 ) -> Result<(), Self::Error> {
335 self.set_custom_value(key, value).await.map(|_| ())
336 }
337
338 async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error>;
344
345 async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error>;
351
352 async fn save_send_queue_request(
362 &self,
363 room_id: &RoomId,
364 transaction_id: OwnedTransactionId,
365 created_at: MilliSecondsSinceUnixEpoch,
366 request: QueuedRequestKind,
367 priority: usize,
368 ) -> Result<(), Self::Error>;
369
370 async fn update_send_queue_request(
382 &self,
383 room_id: &RoomId,
384 transaction_id: &TransactionId,
385 content: QueuedRequestKind,
386 ) -> Result<bool, Self::Error>;
387
388 async fn remove_send_queue_request(
394 &self,
395 room_id: &RoomId,
396 transaction_id: &TransactionId,
397 ) -> Result<bool, Self::Error>;
398
399 async fn load_send_queue_requests(
405 &self,
406 room_id: &RoomId,
407 ) -> Result<Vec<QueuedRequest>, Self::Error>;
408
409 async fn update_send_queue_request_status(
412 &self,
413 room_id: &RoomId,
414 transaction_id: &TransactionId,
415 error: Option<QueueWedgeError>,
416 ) -> Result<(), Self::Error>;
417
418 async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error>;
420
421 async fn save_dependent_queued_request(
424 &self,
425 room_id: &RoomId,
426 parent_txn_id: &TransactionId,
427 own_txn_id: ChildTransactionId,
428 created_at: MilliSecondsSinceUnixEpoch,
429 content: DependentQueuedRequestKind,
430 ) -> Result<(), Self::Error>;
431
432 async fn mark_dependent_queued_requests_as_ready(
441 &self,
442 room_id: &RoomId,
443 parent_txn_id: &TransactionId,
444 sent_parent_key: SentRequestKey,
445 ) -> Result<usize, Self::Error>;
446
447 async fn update_dependent_queued_request(
451 &self,
452 room_id: &RoomId,
453 own_transaction_id: &ChildTransactionId,
454 new_content: DependentQueuedRequestKind,
455 ) -> Result<bool, Self::Error>;
456
457 async fn remove_dependent_queued_request(
462 &self,
463 room: &RoomId,
464 own_txn_id: &ChildTransactionId,
465 ) -> Result<bool, Self::Error>;
466
467 async fn load_dependent_queued_requests(
473 &self,
474 room: &RoomId,
475 ) -> Result<Vec<DependentQueuedRequest>, Self::Error>;
476}
477
478#[repr(transparent)]
479struct EraseStateStoreError<T>(T);
480
481#[cfg(not(tarpaulin_include))]
482impl<T: fmt::Debug> fmt::Debug for EraseStateStoreError<T> {
483 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
484 self.0.fmt(f)
485 }
486}
487
488#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
489#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
490impl<T: StateStore> StateStore for EraseStateStoreError<T> {
491 type Error = StoreError;
492
493 async fn get_kv_data(
494 &self,
495 key: StateStoreDataKey<'_>,
496 ) -> Result<Option<StateStoreDataValue>, Self::Error> {
497 self.0.get_kv_data(key).await.map_err(Into::into)
498 }
499
500 async fn set_kv_data(
501 &self,
502 key: StateStoreDataKey<'_>,
503 value: StateStoreDataValue,
504 ) -> Result<(), Self::Error> {
505 self.0.set_kv_data(key, value).await.map_err(Into::into)
506 }
507
508 async fn remove_kv_data(&self, key: StateStoreDataKey<'_>) -> Result<(), Self::Error> {
509 self.0.remove_kv_data(key).await.map_err(Into::into)
510 }
511
512 async fn save_changes(&self, changes: &StateChanges) -> Result<(), Self::Error> {
513 self.0.save_changes(changes).await.map_err(Into::into)
514 }
515
516 async fn get_presence_event(
517 &self,
518 user_id: &UserId,
519 ) -> Result<Option<Raw<PresenceEvent>>, Self::Error> {
520 self.0.get_presence_event(user_id).await.map_err(Into::into)
521 }
522
523 async fn get_presence_events(
524 &self,
525 user_ids: &[OwnedUserId],
526 ) -> Result<Vec<Raw<PresenceEvent>>, Self::Error> {
527 self.0.get_presence_events(user_ids).await.map_err(Into::into)
528 }
529
530 async fn get_state_event(
531 &self,
532 room_id: &RoomId,
533 event_type: StateEventType,
534 state_key: &str,
535 ) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error> {
536 self.0.get_state_event(room_id, event_type, state_key).await.map_err(Into::into)
537 }
538
539 async fn get_state_events(
540 &self,
541 room_id: &RoomId,
542 event_type: StateEventType,
543 ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
544 self.0.get_state_events(room_id, event_type).await.map_err(Into::into)
545 }
546
547 async fn get_state_events_for_keys(
548 &self,
549 room_id: &RoomId,
550 event_type: StateEventType,
551 state_keys: &[&str],
552 ) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
553 self.0.get_state_events_for_keys(room_id, event_type, state_keys).await.map_err(Into::into)
554 }
555
556 async fn get_profile(
557 &self,
558 room_id: &RoomId,
559 user_id: &UserId,
560 ) -> Result<Option<MinimalRoomMemberEvent>, Self::Error> {
561 self.0.get_profile(room_id, user_id).await.map_err(Into::into)
562 }
563
564 async fn get_profiles<'a>(
565 &self,
566 room_id: &RoomId,
567 user_ids: &'a [OwnedUserId],
568 ) -> Result<BTreeMap<&'a UserId, MinimalRoomMemberEvent>, Self::Error> {
569 self.0.get_profiles(room_id, user_ids).await.map_err(Into::into)
570 }
571
572 async fn get_user_ids(
573 &self,
574 room_id: &RoomId,
575 memberships: RoomMemberships,
576 ) -> Result<Vec<OwnedUserId>, Self::Error> {
577 self.0.get_user_ids(room_id, memberships).await.map_err(Into::into)
578 }
579
580 async fn get_room_infos(
581 &self,
582 room_load_settings: &RoomLoadSettings,
583 ) -> Result<Vec<RoomInfo>, Self::Error> {
584 self.0.get_room_infos(room_load_settings).await.map_err(Into::into)
585 }
586
587 async fn get_users_with_display_name(
588 &self,
589 room_id: &RoomId,
590 display_name: &DisplayName,
591 ) -> Result<BTreeSet<OwnedUserId>, Self::Error> {
592 self.0.get_users_with_display_name(room_id, display_name).await.map_err(Into::into)
593 }
594
595 async fn get_users_with_display_names<'a>(
596 &self,
597 room_id: &RoomId,
598 display_names: &'a [DisplayName],
599 ) -> Result<HashMap<&'a DisplayName, BTreeSet<OwnedUserId>>, Self::Error> {
600 self.0.get_users_with_display_names(room_id, display_names).await.map_err(Into::into)
601 }
602
603 async fn get_account_data_event(
604 &self,
605 event_type: GlobalAccountDataEventType,
606 ) -> Result<Option<Raw<AnyGlobalAccountDataEvent>>, Self::Error> {
607 self.0.get_account_data_event(event_type).await.map_err(Into::into)
608 }
609
610 async fn get_room_account_data_event(
611 &self,
612 room_id: &RoomId,
613 event_type: RoomAccountDataEventType,
614 ) -> Result<Option<Raw<AnyRoomAccountDataEvent>>, Self::Error> {
615 self.0.get_room_account_data_event(room_id, event_type).await.map_err(Into::into)
616 }
617
618 async fn get_user_room_receipt_event(
619 &self,
620 room_id: &RoomId,
621 receipt_type: ReceiptType,
622 thread: ReceiptThread,
623 user_id: &UserId,
624 ) -> Result<Option<(OwnedEventId, Receipt)>, Self::Error> {
625 self.0
626 .get_user_room_receipt_event(room_id, receipt_type, thread, user_id)
627 .await
628 .map_err(Into::into)
629 }
630
631 async fn get_event_room_receipt_events(
632 &self,
633 room_id: &RoomId,
634 receipt_type: ReceiptType,
635 thread: ReceiptThread,
636 event_id: &EventId,
637 ) -> Result<Vec<(OwnedUserId, Receipt)>, Self::Error> {
638 self.0
639 .get_event_room_receipt_events(room_id, receipt_type, thread, event_id)
640 .await
641 .map_err(Into::into)
642 }
643
644 async fn get_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
645 self.0.get_custom_value(key).await.map_err(Into::into)
646 }
647
648 async fn set_custom_value(
649 &self,
650 key: &[u8],
651 value: Vec<u8>,
652 ) -> Result<Option<Vec<u8>>, Self::Error> {
653 self.0.set_custom_value(key, value).await.map_err(Into::into)
654 }
655
656 async fn remove_custom_value(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
657 self.0.remove_custom_value(key).await.map_err(Into::into)
658 }
659
660 async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error> {
661 self.0.remove_room(room_id).await.map_err(Into::into)
662 }
663
664 async fn save_send_queue_request(
665 &self,
666 room_id: &RoomId,
667 transaction_id: OwnedTransactionId,
668 created_at: MilliSecondsSinceUnixEpoch,
669 content: QueuedRequestKind,
670 priority: usize,
671 ) -> Result<(), Self::Error> {
672 self.0
673 .save_send_queue_request(room_id, transaction_id, created_at, content, priority)
674 .await
675 .map_err(Into::into)
676 }
677
678 async fn update_send_queue_request(
679 &self,
680 room_id: &RoomId,
681 transaction_id: &TransactionId,
682 content: QueuedRequestKind,
683 ) -> Result<bool, Self::Error> {
684 self.0.update_send_queue_request(room_id, transaction_id, content).await.map_err(Into::into)
685 }
686
687 async fn remove_send_queue_request(
688 &self,
689 room_id: &RoomId,
690 transaction_id: &TransactionId,
691 ) -> Result<bool, Self::Error> {
692 self.0.remove_send_queue_request(room_id, transaction_id).await.map_err(Into::into)
693 }
694
695 async fn load_send_queue_requests(
696 &self,
697 room_id: &RoomId,
698 ) -> Result<Vec<QueuedRequest>, Self::Error> {
699 self.0.load_send_queue_requests(room_id).await.map_err(Into::into)
700 }
701
702 async fn update_send_queue_request_status(
703 &self,
704 room_id: &RoomId,
705 transaction_id: &TransactionId,
706 error: Option<QueueWedgeError>,
707 ) -> Result<(), Self::Error> {
708 self.0
709 .update_send_queue_request_status(room_id, transaction_id, error)
710 .await
711 .map_err(Into::into)
712 }
713
714 async fn load_rooms_with_unsent_requests(&self) -> Result<Vec<OwnedRoomId>, Self::Error> {
715 self.0.load_rooms_with_unsent_requests().await.map_err(Into::into)
716 }
717
718 async fn save_dependent_queued_request(
719 &self,
720 room_id: &RoomId,
721 parent_txn_id: &TransactionId,
722 own_txn_id: ChildTransactionId,
723 created_at: MilliSecondsSinceUnixEpoch,
724 content: DependentQueuedRequestKind,
725 ) -> Result<(), Self::Error> {
726 self.0
727 .save_dependent_queued_request(room_id, parent_txn_id, own_txn_id, created_at, content)
728 .await
729 .map_err(Into::into)
730 }
731
732 async fn mark_dependent_queued_requests_as_ready(
733 &self,
734 room_id: &RoomId,
735 parent_txn_id: &TransactionId,
736 sent_parent_key: SentRequestKey,
737 ) -> Result<usize, Self::Error> {
738 self.0
739 .mark_dependent_queued_requests_as_ready(room_id, parent_txn_id, sent_parent_key)
740 .await
741 .map_err(Into::into)
742 }
743
744 async fn remove_dependent_queued_request(
745 &self,
746 room_id: &RoomId,
747 own_txn_id: &ChildTransactionId,
748 ) -> Result<bool, Self::Error> {
749 self.0.remove_dependent_queued_request(room_id, own_txn_id).await.map_err(Into::into)
750 }
751
752 async fn load_dependent_queued_requests(
753 &self,
754 room_id: &RoomId,
755 ) -> Result<Vec<DependentQueuedRequest>, Self::Error> {
756 self.0.load_dependent_queued_requests(room_id).await.map_err(Into::into)
757 }
758
759 async fn update_dependent_queued_request(
760 &self,
761 room_id: &RoomId,
762 own_transaction_id: &ChildTransactionId,
763 new_content: DependentQueuedRequestKind,
764 ) -> Result<bool, Self::Error> {
765 self.0
766 .update_dependent_queued_request(room_id, own_transaction_id, new_content)
767 .await
768 .map_err(Into::into)
769 }
770}
771
772#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
774#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
775pub trait StateStoreExt: StateStore {
776 async fn get_state_event_static<C>(
782 &self,
783 room_id: &RoomId,
784 ) -> Result<Option<RawSyncOrStrippedState<C>>, Self::Error>
785 where
786 C: StaticEventContent + StaticStateEventContent<StateKey = EmptyStateKey> + RedactContent,
787 C::Redacted: RedactedStateEventContent,
788 {
789 Ok(self.get_state_event(room_id, C::TYPE.into(), "").await?.map(|raw| raw.cast()))
790 }
791
792 async fn get_state_event_static_for_key<C, K>(
798 &self,
799 room_id: &RoomId,
800 state_key: &K,
801 ) -> Result<Option<RawSyncOrStrippedState<C>>, Self::Error>
802 where
803 C: StaticEventContent + StaticStateEventContent + RedactContent,
804 C::StateKey: Borrow<K>,
805 C::Redacted: RedactedStateEventContent,
806 K: AsRef<str> + ?Sized + Sync,
807 {
808 Ok(self
809 .get_state_event(room_id, C::TYPE.into(), state_key.as_ref())
810 .await?
811 .map(|raw| raw.cast()))
812 }
813
814 async fn get_state_events_static<C>(
820 &self,
821 room_id: &RoomId,
822 ) -> Result<Vec<RawSyncOrStrippedState<C>>, Self::Error>
823 where
824 C: StaticEventContent + StaticStateEventContent + RedactContent,
825 C::Redacted: RedactedStateEventContent,
826 {
827 Ok(self
829 .get_state_events(room_id, C::TYPE.into())
830 .await?
831 .into_iter()
832 .map(|raw| raw.cast())
833 .collect())
834 }
835
836 async fn get_state_events_for_keys_static<'a, C, K, I>(
845 &self,
846 room_id: &RoomId,
847 state_keys: I,
848 ) -> Result<Vec<RawSyncOrStrippedState<C>>, Self::Error>
849 where
850 C: StaticEventContent + StaticStateEventContent + RedactContent,
851 C::StateKey: Borrow<K>,
852 C::Redacted: RedactedStateEventContent,
853 K: AsRef<str> + Sized + Sync + 'a,
854 I: IntoIterator<Item = &'a K> + Send,
855 I::IntoIter: Send,
856 {
857 Ok(self
858 .get_state_events_for_keys(
859 room_id,
860 C::TYPE.into(),
861 &state_keys.into_iter().map(|k| k.as_ref()).collect::<Vec<_>>(),
862 )
863 .await?
864 .into_iter()
865 .map(|raw| raw.cast())
866 .collect())
867 }
868
869 async fn get_account_data_event_static<C>(
871 &self,
872 ) -> Result<Option<Raw<GlobalAccountDataEvent<C>>>, Self::Error>
873 where
874 C: StaticEventContent + GlobalAccountDataEventContent,
875 {
876 Ok(self.get_account_data_event(C::TYPE.into()).await?.map(Raw::cast))
877 }
878
879 async fn get_room_account_data_event_static<C>(
887 &self,
888 room_id: &RoomId,
889 ) -> Result<Option<Raw<RoomAccountDataEvent<C>>>, Self::Error>
890 where
891 C: StaticEventContent + RoomAccountDataEventContent,
892 {
893 Ok(self.get_room_account_data_event(room_id, C::TYPE.into()).await?.map(Raw::cast))
894 }
895
896 async fn get_member_event(
904 &self,
905 room_id: &RoomId,
906 state_key: &UserId,
907 ) -> Result<Option<RawMemberEvent>, Self::Error> {
908 self.get_state_event_static_for_key(room_id, state_key).await
909 }
910}
911
912#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
913#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
914impl<T: StateStore + ?Sized> StateStoreExt for T {}
915
916pub type DynStateStore = dyn StateStore<Error = StoreError>;
918
919pub trait IntoStateStore {
925 #[doc(hidden)]
926 fn into_state_store(self) -> Arc<DynStateStore>;
927}
928
929impl<T> IntoStateStore for T
930where
931 T: StateStore + Sized + 'static,
932{
933 fn into_state_store(self) -> Arc<DynStateStore> {
934 Arc::new(EraseStateStoreError(self))
935 }
936}
937
938impl<T> IntoStateStore for Arc<T>
941where
942 T: StateStore + 'static,
943{
944 fn into_state_store(self) -> Arc<DynStateStore> {
945 let ptr: *const T = Arc::into_raw(self);
946 let ptr_erased = ptr as *const EraseStateStoreError<T>;
947 unsafe { Arc::from_raw(ptr_erased) }
950 }
951}
952
953#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
955pub struct ServerCapabilities {
956 pub versions: Vec<String>,
960
961 pub unstable_features: BTreeMap<String, bool>,
963
964 last_fetch_ts: f64,
967}
968
969impl ServerCapabilities {
970 pub const STALE_THRESHOLD: f64 = (1000 * 60 * 60 * 24 * 7) as _; pub fn new(versions: &[MatrixVersion], unstable_features: BTreeMap<String, bool>) -> Self {
975 Self {
976 versions: versions.iter().map(|item| item.to_string()).collect(),
977 unstable_features,
978 last_fetch_ts: now_timestamp_ms(),
979 }
980 }
981
982 pub fn maybe_decode(&self) -> Option<(Vec<MatrixVersion>, BTreeMap<String, bool>)> {
988 if now_timestamp_ms() - self.last_fetch_ts >= Self::STALE_THRESHOLD {
989 None
990 } else {
991 Some((
992 self.versions.iter().filter_map(|item| item.parse().ok()).collect(),
993 self.unstable_features.clone(),
994 ))
995 }
996 }
997}
998
999fn now_timestamp_ms() -> f64 {
1001 SystemTime::now()
1002 .duration_since(SystemTime::UNIX_EPOCH)
1003 .expect("System clock was before 1970.")
1004 .as_secs_f64()
1005 * 1000.0
1006}
1007
1008#[derive(Debug, Clone)]
1010pub enum StateStoreDataValue {
1011 SyncToken(String),
1013
1014 ServerCapabilities(ServerCapabilities),
1016
1017 Filter(String),
1019
1020 UserAvatarUrl(OwnedMxcUri),
1022
1023 RecentlyVisitedRooms(Vec<OwnedRoomId>),
1025
1026 UtdHookManagerData(GrowableBloom),
1029
1030 ComposerDraft(ComposerDraft),
1035
1036 SeenKnockRequests(BTreeMap<OwnedEventId, OwnedUserId>),
1038}
1039
1040#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1042pub struct ComposerDraft {
1043 pub plain_text: String,
1045 pub html_text: Option<String>,
1048 pub draft_type: ComposerDraftType,
1050}
1051
1052#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1054pub enum ComposerDraftType {
1055 NewMessage,
1057 Reply {
1059 event_id: OwnedEventId,
1061 },
1062 Edit {
1064 event_id: OwnedEventId,
1066 },
1067}
1068
1069impl StateStoreDataValue {
1070 pub fn into_sync_token(self) -> Option<String> {
1072 as_variant!(self, Self::SyncToken)
1073 }
1074
1075 pub fn into_filter(self) -> Option<String> {
1077 as_variant!(self, Self::Filter)
1078 }
1079
1080 pub fn into_user_avatar_url(self) -> Option<OwnedMxcUri> {
1082 as_variant!(self, Self::UserAvatarUrl)
1083 }
1084
1085 pub fn into_recently_visited_rooms(self) -> Option<Vec<OwnedRoomId>> {
1087 as_variant!(self, Self::RecentlyVisitedRooms)
1088 }
1089
1090 pub fn into_utd_hook_manager_data(self) -> Option<GrowableBloom> {
1092 as_variant!(self, Self::UtdHookManagerData)
1093 }
1094
1095 pub fn into_composer_draft(self) -> Option<ComposerDraft> {
1097 as_variant!(self, Self::ComposerDraft)
1098 }
1099
1100 pub fn into_server_capabilities(self) -> Option<ServerCapabilities> {
1102 as_variant!(self, Self::ServerCapabilities)
1103 }
1104
1105 pub fn into_seen_knock_requests(self) -> Option<BTreeMap<OwnedEventId, OwnedUserId>> {
1107 as_variant!(self, Self::SeenKnockRequests)
1108 }
1109}
1110
1111#[derive(Debug, Clone, Copy)]
1113pub enum StateStoreDataKey<'a> {
1114 SyncToken,
1116
1117 ServerCapabilities,
1119
1120 Filter(&'a str),
1122
1123 UserAvatarUrl(&'a UserId),
1125
1126 RecentlyVisitedRooms(&'a UserId),
1128
1129 UtdHookManagerData,
1132
1133 ComposerDraft(&'a RoomId),
1138
1139 SeenKnockRequests(&'a RoomId),
1141}
1142
1143impl StateStoreDataKey<'_> {
1144 pub const SYNC_TOKEN: &'static str = "sync_token";
1146 pub const SERVER_CAPABILITIES: &'static str = "server_capabilities";
1149 pub const FILTER: &'static str = "filter";
1151 pub const USER_AVATAR_URL: &'static str = "user_avatar_url";
1154
1155 pub const RECENTLY_VISITED_ROOMS: &'static str = "recently_visited_rooms";
1158
1159 pub const UTD_HOOK_MANAGER_DATA: &'static str = "utd_hook_manager_data";
1162
1163 pub const COMPOSER_DRAFT: &'static str = "composer_draft";
1166
1167 pub const SEEN_KNOCK_REQUESTS: &'static str = "seen_knock_requests";
1170}
1171
1172#[cfg(test)]
1173mod tests {
1174 use super::{now_timestamp_ms, ServerCapabilities};
1175
1176 #[test]
1177 fn test_stale_server_capabilities() {
1178 let mut caps = ServerCapabilities {
1179 versions: Default::default(),
1180 unstable_features: Default::default(),
1181 last_fetch_ts: now_timestamp_ms() - ServerCapabilities::STALE_THRESHOLD - 1.0,
1182 };
1183
1184 assert!(caps.maybe_decode().is_none());
1186
1187 caps.last_fetch_ts = now_timestamp_ms() - 1.0;
1189 assert!(caps.maybe_decode().is_some());
1190 }
1191}