1use std::{
16 cmp::Ordering,
17 collections::{VecDeque, vec_deque::Iter},
18 iter::{Enumerate, Skip, Take},
19 ops::{Deref, RangeBounds},
20 sync::Arc,
21};
22
23use bitflags::bitflags;
24use eyeball_im::{
25 ObservableVector, ObservableVectorEntries, ObservableVectorEntry, ObservableVectorTransaction,
26 ObservableVectorTransactionEntry, VectorSubscriber,
27};
28use imbl::Vector;
29use ruma::EventId;
30
31use super::{TimelineItem, metadata::EventMeta};
32
33#[derive(Debug)]
70pub struct ObservableItems {
71 items: ObservableVector<Arc<TimelineItem>>,
79
80 all_remote_events: AllRemoteEvents,
88}
89
90impl ObservableItems {
91 pub fn new() -> Self {
93 Self {
94 items: ObservableVector::with_capacity(32),
98 all_remote_events: AllRemoteEvents::default(),
99 }
100 }
101
102 pub fn all_remote_events(&self) -> &AllRemoteEvents {
104 &self.all_remote_events
105 }
106
107 pub fn is_empty(&self) -> bool {
109 self.items.is_empty()
110 }
111
112 pub fn subscribe(&self) -> VectorSubscriber<Arc<TimelineItem>> {
114 self.items.subscribe()
115 }
116
117 pub fn clone_items(&self) -> Vector<Arc<TimelineItem>> {
121 self.items.clone()
122 }
123
124 pub fn transaction(&mut self) -> ObservableItemsTransaction<'_> {
126 ObservableItemsTransaction {
127 items: self.items.transaction(),
128 all_remote_events: &mut self.all_remote_events,
129 }
130 }
131
132 pub fn replace(
139 &mut self,
140 timeline_item_index: usize,
141 timeline_item: Arc<TimelineItem>,
142 ) -> Arc<TimelineItem> {
143 self.items.set(timeline_item_index, timeline_item)
144 }
145
146 pub fn entries(&mut self) -> ObservableItemsEntries<'_> {
148 ObservableItemsEntries(self.items.entries())
149 }
150
151 pub fn for_each<F>(&mut self, mut f: F)
154 where
155 F: FnMut(ObservableItemsEntry<'_>),
156 {
157 self.items.for_each(|entry| f(ObservableItemsEntry(entry)))
158 }
159}
160
161impl Deref for ObservableItems {
167 type Target = Vector<Arc<TimelineItem>>;
168
169 fn deref(&self) -> &Self::Target {
170 &self.items
171 }
172}
173
174pub struct ObservableItemsEntries<'a>(ObservableVectorEntries<'a, Arc<TimelineItem>>);
181
182impl ObservableItemsEntries<'_> {
183 pub fn next(&mut self) -> Option<ObservableItemsEntry<'_>> {
186 self.0.next().map(ObservableItemsEntry)
187 }
188}
189
190#[derive(Debug)]
192pub struct ObservableItemsEntry<'a>(ObservableVectorEntry<'a, Arc<TimelineItem>>);
193
194impl ObservableItemsEntry<'_> {
195 pub fn replace(this: &mut Self, timeline_item: Arc<TimelineItem>) -> Arc<TimelineItem> {
197 ObservableVectorEntry::set(&mut this.0, timeline_item)
198 }
199}
200
201impl Deref for ObservableItemsEntry<'_> {
207 type Target = Arc<TimelineItem>;
208
209 fn deref(&self) -> &Self::Target {
210 &self.0
211 }
212}
213
214#[derive(Debug)]
221pub struct ObservableItemsTransaction<'observable_items> {
222 items: ObservableVectorTransaction<'observable_items, Arc<TimelineItem>>,
223 all_remote_events: &'observable_items mut AllRemoteEvents,
224}
225
226impl<'observable_items> ObservableItemsTransaction<'observable_items> {
227 pub fn get(&self, timeline_item_index: usize) -> Option<&Arc<TimelineItem>> {
229 self.items.get(timeline_item_index)
230 }
231
232 pub fn all_remote_events(&self) -> &AllRemoteEvents {
234 self.all_remote_events
235 }
236
237 pub fn remove_remote_event(&mut self, event_index: usize) -> Option<EventMeta> {
241 self.all_remote_events.remove(event_index)
242 }
243
244 pub fn push_front_remote_event(&mut self, event_meta: EventMeta) {
248 self.all_remote_events.push_front(event_meta);
249 }
250
251 pub fn push_back_remote_event(&mut self, event_meta: EventMeta) {
255 self.all_remote_events.push_back(event_meta);
256 }
257
258 pub fn insert_remote_event(&mut self, event_index: usize, event_meta: EventMeta) {
262 self.all_remote_events.insert(event_index, event_meta);
263 }
264
265 pub fn get_remote_event_by_event_id_mut(
267 &mut self,
268 event_id: &EventId,
269 ) -> Option<&mut EventMeta> {
270 self.all_remote_events.get_by_event_id_mut(event_id)
271 }
272
273 pub fn get_remote_event_by_event_id(&self, event_id: &EventId) -> Option<&EventMeta> {
275 self.all_remote_events.get_by_event_id(event_id)
276 }
277
278 pub fn position_by_event_id(&self, event_id: &EventId) -> Option<usize> {
280 self.all_remote_events.position_by_event_id(event_id)
281 }
282
283 pub fn replace(
286 &mut self,
287 timeline_item_index: usize,
288 timeline_item: Arc<TimelineItem>,
289 ) -> Arc<TimelineItem> {
290 self.items.set(timeline_item_index, timeline_item)
291 }
292
293 pub fn remove(&mut self, timeline_item_index: usize) -> Arc<TimelineItem> {
295 let removed_timeline_item = self.items.remove(timeline_item_index);
296 self.all_remote_events.timeline_item_has_been_removed_at(timeline_item_index);
297
298 removed_timeline_item
299 }
300
301 pub fn insert(
310 &mut self,
311 timeline_item_index: usize,
312 timeline_item: Arc<TimelineItem>,
313 event_index: Option<usize>,
314 ) {
315 self.items.insert(timeline_item_index, timeline_item);
316 self.all_remote_events.timeline_item_has_been_inserted_at(timeline_item_index, event_index);
317 }
318
319 pub fn push_front(&mut self, timeline_item: Arc<TimelineItem>, event_index: Option<usize>) {
328 self.items.push_front(timeline_item);
329 self.all_remote_events.timeline_item_has_been_inserted_at(0, event_index);
330 }
331
332 pub fn push_back(&mut self, timeline_item: Arc<TimelineItem>, event_index: Option<usize>) {
341 self.items.push_back(timeline_item);
342 self.all_remote_events
343 .timeline_item_has_been_inserted_at(self.items.len().saturating_sub(1), event_index);
344 }
345
346 pub fn push_local(&mut self, timeline_item: Arc<TimelineItem>) {
358 assert!(timeline_item.is_local_echo(), "The provided `timeline_item` is not a `Local`");
359
360 self.push_back(timeline_item, None);
361 }
362
363 pub fn push_date_divider(
376 &mut self,
377 timeline_item_index: usize,
378 timeline_item: Arc<TimelineItem>,
379 ) {
380 assert!(
381 timeline_item.is_date_divider(),
382 "The provided `timeline_item` is not a `DateDivider`"
383 );
384
385 if timeline_item_index == 0 && !self.items.is_empty() {
387 assert!(
388 matches!(self.items.get(timeline_item_index), Some(timeline_item) if !timeline_item.is_timeline_start())
389 );
390 }
391
392 if timeline_item_index == self.len() {
393 self.push_back(timeline_item, None);
394 } else if timeline_item_index == 0 {
395 self.push_front(timeline_item, None);
396 } else {
397 self.insert(timeline_item_index, timeline_item, None);
398 }
399 }
400
401 pub fn push_timeline_start_if_missing(&mut self, timeline_item: Arc<TimelineItem>) {
413 assert!(
414 timeline_item.is_timeline_start(),
415 "The provided `timeline_item` is not a `TimelineStart`"
416 );
417
418 if self.get(0).is_some_and(|item| item.is_timeline_start()) {
420 return;
421 }
422
423 self.push_front(timeline_item, None);
424 }
425
426 pub fn clear(&mut self) {
428 self.items.clear();
429 self.all_remote_events.clear();
430 }
431
432 pub fn for_each<F>(&mut self, mut f: F)
435 where
436 F: FnMut(ObservableItemsTransactionEntry<'_, 'observable_items>),
437 {
438 self.items.for_each(|entry| {
439 f(ObservableItemsTransactionEntry { entry, all_remote_events: self.all_remote_events })
440 })
441 }
442
443 pub fn has_local(&self) -> bool {
447 matches!(self.items.last(), Some(timeline_item) if timeline_item.is_local_echo())
448 }
449
450 pub fn first_remotes_region_index(&self) -> usize {
453 if self.items.get(0).is_some_and(|item| item.is_timeline_start()) { 1 } else { 0 }
454 }
455
456 pub fn iter_remotes_region(&self) -> ObservableItemsTransactionIter<'_> {
458 ObservableItemsTransactionIterBuilder::new(&self.items).with_remotes().build()
459 }
460
461 pub fn iter_remotes_and_locals_regions(&self) -> ObservableItemsTransactionIter<'_> {
463 ObservableItemsTransactionIterBuilder::new(&self.items).with_remotes().with_locals().build()
464 }
465
466 pub fn iter_locals_region(&self) -> ObservableItemsTransactionIter<'_> {
468 ObservableItemsTransactionIterBuilder::new(&self.items).with_locals().build()
469 }
470
471 pub fn iter_all_regions(&self) -> ObservableItemsTransactionIter<'_> {
473 ObservableItemsTransactionIterBuilder::new(&self.items)
474 .with_start()
475 .with_remotes()
476 .with_locals()
477 .build()
478 }
479
480 #[allow(unused)] #[deprecated = "This method is now aliased to `Self::iter_all_regions`"]
488 pub fn iter(&self) -> ObservableItemsTransactionIter<'_> {
489 self.iter_all_regions()
490 }
491
492 pub fn commit(self) {
495 self.items.commit()
496 }
497}
498
499bitflags! {
500 struct Regions: u8 {
501 const START = 0b0000_0001;
505
506 const REMOTES = 0b0000_0010;
513
514 const LOCALS = 0b0000_0100;
520 }
521}
522
523struct ObservableItemsTransactionIterBuilder<'e> {
525 items: &'e ObservableVectorTransaction<'e, Arc<TimelineItem>>,
527
528 regions: Regions,
530}
531
532impl<'e> ObservableItemsTransactionIterBuilder<'e> {
533 fn new(items: &'e ObservableVectorTransaction<'e, Arc<TimelineItem>>) -> Self {
535 Self { items, regions: Regions::empty() }
536 }
537
538 fn with_start(mut self) -> Self {
540 self.regions.insert(Regions::START);
541 self
542 }
543
544 fn with_remotes(mut self) -> Self {
546 self.regions.insert(Regions::REMOTES);
547 self
548 }
549
550 fn with_locals(mut self) -> Self {
552 self.regions.insert(Regions::LOCALS);
553 self
554 }
555
556 #[allow(clippy::iter_skip_zero)]
558 fn build(self) -> ObservableItemsTransactionIter<'e> {
559 let size_of_start_region = if matches!(
561 self.items.get(0),
562 Some(first_timeline_item) if first_timeline_item.is_timeline_start()
563 ) {
564 1
565 } else {
566 0
567 };
568
569 let size_of_locals_region = self
571 .items
572 .deref()
573 .iter()
574 .rev()
575 .take_while(|timeline_item| timeline_item.is_local_echo())
576 .count();
577
578 let size_of_remotes_region =
580 self.items.len() - size_of_start_region - size_of_locals_region;
581
582 let with_start = self.regions.contains(Regions::START);
583 let with_remotes = self.regions.contains(Regions::REMOTES);
584 let with_locals = self.regions.contains(Regions::LOCALS);
585
586 let iter = self.items.deref().iter().enumerate();
588 let inner = match (with_start, with_remotes, with_locals) {
589 (false, false, false) => iter.skip(0).take(0),
591
592 (true, false, false) => iter.skip(0).take(size_of_start_region),
594
595 (false, true, false) => iter.skip(size_of_start_region).take(size_of_remotes_region),
597
598 (true, true, false) => iter.skip(0).take(size_of_start_region + size_of_remotes_region),
600
601 (false, false, true) => {
603 iter.skip(size_of_start_region + size_of_remotes_region).take(size_of_locals_region)
604 }
605
606 (true, false, true) => unimplemented!(
611 "Iterating over the start and the locals regions is not implemented yet"
612 ),
613
614 (false, true, true) => {
616 iter.skip(size_of_start_region).take(size_of_remotes_region + size_of_locals_region)
617 }
618
619 (true, true, true) => iter
621 .skip(0)
622 .take(size_of_start_region + size_of_remotes_region + size_of_locals_region),
623 };
624
625 ObservableItemsTransactionIter { inner }
626 }
627}
628
629pub(crate) struct ObservableItemsTransactionIter<'observable_items_transaction> {
631 #[allow(clippy::type_complexity)]
632 inner: Take<
633 Skip<
634 Enumerate<
635 imbl::vector::Iter<
636 'observable_items_transaction,
637 Arc<TimelineItem>,
638 imbl::shared_ptr::DefaultSharedPtr,
639 >,
640 >,
641 >,
642 >,
643}
644
645impl<'e> Iterator for ObservableItemsTransactionIter<'e> {
646 type Item = (usize, &'e Arc<TimelineItem>);
647
648 fn next(&mut self) -> Option<Self::Item> {
649 self.inner.next()
650 }
651}
652
653impl ExactSizeIterator for ObservableItemsTransactionIter<'_> {
654 fn len(&self) -> usize {
655 self.inner.len()
656 }
657}
658
659impl DoubleEndedIterator for ObservableItemsTransactionIter<'_> {
660 fn next_back(&mut self) -> Option<Self::Item> {
661 self.inner.next_back()
662 }
663}
664
665impl Deref for ObservableItemsTransaction<'_> {
671 type Target = Vector<Arc<TimelineItem>>;
672
673 fn deref(&self) -> &Self::Target {
674 &self.items
675 }
676}
677
678pub struct ObservableItemsTransactionEntry<'observable_transaction_items, 'observable_items> {
680 entry: ObservableVectorTransactionEntry<
681 'observable_transaction_items,
682 'observable_items,
683 Arc<TimelineItem>,
684 >,
685 all_remote_events: &'observable_transaction_items mut AllRemoteEvents,
686}
687
688impl ObservableItemsTransactionEntry<'_, '_> {
689 pub fn remove(this: Self) {
691 let entry_index = ObservableVectorTransactionEntry::index(&this.entry);
692
693 ObservableVectorTransactionEntry::remove(this.entry);
694 this.all_remote_events.timeline_item_has_been_removed_at(entry_index);
695 }
696}
697
698impl Deref for ObservableItemsTransactionEntry<'_, '_> {
704 type Target = Arc<TimelineItem>;
705
706 fn deref(&self) -> &Self::Target {
707 &self.entry
708 }
709}
710
711#[cfg(test)]
712mod observable_items_tests {
713 use std::ops::Not;
714
715 use assert_matches::assert_matches;
716 use eyeball_im::VectorDiff;
717 use ruma::{
718 MilliSecondsSinceUnixEpoch,
719 events::room::message::{MessageType, TextMessageEventContent},
720 owned_user_id, uint,
721 };
722 use stream_assert::{assert_next_matches, assert_pending};
723
724 use super::*;
725 use crate::timeline::{
726 EventSendState, EventTimelineItem, Message, MsgLikeContent, MsgLikeKind, TimelineDetails,
727 TimelineItemContent, TimelineItemKind, TimelineUniqueId, VirtualTimelineItem,
728 controller::RemoteEventOrigin,
729 event_item::{EventTimelineItemKind, LocalEventTimelineItem, RemoteEventTimelineItem},
730 };
731
732 fn item(event_id: &str) -> Arc<TimelineItem> {
733 TimelineItem::new(
734 EventTimelineItem::new(
735 owned_user_id!("@ivan:mnt.io"),
736 TimelineDetails::Unavailable,
737 MilliSecondsSinceUnixEpoch(0u32.into()),
738 TimelineItemContent::MsgLike(MsgLikeContent {
739 kind: MsgLikeKind::Message(Message {
740 msgtype: MessageType::Text(TextMessageEventContent::plain("hello")),
741 edited: false,
742 mentions: None,
743 }),
744 reactions: Default::default(),
745 thread_root: None,
746 in_reply_to: None,
747 thread_summary: None,
748 }),
749 EventTimelineItemKind::Remote(RemoteEventTimelineItem {
750 event_id: event_id.parse().unwrap(),
751 transaction_id: None,
752 read_receipts: Default::default(),
753 is_own: false,
754 is_highlighted: false,
755 encryption_info: None,
756 original_json: None,
757 latest_edit_json: None,
758 origin: RemoteEventOrigin::Sync,
759 }),
760 false,
761 ),
762 TimelineUniqueId(format!("__eid_{event_id}")),
763 )
764 }
765
766 fn local_item(transaction_id: &str) -> Arc<TimelineItem> {
767 TimelineItem::new(
768 EventTimelineItem::new(
769 owned_user_id!("@ivan:mnt.io"),
770 TimelineDetails::Unavailable,
771 MilliSecondsSinceUnixEpoch(0u32.into()),
772 TimelineItemContent::MsgLike(MsgLikeContent {
773 kind: MsgLikeKind::Message(Message {
774 msgtype: MessageType::Text(TextMessageEventContent::plain("hello")),
775 edited: false,
776 mentions: None,
777 }),
778 reactions: Default::default(),
779 thread_root: None,
780 in_reply_to: None,
781 thread_summary: None,
782 }),
783 EventTimelineItemKind::Local(LocalEventTimelineItem {
784 send_state: EventSendState::NotSentYet { progress: None },
785 transaction_id: transaction_id.into(),
786 send_handle: None,
787 }),
788 false,
789 ),
790 TimelineUniqueId(format!("__tid_{transaction_id}")),
791 )
792 }
793
794 fn read_marker() -> Arc<TimelineItem> {
795 TimelineItem::read_marker()
796 }
797
798 fn event_meta(event_id: &str) -> EventMeta {
799 EventMeta { event_id: event_id.parse().unwrap(), timeline_item_index: None, visible: false }
800 }
801
802 macro_rules! assert_event_id {
803 ( $timeline_item:expr, $event_id:literal $( , $message:expr )? $(,)? ) => {
804 assert_eq!($timeline_item.as_event().unwrap().event_id().unwrap().as_str(), $event_id $( , $message)? );
805 };
806 }
807
808 macro_rules! assert_transaction_id {
809 ( $timeline_item:expr, $transaction_id:literal $( , $message:expr )? $(,)? ) => {
810 assert_eq!($timeline_item.as_event().unwrap().transaction_id().unwrap().as_str(), $transaction_id $( , $message)? );
811 };
812 }
813
814 macro_rules! assert_mapping {
815 ( on $transaction:ident:
816 | event_id | event_index | timeline_item_index |
817 | $( - )+ | $( - )+ | $( - )+ |
818 $(
819 | $event_id:literal | $event_index:literal | $( $timeline_item_index:literal )? |
820 )+
821 ) => {
822 let all_remote_events = $transaction .all_remote_events();
823
824 $(
825 assert_matches!(all_remote_events.0.get( $event_index ), Some(EventMeta { event_id, timeline_item_index, .. }) => {
827 assert_eq!(
829 event_id.as_str(),
830 $event_id ,
831 concat!("event #", $event_index, " should have ID ", $event_id)
832 );
833
834
835 #[allow(unused_variables)]
837 let timeline_item_index_is_expected = false;
838 $(
839 let timeline_item_index_is_expected = true;
840 let _ = $timeline_item_index;
841 )?
842
843 if timeline_item_index_is_expected.not() {
844 assert!(
846 timeline_item_index.is_none(),
847 concat!("event #", $event_index, " with ID ", $event_id, " should NOT map to a timeline item index" )
848 );
849 }
850
851 $(
852 assert_eq!(
854 *timeline_item_index,
855 Some( $timeline_item_index ),
856 concat!("event #", $event_index, " with ID ", $event_id, " should map to timeline item #", $timeline_item_index )
857 );
858
859 assert_matches!( $transaction .get( $timeline_item_index ), Some(timeline_item) => {
861 assert_event_id!(
863 timeline_item,
864 $event_id ,
865 concat!("timeline item #", $timeline_item_index, " should map to event ID ", $event_id )
866 );
867 });
868 )?
869 });
870 )*
871 }
872 }
873
874 #[test]
875 fn test_is_empty() {
876 let mut items = ObservableItems::new();
877
878 assert!(items.is_empty());
879
880 let mut transaction = items.transaction();
882 transaction.push_back(item("$ev0"), Some(0));
883 transaction.commit();
884
885 assert!(items.is_empty().not());
886 }
887
888 #[test]
889 fn test_subscribe() {
890 let mut items = ObservableItems::new();
891 let mut subscriber = items.subscribe().into_stream();
892
893 let mut transaction = items.transaction();
895 transaction.push_back(item("$ev0"), Some(0));
896 transaction.commit();
897
898 assert_next_matches!(subscriber, VectorDiff::PushBack { value: event } => {
900 assert_event_id!(event, "$ev0");
901 });
902 }
903
904 #[test]
905 fn test_clone_items() {
906 let mut items = ObservableItems::new();
907
908 let mut transaction = items.transaction();
909 transaction.push_back(item("$ev0"), Some(0));
910 transaction.push_back(item("$ev1"), Some(1));
911 transaction.commit();
912
913 let items = items.clone_items();
914 assert_eq!(items.len(), 2);
915 assert_event_id!(items[0], "$ev0");
916 assert_event_id!(items[1], "$ev1");
917 }
918
919 #[test]
920 fn test_replace() {
921 let mut items = ObservableItems::new();
922
923 let mut transaction = items.transaction();
925 transaction.push_back(item("$ev0"), Some(0));
926 transaction.commit();
927
928 items.replace(0, item("$ev1"));
930
931 let items = items.clone_items();
932 assert_eq!(items.len(), 1);
933 assert_event_id!(items[0], "$ev1");
934 }
935
936 #[test]
937 fn test_entries() {
938 let mut items = ObservableItems::new();
939
940 let mut transaction = items.transaction();
942 transaction.push_back(item("$ev0"), Some(0));
943 transaction.push_back(item("$ev1"), Some(1));
944 transaction.push_back(item("$ev2"), Some(2));
945 transaction.commit();
946
947 let mut entries = items.entries();
948
949 assert_matches!(entries.next(), Some(entry) => {
950 assert_event_id!(entry, "$ev0");
951 });
952 assert_matches!(entries.next(), Some(entry) => {
953 assert_event_id!(entry, "$ev1");
954 });
955 assert_matches!(entries.next(), Some(entry) => {
956 assert_event_id!(entry, "$ev2");
957 });
958 assert_matches!(entries.next(), None);
959 }
960
961 #[test]
962 fn test_entry_replace() {
963 let mut items = ObservableItems::new();
964
965 let mut transaction = items.transaction();
967 transaction.push_back(item("$ev0"), Some(0));
968 transaction.commit();
969
970 let mut entries = items.entries();
971
972 assert_matches!(entries.next(), Some(mut entry) => {
974 assert_event_id!(entry, "$ev0");
975 ObservableItemsEntry::replace(&mut entry, item("$ev1"));
976 });
977 assert_matches!(entries.next(), None);
978
979 let mut entries = items.entries();
981
982 assert_matches!(entries.next(), Some(entry) => {
983 assert_event_id!(entry, "$ev1");
984 });
985 assert_matches!(entries.next(), None);
986 }
987
988 #[test]
989 fn test_for_each() {
990 let mut items = ObservableItems::new();
991
992 let mut transaction = items.transaction();
994 transaction.push_back(item("$ev0"), Some(0));
995 transaction.push_back(item("$ev1"), Some(1));
996 transaction.push_back(item("$ev2"), Some(2));
997 transaction.commit();
998
999 let mut nth = 0;
1000
1001 items.for_each(|entry| {
1003 match nth {
1004 0 => {
1005 assert_event_id!(entry, "$ev0");
1006 }
1007 1 => {
1008 assert_event_id!(entry, "$ev1");
1009 }
1010 2 => {
1011 assert_event_id!(entry, "$ev2");
1012 }
1013 _ => unreachable!(),
1014 }
1015
1016 nth += 1;
1017 });
1018 }
1019
1020 #[test]
1021 fn test_transaction_commit() {
1022 let mut items = ObservableItems::new();
1023
1024 let mut transaction = items.transaction();
1026 transaction.push_back(item("$ev0"), Some(0));
1027 drop(transaction);
1028
1029 assert!(items.is_empty());
1030
1031 let mut transaction = items.transaction();
1033 transaction.push_back(item("$ev0"), Some(0));
1034 transaction.commit();
1035
1036 assert!(items.is_empty().not());
1037 }
1038
1039 #[test]
1040 fn test_transaction_get() {
1041 let mut items = ObservableItems::new();
1042
1043 let mut transaction = items.transaction();
1044 transaction.push_back(item("$ev0"), Some(0));
1045
1046 assert_matches!(transaction.get(0), Some(event) => {
1047 assert_event_id!(event, "$ev0");
1048 });
1049 }
1050
1051 #[test]
1052 fn test_transaction_replace() {
1053 let mut items = ObservableItems::new();
1054
1055 let mut transaction = items.transaction();
1056 transaction.push_back(item("$ev0"), Some(0));
1057 transaction.replace(0, item("$ev1"));
1058
1059 assert_matches!(transaction.get(0), Some(event) => {
1060 assert_event_id!(event, "$ev1");
1061 });
1062 }
1063
1064 #[test]
1065 fn test_transaction_insert() {
1066 let mut items = ObservableItems::new();
1067
1068 let mut transaction = items.transaction();
1069
1070 transaction.push_back_remote_event(event_meta("$ev0"));
1072 transaction.insert(0, item("$ev0"), Some(0));
1073
1074 assert_mapping! {
1075 on transaction:
1076
1077 | event_id | event_index | timeline_item_index |
1078 |----------|-------------|---------------------|
1079 | "$ev0" | 0 | 0 | }
1081
1082 transaction.insert(0, read_marker(), None);
1084
1085 assert_mapping! {
1086 on transaction:
1087
1088 | event_id | event_index | timeline_item_index |
1089 |----------|-------------|---------------------|
1090 | "$ev0" | 0 | 1 | }
1092
1093 transaction.push_back_remote_event(event_meta("$ev1"));
1095 transaction.insert(2, item("$ev1"), Some(1));
1096
1097 assert_mapping! {
1098 on transaction:
1099
1100 | event_id | event_index | timeline_item_index |
1101 |----------|-------------|---------------------|
1102 | "$ev0" | 0 | 1 |
1103 | "$ev1" | 1 | 2 | }
1105
1106 transaction.push_back_remote_event(event_meta("$ev2"));
1108
1109 assert_mapping! {
1110 on transaction:
1111
1112 | event_id | event_index | timeline_item_index |
1113 |----------|-------------|---------------------|
1114 | "$ev0" | 0 | 1 |
1115 | "$ev1" | 1 | 2 |
1116 | "$ev2" | 2 | | }
1118
1119 transaction.push_back_remote_event(event_meta("$ev3"));
1121 transaction.insert(3, item("$ev3"), Some(3));
1122
1123 assert_mapping! {
1124 on transaction:
1125
1126 | event_id | event_index | timeline_item_index |
1127 |----------|-------------|---------------------|
1128 | "$ev0" | 0 | 1 |
1129 | "$ev1" | 1 | 2 |
1130 | "$ev2" | 2 | |
1131 | "$ev3" | 3 | 3 | }
1133
1134 transaction.insert(3, item("$ev2"), Some(2));
1137
1138 assert_mapping! {
1139 on transaction:
1140
1141 | event_id | event_index | timeline_item_index |
1142 |----------|-------------|---------------------|
1143 | "$ev0" | 0 | 1 |
1144 | "$ev1" | 1 | 2 |
1145 | "$ev2" | 2 | 3 | | "$ev3" | 3 | 4 | }
1148
1149 transaction.remove(0);
1151 transaction.insert(2, read_marker(), None);
1152
1153 assert_mapping! {
1154 on transaction:
1155
1156 | event_id | event_index | timeline_item_index |
1157 |----------|-------------|---------------------|
1158 | "$ev0" | 0 | 0 | | "$ev1" | 1 | 1 | | "$ev2" | 2 | 3 |
1161 | "$ev3" | 3 | 4 |
1162 }
1163
1164 assert_eq!(transaction.len(), 5);
1165 }
1166
1167 #[test]
1168 fn test_transaction_push_front() {
1169 let mut items = ObservableItems::new();
1170
1171 let mut transaction = items.transaction();
1172
1173 transaction.push_front_remote_event(event_meta("$ev0"));
1175 transaction.push_front(item("$ev0"), Some(0));
1176
1177 assert_mapping! {
1178 on transaction:
1179
1180 | event_id | event_index | timeline_item_index |
1181 |----------|-------------|---------------------|
1182 | "$ev0" | 0 | 0 | }
1184
1185 transaction.push_front(read_marker(), None);
1187
1188 assert_mapping! {
1189 on transaction:
1190
1191 | event_id | event_index | timeline_item_index |
1192 |----------|-------------|---------------------|
1193 | "$ev0" | 0 | 1 | }
1195
1196 transaction.push_front_remote_event(event_meta("$ev1"));
1198 transaction.push_front(item("$ev1"), Some(0));
1199
1200 assert_mapping! {
1201 on transaction:
1202
1203 | event_id | event_index | timeline_item_index |
1204 |----------|-------------|---------------------|
1205 | "$ev1" | 0 | 0 | | "$ev0" | 1 | 2 | }
1208
1209 transaction.push_front_remote_event(event_meta("$ev2"));
1211
1212 assert_mapping! {
1213 on transaction:
1214
1215 | event_id | event_index | timeline_item_index |
1216 |----------|-------------|---------------------|
1217 | "$ev2" | 0 | |
1218 | "$ev1" | 1 | 0 | | "$ev0" | 2 | 2 | }
1221
1222 transaction.push_front_remote_event(event_meta("$ev3"));
1224 transaction.push_front(item("$ev3"), Some(0));
1225
1226 assert_mapping! {
1227 on transaction:
1228
1229 | event_id | event_index | timeline_item_index |
1230 |----------|-------------|---------------------|
1231 | "$ev3" | 0 | 0 | | "$ev2" | 1 | |
1233 | "$ev1" | 2 | 1 | | "$ev0" | 3 | 3 | }
1236
1237 assert_eq!(transaction.len(), 4);
1238 }
1239
1240 #[test]
1241 fn test_transaction_push_back() {
1242 let mut items = ObservableItems::new();
1243
1244 let mut transaction = items.transaction();
1245
1246 transaction.push_back_remote_event(event_meta("$ev0"));
1248 transaction.push_back(item("$ev0"), Some(0));
1249
1250 assert_mapping! {
1251 on transaction:
1252
1253 | event_id | event_index | timeline_item_index |
1254 |----------|-------------|---------------------|
1255 | "$ev0" | 0 | 0 | }
1257
1258 transaction.push_back(read_marker(), None);
1260
1261 assert_mapping! {
1262 on transaction:
1263
1264 | event_id | event_index | timeline_item_index |
1265 |----------|-------------|---------------------|
1266 | "$ev0" | 0 | 0 |
1267 }
1268
1269 transaction.push_back_remote_event(event_meta("$ev1"));
1271 transaction.push_back(item("$ev1"), Some(1));
1272
1273 assert_mapping! {
1274 on transaction:
1275
1276 | event_id | event_index | timeline_item_index |
1277 |----------|-------------|---------------------|
1278 | "$ev0" | 0 | 0 |
1279 | "$ev1" | 1 | 2 | }
1281
1282 transaction.push_back_remote_event(event_meta("$ev2"));
1284
1285 assert_mapping! {
1286 on transaction:
1287
1288 | event_id | event_index | timeline_item_index |
1289 |----------|-------------|---------------------|
1290 | "$ev0" | 0 | 0 |
1291 | "$ev1" | 1 | 2 |
1292 | "$ev2" | 2 | | }
1294
1295 transaction.push_back_remote_event(event_meta("$ev3"));
1297 transaction.push_back(item("$ev3"), Some(3));
1298
1299 assert_mapping! {
1300 on transaction:
1301
1302 | event_id | event_index | timeline_item_index |
1303 |----------|-------------|---------------------|
1304 | "$ev0" | 0 | 0 |
1305 | "$ev1" | 1 | 2 |
1306 | "$ev2" | 2 | |
1307 | "$ev3" | 3 | 3 | }
1309
1310 assert_eq!(transaction.len(), 4);
1311 }
1312
1313 #[test]
1314 fn test_transaction_remove() {
1315 let mut items = ObservableItems::new();
1316
1317 let mut transaction = items.transaction();
1318
1319 transaction.push_back_remote_event(event_meta("$ev0"));
1321 transaction.push_back(item("$ev0"), Some(0));
1322
1323 transaction.push_back(read_marker(), None);
1325
1326 transaction.push_back_remote_event(event_meta("$ev1"));
1328 transaction.push_back(item("$ev1"), Some(1));
1329
1330 transaction.push_back_remote_event(event_meta("$ev2"));
1332
1333 transaction.push_back_remote_event(event_meta("$ev3"));
1335 transaction.push_back(item("$ev3"), Some(3));
1336
1337 assert_mapping! {
1338 on transaction:
1339
1340 | event_id | event_index | timeline_item_index |
1341 |----------|-------------|---------------------|
1342 | "$ev0" | 0 | 0 |
1343 | "$ev1" | 1 | 2 |
1344 | "$ev2" | 2 | |
1345 | "$ev3" | 3 | 3 |
1346 }
1347
1348 transaction.remove(1);
1350
1351 assert_mapping! {
1352 on transaction:
1353
1354 | event_id | event_index | timeline_item_index |
1355 |----------|-------------|---------------------|
1356 | "$ev0" | 0 | 0 |
1357 | "$ev1" | 1 | 1 | | "$ev2" | 2 | |
1359 | "$ev3" | 3 | 2 | }
1361
1362 transaction.remove(1);
1364
1365 assert_mapping! {
1366 on transaction:
1367
1368 | event_id | event_index | timeline_item_index |
1369 |----------|-------------|---------------------|
1370 | "$ev0" | 0 | 0 |
1371 | "$ev1" | 1 | | | "$ev2" | 2 | |
1373 | "$ev3" | 3 | 1 | }
1375
1376 transaction.remove(1);
1378
1379 assert_mapping! {
1380 on transaction:
1381
1382 | event_id | event_index | timeline_item_index |
1383 |----------|-------------|---------------------|
1384 | "$ev0" | 0 | 0 |
1385 | "$ev1" | 1 | |
1386 | "$ev2" | 2 | |
1387 | "$ev3" | 3 | | }
1389
1390 transaction.remove(0);
1392
1393 assert_mapping! {
1394 on transaction:
1395
1396 | event_id | event_index | timeline_item_index |
1397 |----------|-------------|---------------------|
1398 | "$ev0" | 0 | | | "$ev1" | 1 | |
1400 | "$ev2" | 2 | |
1401 | "$ev3" | 3 | |
1402 }
1403
1404 assert!(transaction.is_empty());
1405 }
1406
1407 #[test]
1408 fn test_transaction_clear() {
1409 let mut items = ObservableItems::new();
1410
1411 let mut transaction = items.transaction();
1412
1413 transaction.push_back_remote_event(event_meta("$ev0"));
1415 transaction.push_back(item("$ev0"), Some(0));
1416
1417 transaction.push_back(read_marker(), None);
1419
1420 transaction.push_back_remote_event(event_meta("$ev1"));
1422 transaction.push_back(item("$ev1"), Some(1));
1423
1424 transaction.push_back_remote_event(event_meta("$ev2"));
1426
1427 transaction.push_back_remote_event(event_meta("$ev3"));
1429 transaction.push_back(item("$ev3"), Some(3));
1430
1431 assert_mapping! {
1432 on transaction:
1433
1434 | event_id | event_index | timeline_item_index |
1435 |----------|-------------|---------------------|
1436 | "$ev0" | 0 | 0 |
1437 | "$ev1" | 1 | 2 |
1438 | "$ev2" | 2 | |
1439 | "$ev3" | 3 | 3 |
1440 }
1441
1442 assert_eq!(transaction.all_remote_events().0.len(), 4);
1443 assert_eq!(transaction.len(), 4);
1444
1445 transaction.clear();
1447
1448 assert!(transaction.all_remote_events().0.is_empty());
1449 assert!(transaction.is_empty());
1450 }
1451
1452 #[test]
1453 fn test_transaction_for_each() {
1454 let mut items = ObservableItems::new();
1455
1456 let mut transaction = items.transaction();
1458 transaction.push_back(item("$ev0"), Some(0));
1459 transaction.push_back(item("$ev1"), Some(1));
1460 transaction.push_back(item("$ev2"), Some(2));
1461
1462 let mut nth = 0;
1463
1464 transaction.for_each(|entry| {
1466 match nth {
1467 0 => {
1468 assert_event_id!(entry, "$ev0");
1469 }
1470 1 => {
1471 assert_event_id!(entry, "$ev1");
1472 }
1473 2 => {
1474 assert_event_id!(entry, "$ev2");
1475 }
1476 _ => unreachable!(),
1477 }
1478
1479 nth += 1;
1480 });
1481 }
1482
1483 #[test]
1484 fn test_transaction_for_each_remove() {
1485 let mut items = ObservableItems::new();
1486
1487 let mut transaction = items.transaction();
1489
1490 transaction.push_back_remote_event(event_meta("$ev0"));
1491 transaction.push_back(item("$ev0"), Some(0));
1492
1493 transaction.push_back_remote_event(event_meta("$ev1"));
1494 transaction.push_back(item("$ev1"), Some(1));
1495
1496 transaction.push_back_remote_event(event_meta("$ev2"));
1497 transaction.push_back(item("$ev2"), Some(2));
1498
1499 assert_mapping! {
1500 on transaction:
1501
1502 | event_id | event_index | timeline_item_index |
1503 |----------|-------------|---------------------|
1504 | "$ev0" | 0 | 0 |
1505 | "$ev1" | 1 | 1 |
1506 | "$ev2" | 2 | 2 |
1507 }
1508
1509 transaction.for_each(|entry| {
1511 if entry.as_event().unwrap().event_id().unwrap().as_str() == "$ev1" {
1512 ObservableItemsTransactionEntry::remove(entry);
1513 }
1514 });
1515
1516 assert_mapping! {
1517 on transaction:
1518
1519 | event_id | event_index | timeline_item_index |
1520 |----------|-------------|---------------------|
1521 | "$ev0" | 0 | 0 |
1522 | "$ev2" | 2 | 1 | }
1524
1525 assert_eq!(transaction.all_remote_events().0.len(), 3);
1526 assert_eq!(transaction.len(), 2);
1527 }
1528
1529 #[test]
1530 fn test_transaction_push_local() {
1531 let mut items = ObservableItems::new();
1532
1533 let mut transaction = items.transaction();
1534
1535 transaction.push_back(item("$ev0"), None);
1537
1538 transaction.push_local(local_item("t0"));
1540
1541 transaction.push_local(local_item("t1"));
1543
1544 transaction.commit();
1545
1546 let mut entries = items.entries();
1547
1548 assert_matches!(entries.next(), Some(entry) => {
1549 assert_event_id!(entry, "$ev0");
1550 });
1551 assert_matches!(entries.next(), Some(entry) => {
1552 assert_transaction_id!(entry, "t0");
1553 });
1554 assert_matches!(entries.next(), Some(entry) => {
1555 assert_transaction_id!(entry, "t1");
1556 });
1557 assert_matches!(entries.next(), None);
1558 }
1559
1560 #[test]
1561 #[should_panic]
1562 fn test_transaction_push_local_panic_not_a_local() {
1563 let mut items = ObservableItems::new();
1564 let mut transaction = items.transaction();
1565 transaction.push_local(item("$ev0"));
1566 }
1567
1568 #[test]
1569 fn test_transaction_push_date_divider() {
1570 let mut items = ObservableItems::new();
1571 let mut stream = items.subscribe().into_stream();
1572
1573 let mut transaction = items.transaction();
1574
1575 transaction.push_date_divider(
1576 0,
1577 TimelineItem::new(
1578 TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(
1579 MilliSecondsSinceUnixEpoch(uint!(10)),
1580 )),
1581 TimelineUniqueId("__foo".to_owned()),
1582 ),
1583 );
1584 transaction.push_date_divider(
1585 0,
1586 TimelineItem::new(
1587 TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(
1588 MilliSecondsSinceUnixEpoch(uint!(20)),
1589 )),
1590 TimelineUniqueId("__bar".to_owned()),
1591 ),
1592 );
1593 transaction.push_date_divider(
1594 1,
1595 TimelineItem::new(
1596 TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(
1597 MilliSecondsSinceUnixEpoch(uint!(30)),
1598 )),
1599 TimelineUniqueId("__baz".to_owned()),
1600 ),
1601 );
1602 transaction.commit();
1603
1604 assert_next_matches!(stream, VectorDiff::PushBack { value: timeline_item } => {
1605 assert_matches!(timeline_item.as_virtual(), Some(VirtualTimelineItem::DateDivider(ms)) => {
1606 assert_eq!(u64::from(ms.0), 10);
1607 });
1608 });
1609 assert_next_matches!(stream, VectorDiff::PushFront { value: timeline_item } => {
1610 assert_matches!(timeline_item.as_virtual(), Some(VirtualTimelineItem::DateDivider(ms)) => {
1611 assert_eq!(u64::from(ms.0), 20);
1612 });
1613 });
1614 assert_next_matches!(stream, VectorDiff::Insert { index: 1, value: timeline_item } => {
1615 assert_matches!(timeline_item.as_virtual(), Some(VirtualTimelineItem::DateDivider(ms)) => {
1616 assert_eq!(u64::from(ms.0), 30);
1617 });
1618 });
1619 assert_pending!(stream);
1620 }
1621
1622 #[test]
1623 #[should_panic]
1624 fn test_transaction_push_date_divider_panic_not_a_date_divider() {
1625 let mut items = ObservableItems::new();
1626 let mut transaction = items.transaction();
1627
1628 transaction.push_date_divider(0, item("$ev0"));
1629 }
1630
1631 #[test]
1632 #[should_panic]
1633 fn test_transaction_push_date_divider_panic_not_in_remotes_region() {
1634 let mut items = ObservableItems::new();
1635 let mut transaction = items.transaction();
1636
1637 transaction.push_timeline_start_if_missing(TimelineItem::new(
1638 VirtualTimelineItem::TimelineStart,
1639 TimelineUniqueId("__id_start".to_owned()),
1640 ));
1641 transaction.push_date_divider(
1642 0,
1643 TimelineItem::new(
1644 VirtualTimelineItem::DateDivider(MilliSecondsSinceUnixEpoch(uint!(10))),
1645 TimelineUniqueId("__date_divider".to_owned()),
1646 ),
1647 );
1648 }
1649
1650 #[test]
1651 fn test_transaction_push_timeline_start_if_missing() {
1652 let mut items = ObservableItems::new();
1653
1654 let mut transaction = items.transaction();
1655
1656 transaction.push_back(item("$ev0"), None);
1658
1659 transaction.push_timeline_start_if_missing(TimelineItem::new(
1661 VirtualTimelineItem::TimelineStart,
1662 TimelineUniqueId("__id_start".to_owned()),
1663 ));
1664
1665 transaction.push_back(item("$ev1"), None);
1667
1668 transaction.push_timeline_start_if_missing(TimelineItem::new(
1670 VirtualTimelineItem::TimelineStart,
1671 TimelineUniqueId("__id_start_again".to_owned()),
1672 ));
1673
1674 transaction.commit();
1675
1676 let mut entries = items.entries();
1677
1678 assert_matches!(entries.next(), Some(entry) => {
1679 assert!(entry.is_timeline_start());
1680 });
1681 assert_matches!(entries.next(), Some(entry) => {
1682 assert_event_id!(entry, "$ev0");
1683 });
1684 assert_matches!(entries.next(), Some(entry) => {
1685 assert_event_id!(entry, "$ev1");
1686 });
1687 assert_matches!(entries.next(), None);
1688 }
1689
1690 #[test]
1691 fn test_transaction_iter_all_regions() {
1692 let mut items = ObservableItems::new();
1693
1694 let mut transaction = items.transaction();
1695 transaction.push_timeline_start_if_missing(TimelineItem::new(
1696 VirtualTimelineItem::TimelineStart,
1697 TimelineUniqueId("__start".to_owned()),
1698 ));
1699 transaction.push_back(item("$ev0"), None);
1700 transaction.push_back(item("$ev1"), None);
1701 transaction.push_back(item("$ev2"), None);
1702 transaction.push_local(local_item("t0"));
1703 transaction.push_local(local_item("t1"));
1704 transaction.push_local(local_item("t2"));
1705
1706 let mut iter = transaction.iter_all_regions();
1708 assert_matches!(iter.next(), Some((0, item)) => {
1709 assert!(item.is_timeline_start());
1710 });
1711 assert_matches!(iter.next(), Some((1, item)) => {
1712 assert_event_id!(item, "$ev0");
1713 });
1714 assert_matches!(iter.next(), Some((2, item)) => {
1715 assert_event_id!(item, "$ev1");
1716 });
1717 assert_matches!(iter.next(), Some((3, item)) => {
1718 assert_event_id!(item, "$ev2");
1719 });
1720 assert_matches!(iter.next(), Some((4, item)) => {
1721 assert_transaction_id!(item, "t0");
1722 });
1723 assert_matches!(iter.next(), Some((5, item)) => {
1724 assert_transaction_id!(item, "t1");
1725 });
1726 assert_matches!(iter.next(), Some((6, item)) => {
1727 assert_transaction_id!(item, "t2");
1728 });
1729 assert!(iter.next().is_none());
1730 }
1731
1732 #[test]
1733 fn test_transaction_iter_remotes_regions() {
1734 let mut items = ObservableItems::new();
1735
1736 let mut transaction = items.transaction();
1737 transaction.push_timeline_start_if_missing(TimelineItem::new(
1738 VirtualTimelineItem::TimelineStart,
1739 TimelineUniqueId("__start".to_owned()),
1740 ));
1741 transaction.push_back(item("$ev0"), None);
1742 transaction.push_back(item("$ev1"), None);
1743 transaction.push_back(item("$ev2"), None);
1744 transaction.push_local(local_item("t0"));
1745 transaction.push_local(local_item("t1"));
1746 transaction.push_local(local_item("t2"));
1747
1748 let mut iter = transaction.iter_remotes_region();
1750 assert_matches!(iter.next(), Some((1, item)) => {
1751 assert_event_id!(item, "$ev0");
1752 });
1753 assert_matches!(iter.next(), Some((2, item)) => {
1754 assert_event_id!(item, "$ev1");
1755 });
1756 assert_matches!(iter.next(), Some((3, item)) => {
1757 assert_event_id!(item, "$ev2");
1758 });
1759 assert!(iter.next().is_none());
1760 }
1761
1762 #[test]
1763 fn test_transaction_iter_remotes_regions_with_no_start_region() {
1764 let mut items = ObservableItems::new();
1765
1766 let mut transaction = items.transaction();
1767 transaction.push_back(item("$ev0"), None);
1768 transaction.push_back(item("$ev1"), None);
1769 transaction.push_back(item("$ev2"), None);
1770 transaction.push_local(local_item("t0"));
1771 transaction.push_local(local_item("t1"));
1772 transaction.push_local(local_item("t2"));
1773
1774 let mut iter = transaction.iter_remotes_region();
1776 assert_matches!(iter.next(), Some((0, item)) => {
1777 assert_event_id!(item, "$ev0");
1778 });
1779 assert_matches!(iter.next(), Some((1, item)) => {
1780 assert_event_id!(item, "$ev1");
1781 });
1782 assert_matches!(iter.next(), Some((2, item)) => {
1783 assert_event_id!(item, "$ev2");
1784 });
1785 assert!(iter.next().is_none());
1786 }
1787
1788 #[test]
1789 fn test_transaction_iter_remotes_regions_with_no_locals_region() {
1790 let mut items = ObservableItems::new();
1791
1792 let mut transaction = items.transaction();
1793 transaction.push_back(item("$ev0"), None);
1794 transaction.push_back(item("$ev1"), None);
1795 transaction.push_back(item("$ev2"), None);
1796
1797 let mut iter = transaction.iter_remotes_region();
1799 assert_matches!(iter.next(), Some((0, item)) => {
1800 assert_event_id!(item, "$ev0");
1801 });
1802 assert_matches!(iter.next(), Some((1, item)) => {
1803 assert_event_id!(item, "$ev1");
1804 });
1805 assert_matches!(iter.next(), Some((2, item)) => {
1806 assert_event_id!(item, "$ev2");
1807 });
1808 assert!(iter.next().is_none());
1809 }
1810
1811 #[test]
1812 fn test_transaction_iter_locals_region() {
1813 let mut items = ObservableItems::new();
1814
1815 let mut transaction = items.transaction();
1816 transaction.push_timeline_start_if_missing(TimelineItem::new(
1817 VirtualTimelineItem::TimelineStart,
1818 TimelineUniqueId("__start".to_owned()),
1819 ));
1820 transaction.push_back(item("$ev0"), None);
1821 transaction.push_back(item("$ev1"), None);
1822 transaction.push_back(item("$ev2"), None);
1823 transaction.push_local(local_item("t0"));
1824 transaction.push_local(local_item("t1"));
1825 transaction.push_local(local_item("t2"));
1826
1827 let mut iter = transaction.iter_locals_region();
1829 assert_matches!(iter.next(), Some((4, item)) => {
1830 assert_transaction_id!(item, "t0");
1831 });
1832 assert_matches!(iter.next(), Some((5, item)) => {
1833 assert_transaction_id!(item, "t1");
1834 });
1835 assert_matches!(iter.next(), Some((6, item)) => {
1836 assert_transaction_id!(item, "t2");
1837 });
1838 assert!(iter.next().is_none());
1839 }
1840}
1841
1842#[derive(Clone, Debug, Default)]
1848pub struct AllRemoteEvents(VecDeque<EventMeta>);
1849
1850impl AllRemoteEvents {
1851 pub fn get(&self, event_index: usize) -> Option<&EventMeta> {
1853 self.0.get(event_index)
1854 }
1855
1856 pub fn iter(&self) -> Iter<'_, EventMeta> {
1858 self.0.iter()
1859 }
1860
1861 pub fn range<R>(&self, range: R) -> Iter<'_, EventMeta>
1864 where
1865 R: RangeBounds<usize>,
1866 {
1867 self.0.range(range)
1868 }
1869
1870 fn clear(&mut self) {
1872 self.0.clear();
1873 }
1874
1875 fn push_front(&mut self, event_meta: EventMeta) {
1877 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1880 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1881 }
1882
1883 self.0.push_front(event_meta)
1885 }
1886
1887 fn push_back(&mut self, event_meta: EventMeta) {
1889 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1892 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1893 }
1894
1895 self.0.push_back(event_meta)
1897 }
1898
1899 fn insert(&mut self, event_index: usize, event_meta: EventMeta) {
1901 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1904 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1905 }
1906
1907 self.0.insert(event_index, event_meta)
1909 }
1910
1911 fn remove(&mut self, event_index: usize) -> Option<EventMeta> {
1913 let event_meta = self.0.remove(event_index)?;
1915
1916 if let Some(removed_timeline_item_index) = event_meta.timeline_item_index {
1919 self.decrement_all_timeline_item_index_after(removed_timeline_item_index);
1920 }
1921
1922 Some(event_meta)
1923 }
1924
1925 pub fn last(&self) -> Option<&EventMeta> {
1927 self.0.back()
1928 }
1929
1930 pub fn last_index(&self) -> Option<usize> {
1932 self.0.len().checked_sub(1)
1933 }
1934
1935 pub fn get_by_event_id_mut(&mut self, event_id: &EventId) -> Option<&mut EventMeta> {
1937 self.0.iter_mut().rev().find(|event_meta| event_meta.event_id == event_id)
1938 }
1939
1940 pub fn get_by_event_id(&self, event_id: &EventId) -> Option<&EventMeta> {
1942 self.0.iter().rev().find(|event_meta| event_meta.event_id == event_id)
1943 }
1944
1945 pub fn position_by_event_id(&self, event_id: &EventId) -> Option<usize> {
1947 self.0
1950 .iter()
1951 .enumerate()
1952 .rev()
1953 .find_map(|(i, event_meta)| (event_meta.event_id == event_id).then_some(i))
1954 }
1955
1956 fn increment_all_timeline_item_index_after(&mut self, new_timeline_item_index: usize) {
1959 for event_meta in self.0.iter_mut().rev() {
1967 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
1968 if *timeline_item_index >= new_timeline_item_index {
1969 *timeline_item_index += 1;
1970 } else {
1971 break;
1973 }
1974 }
1975 }
1976 }
1977
1978 fn decrement_all_timeline_item_index_after(&mut self, removed_timeline_item_index: usize) {
1981 for event_meta in self.0.iter_mut().rev() {
1989 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
1990 if *timeline_item_index > removed_timeline_item_index {
1991 *timeline_item_index -= 1;
1992 } else {
1993 break;
1995 }
1996 }
1997 }
1998 }
1999
2000 fn timeline_item_has_been_inserted_at(
2005 &mut self,
2006 new_timeline_item_index: usize,
2007 event_index: Option<usize>,
2008 ) {
2009 self.increment_all_timeline_item_index_after(new_timeline_item_index);
2010
2011 if let Some(event_index) = event_index
2012 && let Some(event_meta) = self.0.get_mut(event_index)
2013 {
2014 event_meta.timeline_item_index = Some(new_timeline_item_index);
2015 }
2016 }
2017
2018 fn timeline_item_has_been_removed_at(&mut self, timeline_item_index_to_remove: usize) {
2021 for event_meta in self.0.iter_mut() {
2022 let mut remove_timeline_item_index = false;
2023
2024 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
2027 match (*timeline_item_index).cmp(&timeline_item_index_to_remove) {
2028 Ordering::Equal => {
2029 remove_timeline_item_index = true;
2030 }
2031
2032 Ordering::Greater => {
2033 *timeline_item_index -= 1;
2034 }
2035
2036 Ordering::Less => {}
2037 }
2038 }
2039
2040 if remove_timeline_item_index {
2043 event_meta.timeline_item_index = None;
2044 }
2045 }
2046 }
2047}
2048
2049#[cfg(test)]
2050mod all_remote_events_tests {
2051 use assert_matches::assert_matches;
2052 use ruma::event_id;
2053
2054 use super::{AllRemoteEvents, EventMeta};
2055
2056 fn event_meta(event_id: &str, timeline_item_index: Option<usize>) -> EventMeta {
2057 EventMeta { event_id: event_id.parse().unwrap(), timeline_item_index, visible: false }
2058 }
2059
2060 macro_rules! assert_events {
2061 ( $events:ident, [ $( ( $event_id:literal, $timeline_item_index:expr ) ),* $(,)? ] ) => {
2062 let mut iter = $events .iter();
2063
2064 $(
2065 assert_matches!(iter.next(), Some(EventMeta { event_id, timeline_item_index, .. }) => {
2066 assert_eq!(event_id.as_str(), $event_id );
2067 assert_eq!(*timeline_item_index, $timeline_item_index );
2068 });
2069 )*
2070
2071 assert!(iter.next().is_none(), "Not all events have been asserted");
2072 }
2073 }
2074
2075 #[test]
2076 fn test_range() {
2077 let mut events = AllRemoteEvents::default();
2078
2079 events.push_back(event_meta("$ev0", None));
2081 events.push_back(event_meta("$ev1", None));
2082 events.push_back(event_meta("$ev2", None));
2083
2084 assert_eq!(events.iter().count(), 3);
2085
2086 assert_eq!(events.range(..).count(), 3);
2088 assert_eq!(events.range(1..).count(), 2);
2089 assert_eq!(events.range(0..=1).count(), 2);
2090
2091 let mut some_events = events.range(1..);
2093
2094 assert_matches!(some_events.next(), Some(EventMeta { event_id, .. }) => {
2095 assert_eq!(event_id.as_str(), "$ev1");
2096 });
2097 assert_matches!(some_events.next(), Some(EventMeta { event_id, .. }) => {
2098 assert_eq!(event_id.as_str(), "$ev2");
2099 });
2100 assert!(some_events.next().is_none());
2101 }
2102
2103 #[test]
2104 fn test_clear() {
2105 let mut events = AllRemoteEvents::default();
2106
2107 events.push_back(event_meta("$ev0", None));
2109 events.push_back(event_meta("$ev1", None));
2110 events.push_back(event_meta("$ev2", None));
2111
2112 assert_eq!(events.iter().count(), 3);
2113
2114 events.clear();
2116
2117 assert_eq!(events.iter().count(), 0);
2118 }
2119
2120 #[test]
2121 fn test_push_front() {
2122 let mut events = AllRemoteEvents::default();
2123
2124 events.push_front(event_meta("$ev0", Some(1)));
2126
2127 events.push_front(event_meta("$ev1", None));
2129
2130 events.push_front(event_meta("$ev2", Some(0)));
2132
2133 events.push_front(event_meta("$ev3", Some(0)));
2135
2136 assert_events!(
2137 events,
2138 [
2139 ("$ev3", Some(0)),
2141 ("$ev2", Some(1)),
2143 ("$ev1", None),
2145 ("$ev0", Some(3)),
2147 ]
2148 );
2149 }
2150
2151 #[test]
2152 fn test_push_back() {
2153 let mut events = AllRemoteEvents::default();
2154
2155 events.push_back(event_meta("$ev0", Some(0)));
2157
2158 events.push_back(event_meta("$ev1", None));
2160
2161 events.push_back(event_meta("$ev2", Some(1)));
2163
2164 events.push_back(event_meta("$ev3", Some(1)));
2168
2169 assert_events!(
2170 events,
2171 [
2172 ("$ev0", Some(0)),
2174 ("$ev1", None),
2176 ("$ev2", Some(2)),
2178 ("$ev3", Some(1)),
2180 ]
2181 );
2182 }
2183
2184 #[test]
2185 fn test_insert() {
2186 let mut events = AllRemoteEvents::default();
2187
2188 events.insert(0, event_meta("$ev0", Some(0)));
2190
2191 events.insert(1, event_meta("$ev1", None));
2193
2194 events.insert(2, event_meta("$ev2", Some(1)));
2196
2197 events.insert(0, event_meta("$ev3", Some(0)));
2199
2200 assert_events!(
2201 events,
2202 [
2203 ("$ev3", Some(0)),
2205 ("$ev0", Some(1)),
2207 ("$ev1", None),
2209 ("$ev2", Some(2)),
2211 ]
2212 );
2213 }
2214
2215 #[test]
2216 fn test_remove() {
2217 let mut events = AllRemoteEvents::default();
2218
2219 events.push_back(event_meta("$ev0", Some(0)));
2221 events.push_back(event_meta("$ev1", Some(1)));
2222 events.push_back(event_meta("$ev2", None));
2223 events.push_back(event_meta("$ev3", Some(2)));
2224
2225 assert_events!(
2227 events,
2228 [("$ev0", Some(0)), ("$ev1", Some(1)), ("$ev2", None), ("$ev3", Some(2))]
2229 );
2230
2231 events.remove(2); events.remove(1); assert_events!(
2236 events,
2237 [
2238 ("$ev0", Some(0)),
2239 ("$ev3", Some(1)),
2241 ]
2242 );
2243 }
2244
2245 #[test]
2246 fn test_last() {
2247 let mut events = AllRemoteEvents::default();
2248
2249 assert!(events.last().is_none());
2250 assert!(events.last_index().is_none());
2251
2252 events.push_back(event_meta("$ev0", Some(0)));
2254 events.push_back(event_meta("$ev1", Some(1)));
2255
2256 assert_matches!(events.last(), Some(EventMeta { event_id, .. }) => {
2257 assert_eq!(event_id.as_str(), "$ev1");
2258 });
2259 assert_eq!(events.last_index(), Some(1));
2260 }
2261
2262 #[test]
2263 fn test_get_by_event_by_mut() {
2264 let mut events = AllRemoteEvents::default();
2265
2266 events.push_back(event_meta("$ev0", Some(0)));
2268 events.push_back(event_meta("$ev1", Some(1)));
2269
2270 assert!(events.get_by_event_id_mut(event_id!("$ev0")).is_some());
2271 assert!(events.get_by_event_id_mut(event_id!("$ev42")).is_none());
2272 }
2273
2274 #[test]
2275 fn test_timeline_item_has_been_inserted_at() {
2276 let mut events = AllRemoteEvents::default();
2277
2278 events.push_back(event_meta("$ev0", Some(0)));
2280 events.push_back(event_meta("$ev1", Some(1)));
2281 events.push_back(event_meta("$ev2", None));
2282 events.push_back(event_meta("$ev3", None));
2283 events.push_back(event_meta("$ev4", Some(2)));
2284 events.push_back(event_meta("$ev5", Some(3)));
2285 events.push_back(event_meta("$ev6", None));
2286
2287 events.timeline_item_has_been_inserted_at(2, None);
2289
2290 assert_events!(
2291 events,
2292 [
2293 ("$ev0", Some(0)),
2294 ("$ev1", Some(1)),
2295 ("$ev2", None),
2296 ("$ev3", None),
2297 ("$ev4", Some(3)),
2299 ("$ev5", Some(4)),
2301 ("$ev6", None),
2302 ]
2303 );
2304
2305 events.timeline_item_has_been_inserted_at(5, Some(6));
2307
2308 assert_events!(
2309 events,
2310 [
2311 ("$ev0", Some(0)),
2312 ("$ev1", Some(1)),
2313 ("$ev2", None),
2314 ("$ev3", None),
2315 ("$ev4", Some(3)),
2316 ("$ev5", Some(4)),
2317 ("$ev6", Some(5)),
2319 ]
2320 );
2321 }
2322
2323 #[test]
2324 fn test_timeline_item_has_been_removed_at() {
2325 let mut events = AllRemoteEvents::default();
2326
2327 events.push_back(event_meta("$ev0", Some(0)));
2329 events.push_back(event_meta("$ev1", Some(1)));
2330 events.push_back(event_meta("$ev2", None));
2331 events.push_back(event_meta("$ev3", None));
2332 events.push_back(event_meta("$ev4", Some(3)));
2333 events.push_back(event_meta("$ev5", Some(4)));
2334 events.push_back(event_meta("$ev6", None));
2335
2336 events.timeline_item_has_been_removed_at(2);
2338
2339 assert_events!(
2340 events,
2341 [
2342 ("$ev0", Some(0)),
2343 ("$ev1", Some(1)),
2344 ("$ev2", None),
2345 ("$ev3", None),
2346 ("$ev4", Some(2)),
2348 ("$ev5", Some(3)),
2350 ("$ev6", None),
2351 ]
2352 );
2353
2354 events.timeline_item_has_been_removed_at(2);
2356
2357 assert_events!(
2358 events,
2359 [
2360 ("$ev0", Some(0)),
2361 ("$ev1", Some(1)),
2362 ("$ev2", None),
2363 ("$ev3", None),
2364 ("$ev4", None),
2366 ("$ev5", Some(2)),
2368 ("$ev6", None),
2369 ]
2370 );
2371
2372 events.timeline_item_has_been_removed_at(0);
2374
2375 assert_events!(
2376 events,
2377 [
2378 ("$ev0", None),
2380 ("$ev1", Some(0)),
2382 ("$ev2", None),
2383 ("$ev3", None),
2384 ("$ev4", None),
2385 ("$ev5", Some(1)),
2387 ("$ev6", None),
2388 ]
2389 );
2390 }
2391}