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 {
800 event_id: event_id.parse().unwrap(),
801 thread_root_id: None,
802 timeline_item_index: None,
803 visible: false,
804 can_show_read_receipts: false,
805 }
806 }
807
808 macro_rules! assert_event_id {
809 ( $timeline_item:expr, $event_id:literal $( , $message:expr )? $(,)? ) => {
810 assert_eq!($timeline_item.as_event().unwrap().event_id().unwrap().as_str(), $event_id $( , $message)? );
811 };
812 }
813
814 macro_rules! assert_transaction_id {
815 ( $timeline_item:expr, $transaction_id:literal $( , $message:expr )? $(,)? ) => {
816 assert_eq!($timeline_item.as_event().unwrap().transaction_id().unwrap().as_str(), $transaction_id $( , $message)? );
817 };
818 }
819
820 macro_rules! assert_mapping {
821 ( on $transaction:ident:
822 | event_id | event_index | timeline_item_index |
823 | $( - )+ | $( - )+ | $( - )+ |
824 $(
825 | $event_id:literal | $event_index:literal | $( $timeline_item_index:literal )? |
826 )+
827 ) => {
828 let all_remote_events = $transaction .all_remote_events();
829
830 $(
831 assert_matches!(all_remote_events.0.get( $event_index ), Some(EventMeta { event_id, timeline_item_index, .. }) => {
833 assert_eq!(
835 event_id.as_str(),
836 $event_id ,
837 concat!("event #", $event_index, " should have ID ", $event_id)
838 );
839
840
841 #[allow(unused_variables)]
843 let timeline_item_index_is_expected = false;
844 $(
845 let timeline_item_index_is_expected = true;
846 let _ = $timeline_item_index;
847 )?
848
849 if timeline_item_index_is_expected.not() {
850 assert!(
852 timeline_item_index.is_none(),
853 concat!("event #", $event_index, " with ID ", $event_id, " should NOT map to a timeline item index" )
854 );
855 }
856
857 $(
858 assert_eq!(
860 *timeline_item_index,
861 Some( $timeline_item_index ),
862 concat!("event #", $event_index, " with ID ", $event_id, " should map to timeline item #", $timeline_item_index )
863 );
864
865 assert_matches!( $transaction .get( $timeline_item_index ), Some(timeline_item) => {
867 assert_event_id!(
869 timeline_item,
870 $event_id ,
871 concat!("timeline item #", $timeline_item_index, " should map to event ID ", $event_id )
872 );
873 });
874 )?
875 });
876 )*
877 }
878 }
879
880 #[test]
881 fn test_is_empty() {
882 let mut items = ObservableItems::new();
883
884 assert!(items.is_empty());
885
886 let mut transaction = items.transaction();
888 transaction.push_back(item("$ev0"), Some(0));
889 transaction.commit();
890
891 assert!(items.is_empty().not());
892 }
893
894 #[test]
895 fn test_subscribe() {
896 let mut items = ObservableItems::new();
897 let mut subscriber = items.subscribe().into_stream();
898
899 let mut transaction = items.transaction();
901 transaction.push_back(item("$ev0"), Some(0));
902 transaction.commit();
903
904 assert_next_matches!(subscriber, VectorDiff::PushBack { value: event } => {
906 assert_event_id!(event, "$ev0");
907 });
908 }
909
910 #[test]
911 fn test_clone_items() {
912 let mut items = ObservableItems::new();
913
914 let mut transaction = items.transaction();
915 transaction.push_back(item("$ev0"), Some(0));
916 transaction.push_back(item("$ev1"), Some(1));
917 transaction.commit();
918
919 let items = items.clone_items();
920 assert_eq!(items.len(), 2);
921 assert_event_id!(items[0], "$ev0");
922 assert_event_id!(items[1], "$ev1");
923 }
924
925 #[test]
926 fn test_replace() {
927 let mut items = ObservableItems::new();
928
929 let mut transaction = items.transaction();
931 transaction.push_back(item("$ev0"), Some(0));
932 transaction.commit();
933
934 items.replace(0, item("$ev1"));
936
937 let items = items.clone_items();
938 assert_eq!(items.len(), 1);
939 assert_event_id!(items[0], "$ev1");
940 }
941
942 #[test]
943 fn test_entries() {
944 let mut items = ObservableItems::new();
945
946 let mut transaction = items.transaction();
948 transaction.push_back(item("$ev0"), Some(0));
949 transaction.push_back(item("$ev1"), Some(1));
950 transaction.push_back(item("$ev2"), Some(2));
951 transaction.commit();
952
953 let mut entries = items.entries();
954
955 assert_matches!(entries.next(), Some(entry) => {
956 assert_event_id!(entry, "$ev0");
957 });
958 assert_matches!(entries.next(), Some(entry) => {
959 assert_event_id!(entry, "$ev1");
960 });
961 assert_matches!(entries.next(), Some(entry) => {
962 assert_event_id!(entry, "$ev2");
963 });
964 assert_matches!(entries.next(), None);
965 }
966
967 #[test]
968 fn test_entry_replace() {
969 let mut items = ObservableItems::new();
970
971 let mut transaction = items.transaction();
973 transaction.push_back(item("$ev0"), Some(0));
974 transaction.commit();
975
976 let mut entries = items.entries();
977
978 assert_matches!(entries.next(), Some(mut entry) => {
980 assert_event_id!(entry, "$ev0");
981 ObservableItemsEntry::replace(&mut entry, item("$ev1"));
982 });
983 assert_matches!(entries.next(), None);
984
985 let mut entries = items.entries();
987
988 assert_matches!(entries.next(), Some(entry) => {
989 assert_event_id!(entry, "$ev1");
990 });
991 assert_matches!(entries.next(), None);
992 }
993
994 #[test]
995 fn test_for_each() {
996 let mut items = ObservableItems::new();
997
998 let mut transaction = items.transaction();
1000 transaction.push_back(item("$ev0"), Some(0));
1001 transaction.push_back(item("$ev1"), Some(1));
1002 transaction.push_back(item("$ev2"), Some(2));
1003 transaction.commit();
1004
1005 let mut nth = 0;
1006
1007 items.for_each(|entry| {
1009 match nth {
1010 0 => {
1011 assert_event_id!(entry, "$ev0");
1012 }
1013 1 => {
1014 assert_event_id!(entry, "$ev1");
1015 }
1016 2 => {
1017 assert_event_id!(entry, "$ev2");
1018 }
1019 _ => unreachable!(),
1020 }
1021
1022 nth += 1;
1023 });
1024 }
1025
1026 #[test]
1027 fn test_transaction_commit() {
1028 let mut items = ObservableItems::new();
1029
1030 let mut transaction = items.transaction();
1032 transaction.push_back(item("$ev0"), Some(0));
1033 drop(transaction);
1034
1035 assert!(items.is_empty());
1036
1037 let mut transaction = items.transaction();
1039 transaction.push_back(item("$ev0"), Some(0));
1040 transaction.commit();
1041
1042 assert!(items.is_empty().not());
1043 }
1044
1045 #[test]
1046 fn test_transaction_get() {
1047 let mut items = ObservableItems::new();
1048
1049 let mut transaction = items.transaction();
1050 transaction.push_back(item("$ev0"), Some(0));
1051
1052 assert_matches!(transaction.get(0), Some(event) => {
1053 assert_event_id!(event, "$ev0");
1054 });
1055 }
1056
1057 #[test]
1058 fn test_transaction_replace() {
1059 let mut items = ObservableItems::new();
1060
1061 let mut transaction = items.transaction();
1062 transaction.push_back(item("$ev0"), Some(0));
1063 transaction.replace(0, item("$ev1"));
1064
1065 assert_matches!(transaction.get(0), Some(event) => {
1066 assert_event_id!(event, "$ev1");
1067 });
1068 }
1069
1070 #[test]
1071 fn test_transaction_insert() {
1072 let mut items = ObservableItems::new();
1073
1074 let mut transaction = items.transaction();
1075
1076 transaction.push_back_remote_event(event_meta("$ev0"));
1078 transaction.insert(0, item("$ev0"), Some(0));
1079
1080 assert_mapping! {
1081 on transaction:
1082
1083 | event_id | event_index | timeline_item_index |
1084 |----------|-------------|---------------------|
1085 | "$ev0" | 0 | 0 | }
1087
1088 transaction.insert(0, read_marker(), None);
1090
1091 assert_mapping! {
1092 on transaction:
1093
1094 | event_id | event_index | timeline_item_index |
1095 |----------|-------------|---------------------|
1096 | "$ev0" | 0 | 1 | }
1098
1099 transaction.push_back_remote_event(event_meta("$ev1"));
1101 transaction.insert(2, item("$ev1"), Some(1));
1102
1103 assert_mapping! {
1104 on transaction:
1105
1106 | event_id | event_index | timeline_item_index |
1107 |----------|-------------|---------------------|
1108 | "$ev0" | 0 | 1 |
1109 | "$ev1" | 1 | 2 | }
1111
1112 transaction.push_back_remote_event(event_meta("$ev2"));
1114
1115 assert_mapping! {
1116 on transaction:
1117
1118 | event_id | event_index | timeline_item_index |
1119 |----------|-------------|---------------------|
1120 | "$ev0" | 0 | 1 |
1121 | "$ev1" | 1 | 2 |
1122 | "$ev2" | 2 | | }
1124
1125 transaction.push_back_remote_event(event_meta("$ev3"));
1127 transaction.insert(3, item("$ev3"), Some(3));
1128
1129 assert_mapping! {
1130 on transaction:
1131
1132 | event_id | event_index | timeline_item_index |
1133 |----------|-------------|---------------------|
1134 | "$ev0" | 0 | 1 |
1135 | "$ev1" | 1 | 2 |
1136 | "$ev2" | 2 | |
1137 | "$ev3" | 3 | 3 | }
1139
1140 transaction.insert(3, item("$ev2"), Some(2));
1143
1144 assert_mapping! {
1145 on transaction:
1146
1147 | event_id | event_index | timeline_item_index |
1148 |----------|-------------|---------------------|
1149 | "$ev0" | 0 | 1 |
1150 | "$ev1" | 1 | 2 |
1151 | "$ev2" | 2 | 3 | | "$ev3" | 3 | 4 | }
1154
1155 transaction.remove(0);
1157 transaction.insert(2, read_marker(), None);
1158
1159 assert_mapping! {
1160 on transaction:
1161
1162 | event_id | event_index | timeline_item_index |
1163 |----------|-------------|---------------------|
1164 | "$ev0" | 0 | 0 | | "$ev1" | 1 | 1 | | "$ev2" | 2 | 3 |
1167 | "$ev3" | 3 | 4 |
1168 }
1169
1170 assert_eq!(transaction.len(), 5);
1171 }
1172
1173 #[test]
1174 fn test_transaction_push_front() {
1175 let mut items = ObservableItems::new();
1176
1177 let mut transaction = items.transaction();
1178
1179 transaction.push_front_remote_event(event_meta("$ev0"));
1181 transaction.push_front(item("$ev0"), Some(0));
1182
1183 assert_mapping! {
1184 on transaction:
1185
1186 | event_id | event_index | timeline_item_index |
1187 |----------|-------------|---------------------|
1188 | "$ev0" | 0 | 0 | }
1190
1191 transaction.push_front(read_marker(), None);
1193
1194 assert_mapping! {
1195 on transaction:
1196
1197 | event_id | event_index | timeline_item_index |
1198 |----------|-------------|---------------------|
1199 | "$ev0" | 0 | 1 | }
1201
1202 transaction.push_front_remote_event(event_meta("$ev1"));
1204 transaction.push_front(item("$ev1"), Some(0));
1205
1206 assert_mapping! {
1207 on transaction:
1208
1209 | event_id | event_index | timeline_item_index |
1210 |----------|-------------|---------------------|
1211 | "$ev1" | 0 | 0 | | "$ev0" | 1 | 2 | }
1214
1215 transaction.push_front_remote_event(event_meta("$ev2"));
1217
1218 assert_mapping! {
1219 on transaction:
1220
1221 | event_id | event_index | timeline_item_index |
1222 |----------|-------------|---------------------|
1223 | "$ev2" | 0 | |
1224 | "$ev1" | 1 | 0 | | "$ev0" | 2 | 2 | }
1227
1228 transaction.push_front_remote_event(event_meta("$ev3"));
1230 transaction.push_front(item("$ev3"), Some(0));
1231
1232 assert_mapping! {
1233 on transaction:
1234
1235 | event_id | event_index | timeline_item_index |
1236 |----------|-------------|---------------------|
1237 | "$ev3" | 0 | 0 | | "$ev2" | 1 | |
1239 | "$ev1" | 2 | 1 | | "$ev0" | 3 | 3 | }
1242
1243 assert_eq!(transaction.len(), 4);
1244 }
1245
1246 #[test]
1247 fn test_transaction_push_back() {
1248 let mut items = ObservableItems::new();
1249
1250 let mut transaction = items.transaction();
1251
1252 transaction.push_back_remote_event(event_meta("$ev0"));
1254 transaction.push_back(item("$ev0"), Some(0));
1255
1256 assert_mapping! {
1257 on transaction:
1258
1259 | event_id | event_index | timeline_item_index |
1260 |----------|-------------|---------------------|
1261 | "$ev0" | 0 | 0 | }
1263
1264 transaction.push_back(read_marker(), None);
1266
1267 assert_mapping! {
1268 on transaction:
1269
1270 | event_id | event_index | timeline_item_index |
1271 |----------|-------------|---------------------|
1272 | "$ev0" | 0 | 0 |
1273 }
1274
1275 transaction.push_back_remote_event(event_meta("$ev1"));
1277 transaction.push_back(item("$ev1"), Some(1));
1278
1279 assert_mapping! {
1280 on transaction:
1281
1282 | event_id | event_index | timeline_item_index |
1283 |----------|-------------|---------------------|
1284 | "$ev0" | 0 | 0 |
1285 | "$ev1" | 1 | 2 | }
1287
1288 transaction.push_back_remote_event(event_meta("$ev2"));
1290
1291 assert_mapping! {
1292 on transaction:
1293
1294 | event_id | event_index | timeline_item_index |
1295 |----------|-------------|---------------------|
1296 | "$ev0" | 0 | 0 |
1297 | "$ev1" | 1 | 2 |
1298 | "$ev2" | 2 | | }
1300
1301 transaction.push_back_remote_event(event_meta("$ev3"));
1303 transaction.push_back(item("$ev3"), Some(3));
1304
1305 assert_mapping! {
1306 on transaction:
1307
1308 | event_id | event_index | timeline_item_index |
1309 |----------|-------------|---------------------|
1310 | "$ev0" | 0 | 0 |
1311 | "$ev1" | 1 | 2 |
1312 | "$ev2" | 2 | |
1313 | "$ev3" | 3 | 3 | }
1315
1316 assert_eq!(transaction.len(), 4);
1317 }
1318
1319 #[test]
1320 fn test_transaction_remove() {
1321 let mut items = ObservableItems::new();
1322
1323 let mut transaction = items.transaction();
1324
1325 transaction.push_back_remote_event(event_meta("$ev0"));
1327 transaction.push_back(item("$ev0"), Some(0));
1328
1329 transaction.push_back(read_marker(), None);
1331
1332 transaction.push_back_remote_event(event_meta("$ev1"));
1334 transaction.push_back(item("$ev1"), Some(1));
1335
1336 transaction.push_back_remote_event(event_meta("$ev2"));
1338
1339 transaction.push_back_remote_event(event_meta("$ev3"));
1341 transaction.push_back(item("$ev3"), Some(3));
1342
1343 assert_mapping! {
1344 on transaction:
1345
1346 | event_id | event_index | timeline_item_index |
1347 |----------|-------------|---------------------|
1348 | "$ev0" | 0 | 0 |
1349 | "$ev1" | 1 | 2 |
1350 | "$ev2" | 2 | |
1351 | "$ev3" | 3 | 3 |
1352 }
1353
1354 transaction.remove(1);
1356
1357 assert_mapping! {
1358 on transaction:
1359
1360 | event_id | event_index | timeline_item_index |
1361 |----------|-------------|---------------------|
1362 | "$ev0" | 0 | 0 |
1363 | "$ev1" | 1 | 1 | | "$ev2" | 2 | |
1365 | "$ev3" | 3 | 2 | }
1367
1368 transaction.remove(1);
1370
1371 assert_mapping! {
1372 on transaction:
1373
1374 | event_id | event_index | timeline_item_index |
1375 |----------|-------------|---------------------|
1376 | "$ev0" | 0 | 0 |
1377 | "$ev1" | 1 | | | "$ev2" | 2 | |
1379 | "$ev3" | 3 | 1 | }
1381
1382 transaction.remove(1);
1384
1385 assert_mapping! {
1386 on transaction:
1387
1388 | event_id | event_index | timeline_item_index |
1389 |----------|-------------|---------------------|
1390 | "$ev0" | 0 | 0 |
1391 | "$ev1" | 1 | |
1392 | "$ev2" | 2 | |
1393 | "$ev3" | 3 | | }
1395
1396 transaction.remove(0);
1398
1399 assert_mapping! {
1400 on transaction:
1401
1402 | event_id | event_index | timeline_item_index |
1403 |----------|-------------|---------------------|
1404 | "$ev0" | 0 | | | "$ev1" | 1 | |
1406 | "$ev2" | 2 | |
1407 | "$ev3" | 3 | |
1408 }
1409
1410 assert!(transaction.is_empty());
1411 }
1412
1413 #[test]
1414 fn test_transaction_clear() {
1415 let mut items = ObservableItems::new();
1416
1417 let mut transaction = items.transaction();
1418
1419 transaction.push_back_remote_event(event_meta("$ev0"));
1421 transaction.push_back(item("$ev0"), Some(0));
1422
1423 transaction.push_back(read_marker(), None);
1425
1426 transaction.push_back_remote_event(event_meta("$ev1"));
1428 transaction.push_back(item("$ev1"), Some(1));
1429
1430 transaction.push_back_remote_event(event_meta("$ev2"));
1432
1433 transaction.push_back_remote_event(event_meta("$ev3"));
1435 transaction.push_back(item("$ev3"), Some(3));
1436
1437 assert_mapping! {
1438 on transaction:
1439
1440 | event_id | event_index | timeline_item_index |
1441 |----------|-------------|---------------------|
1442 | "$ev0" | 0 | 0 |
1443 | "$ev1" | 1 | 2 |
1444 | "$ev2" | 2 | |
1445 | "$ev3" | 3 | 3 |
1446 }
1447
1448 assert_eq!(transaction.all_remote_events().0.len(), 4);
1449 assert_eq!(transaction.len(), 4);
1450
1451 transaction.clear();
1453
1454 assert!(transaction.all_remote_events().0.is_empty());
1455 assert!(transaction.is_empty());
1456 }
1457
1458 #[test]
1459 fn test_transaction_for_each() {
1460 let mut items = ObservableItems::new();
1461
1462 let mut transaction = items.transaction();
1464 transaction.push_back(item("$ev0"), Some(0));
1465 transaction.push_back(item("$ev1"), Some(1));
1466 transaction.push_back(item("$ev2"), Some(2));
1467
1468 let mut nth = 0;
1469
1470 transaction.for_each(|entry| {
1472 match nth {
1473 0 => {
1474 assert_event_id!(entry, "$ev0");
1475 }
1476 1 => {
1477 assert_event_id!(entry, "$ev1");
1478 }
1479 2 => {
1480 assert_event_id!(entry, "$ev2");
1481 }
1482 _ => unreachable!(),
1483 }
1484
1485 nth += 1;
1486 });
1487 }
1488
1489 #[test]
1490 fn test_transaction_for_each_remove() {
1491 let mut items = ObservableItems::new();
1492
1493 let mut transaction = items.transaction();
1495
1496 transaction.push_back_remote_event(event_meta("$ev0"));
1497 transaction.push_back(item("$ev0"), Some(0));
1498
1499 transaction.push_back_remote_event(event_meta("$ev1"));
1500 transaction.push_back(item("$ev1"), Some(1));
1501
1502 transaction.push_back_remote_event(event_meta("$ev2"));
1503 transaction.push_back(item("$ev2"), Some(2));
1504
1505 assert_mapping! {
1506 on transaction:
1507
1508 | event_id | event_index | timeline_item_index |
1509 |----------|-------------|---------------------|
1510 | "$ev0" | 0 | 0 |
1511 | "$ev1" | 1 | 1 |
1512 | "$ev2" | 2 | 2 |
1513 }
1514
1515 transaction.for_each(|entry| {
1517 if entry.as_event().unwrap().event_id().unwrap().as_str() == "$ev1" {
1518 ObservableItemsTransactionEntry::remove(entry);
1519 }
1520 });
1521
1522 assert_mapping! {
1523 on transaction:
1524
1525 | event_id | event_index | timeline_item_index |
1526 |----------|-------------|---------------------|
1527 | "$ev0" | 0 | 0 |
1528 | "$ev2" | 2 | 1 | }
1530
1531 assert_eq!(transaction.all_remote_events().0.len(), 3);
1532 assert_eq!(transaction.len(), 2);
1533 }
1534
1535 #[test]
1536 fn test_transaction_push_local() {
1537 let mut items = ObservableItems::new();
1538
1539 let mut transaction = items.transaction();
1540
1541 transaction.push_back(item("$ev0"), None);
1543
1544 transaction.push_local(local_item("t0"));
1546
1547 transaction.push_local(local_item("t1"));
1549
1550 transaction.commit();
1551
1552 let mut entries = items.entries();
1553
1554 assert_matches!(entries.next(), Some(entry) => {
1555 assert_event_id!(entry, "$ev0");
1556 });
1557 assert_matches!(entries.next(), Some(entry) => {
1558 assert_transaction_id!(entry, "t0");
1559 });
1560 assert_matches!(entries.next(), Some(entry) => {
1561 assert_transaction_id!(entry, "t1");
1562 });
1563 assert_matches!(entries.next(), None);
1564 }
1565
1566 #[test]
1567 #[should_panic]
1568 fn test_transaction_push_local_panic_not_a_local() {
1569 let mut items = ObservableItems::new();
1570 let mut transaction = items.transaction();
1571 transaction.push_local(item("$ev0"));
1572 }
1573
1574 #[test]
1575 fn test_transaction_push_date_divider() {
1576 let mut items = ObservableItems::new();
1577 let mut stream = items.subscribe().into_stream();
1578
1579 let mut transaction = items.transaction();
1580
1581 transaction.push_date_divider(
1582 0,
1583 TimelineItem::new(
1584 TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(
1585 MilliSecondsSinceUnixEpoch(uint!(10)),
1586 )),
1587 TimelineUniqueId("__foo".to_owned()),
1588 ),
1589 );
1590 transaction.push_date_divider(
1591 0,
1592 TimelineItem::new(
1593 TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(
1594 MilliSecondsSinceUnixEpoch(uint!(20)),
1595 )),
1596 TimelineUniqueId("__bar".to_owned()),
1597 ),
1598 );
1599 transaction.push_date_divider(
1600 1,
1601 TimelineItem::new(
1602 TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(
1603 MilliSecondsSinceUnixEpoch(uint!(30)),
1604 )),
1605 TimelineUniqueId("__baz".to_owned()),
1606 ),
1607 );
1608 transaction.commit();
1609
1610 assert_next_matches!(stream, VectorDiff::PushBack { value: timeline_item } => {
1611 assert_matches!(timeline_item.as_virtual(), Some(VirtualTimelineItem::DateDivider(ms)) => {
1612 assert_eq!(u64::from(ms.0), 10);
1613 });
1614 });
1615 assert_next_matches!(stream, VectorDiff::PushFront { value: timeline_item } => {
1616 assert_matches!(timeline_item.as_virtual(), Some(VirtualTimelineItem::DateDivider(ms)) => {
1617 assert_eq!(u64::from(ms.0), 20);
1618 });
1619 });
1620 assert_next_matches!(stream, VectorDiff::Insert { index: 1, value: timeline_item } => {
1621 assert_matches!(timeline_item.as_virtual(), Some(VirtualTimelineItem::DateDivider(ms)) => {
1622 assert_eq!(u64::from(ms.0), 30);
1623 });
1624 });
1625 assert_pending!(stream);
1626 }
1627
1628 #[test]
1629 #[should_panic]
1630 fn test_transaction_push_date_divider_panic_not_a_date_divider() {
1631 let mut items = ObservableItems::new();
1632 let mut transaction = items.transaction();
1633
1634 transaction.push_date_divider(0, item("$ev0"));
1635 }
1636
1637 #[test]
1638 #[should_panic]
1639 fn test_transaction_push_date_divider_panic_not_in_remotes_region() {
1640 let mut items = ObservableItems::new();
1641 let mut transaction = items.transaction();
1642
1643 transaction.push_timeline_start_if_missing(TimelineItem::new(
1644 VirtualTimelineItem::TimelineStart,
1645 TimelineUniqueId("__id_start".to_owned()),
1646 ));
1647 transaction.push_date_divider(
1648 0,
1649 TimelineItem::new(
1650 VirtualTimelineItem::DateDivider(MilliSecondsSinceUnixEpoch(uint!(10))),
1651 TimelineUniqueId("__date_divider".to_owned()),
1652 ),
1653 );
1654 }
1655
1656 #[test]
1657 fn test_transaction_push_timeline_start_if_missing() {
1658 let mut items = ObservableItems::new();
1659
1660 let mut transaction = items.transaction();
1661
1662 transaction.push_back(item("$ev0"), None);
1664
1665 transaction.push_timeline_start_if_missing(TimelineItem::new(
1667 VirtualTimelineItem::TimelineStart,
1668 TimelineUniqueId("__id_start".to_owned()),
1669 ));
1670
1671 transaction.push_back(item("$ev1"), None);
1673
1674 transaction.push_timeline_start_if_missing(TimelineItem::new(
1676 VirtualTimelineItem::TimelineStart,
1677 TimelineUniqueId("__id_start_again".to_owned()),
1678 ));
1679
1680 transaction.commit();
1681
1682 let mut entries = items.entries();
1683
1684 assert_matches!(entries.next(), Some(entry) => {
1685 assert!(entry.is_timeline_start());
1686 });
1687 assert_matches!(entries.next(), Some(entry) => {
1688 assert_event_id!(entry, "$ev0");
1689 });
1690 assert_matches!(entries.next(), Some(entry) => {
1691 assert_event_id!(entry, "$ev1");
1692 });
1693 assert_matches!(entries.next(), None);
1694 }
1695
1696 #[test]
1697 fn test_transaction_iter_all_regions() {
1698 let mut items = ObservableItems::new();
1699
1700 let mut transaction = items.transaction();
1701 transaction.push_timeline_start_if_missing(TimelineItem::new(
1702 VirtualTimelineItem::TimelineStart,
1703 TimelineUniqueId("__start".to_owned()),
1704 ));
1705 transaction.push_back(item("$ev0"), None);
1706 transaction.push_back(item("$ev1"), None);
1707 transaction.push_back(item("$ev2"), None);
1708 transaction.push_local(local_item("t0"));
1709 transaction.push_local(local_item("t1"));
1710 transaction.push_local(local_item("t2"));
1711
1712 let mut iter = transaction.iter_all_regions();
1714 assert_matches!(iter.next(), Some((0, item)) => {
1715 assert!(item.is_timeline_start());
1716 });
1717 assert_matches!(iter.next(), Some((1, item)) => {
1718 assert_event_id!(item, "$ev0");
1719 });
1720 assert_matches!(iter.next(), Some((2, item)) => {
1721 assert_event_id!(item, "$ev1");
1722 });
1723 assert_matches!(iter.next(), Some((3, item)) => {
1724 assert_event_id!(item, "$ev2");
1725 });
1726 assert_matches!(iter.next(), Some((4, item)) => {
1727 assert_transaction_id!(item, "t0");
1728 });
1729 assert_matches!(iter.next(), Some((5, item)) => {
1730 assert_transaction_id!(item, "t1");
1731 });
1732 assert_matches!(iter.next(), Some((6, item)) => {
1733 assert_transaction_id!(item, "t2");
1734 });
1735 assert!(iter.next().is_none());
1736 }
1737
1738 #[test]
1739 fn test_transaction_iter_remotes_regions() {
1740 let mut items = ObservableItems::new();
1741
1742 let mut transaction = items.transaction();
1743 transaction.push_timeline_start_if_missing(TimelineItem::new(
1744 VirtualTimelineItem::TimelineStart,
1745 TimelineUniqueId("__start".to_owned()),
1746 ));
1747 transaction.push_back(item("$ev0"), None);
1748 transaction.push_back(item("$ev1"), None);
1749 transaction.push_back(item("$ev2"), None);
1750 transaction.push_local(local_item("t0"));
1751 transaction.push_local(local_item("t1"));
1752 transaction.push_local(local_item("t2"));
1753
1754 let mut iter = transaction.iter_remotes_region();
1756 assert_matches!(iter.next(), Some((1, item)) => {
1757 assert_event_id!(item, "$ev0");
1758 });
1759 assert_matches!(iter.next(), Some((2, item)) => {
1760 assert_event_id!(item, "$ev1");
1761 });
1762 assert_matches!(iter.next(), Some((3, item)) => {
1763 assert_event_id!(item, "$ev2");
1764 });
1765 assert!(iter.next().is_none());
1766 }
1767
1768 #[test]
1769 fn test_transaction_iter_remotes_regions_with_no_start_region() {
1770 let mut items = ObservableItems::new();
1771
1772 let mut transaction = items.transaction();
1773 transaction.push_back(item("$ev0"), None);
1774 transaction.push_back(item("$ev1"), None);
1775 transaction.push_back(item("$ev2"), None);
1776 transaction.push_local(local_item("t0"));
1777 transaction.push_local(local_item("t1"));
1778 transaction.push_local(local_item("t2"));
1779
1780 let mut iter = transaction.iter_remotes_region();
1782 assert_matches!(iter.next(), Some((0, item)) => {
1783 assert_event_id!(item, "$ev0");
1784 });
1785 assert_matches!(iter.next(), Some((1, item)) => {
1786 assert_event_id!(item, "$ev1");
1787 });
1788 assert_matches!(iter.next(), Some((2, item)) => {
1789 assert_event_id!(item, "$ev2");
1790 });
1791 assert!(iter.next().is_none());
1792 }
1793
1794 #[test]
1795 fn test_transaction_iter_remotes_regions_with_no_locals_region() {
1796 let mut items = ObservableItems::new();
1797
1798 let mut transaction = items.transaction();
1799 transaction.push_back(item("$ev0"), None);
1800 transaction.push_back(item("$ev1"), None);
1801 transaction.push_back(item("$ev2"), None);
1802
1803 let mut iter = transaction.iter_remotes_region();
1805 assert_matches!(iter.next(), Some((0, item)) => {
1806 assert_event_id!(item, "$ev0");
1807 });
1808 assert_matches!(iter.next(), Some((1, item)) => {
1809 assert_event_id!(item, "$ev1");
1810 });
1811 assert_matches!(iter.next(), Some((2, item)) => {
1812 assert_event_id!(item, "$ev2");
1813 });
1814 assert!(iter.next().is_none());
1815 }
1816
1817 #[test]
1818 fn test_transaction_iter_locals_region() {
1819 let mut items = ObservableItems::new();
1820
1821 let mut transaction = items.transaction();
1822 transaction.push_timeline_start_if_missing(TimelineItem::new(
1823 VirtualTimelineItem::TimelineStart,
1824 TimelineUniqueId("__start".to_owned()),
1825 ));
1826 transaction.push_back(item("$ev0"), None);
1827 transaction.push_back(item("$ev1"), None);
1828 transaction.push_back(item("$ev2"), None);
1829 transaction.push_local(local_item("t0"));
1830 transaction.push_local(local_item("t1"));
1831 transaction.push_local(local_item("t2"));
1832
1833 let mut iter = transaction.iter_locals_region();
1835 assert_matches!(iter.next(), Some((4, item)) => {
1836 assert_transaction_id!(item, "t0");
1837 });
1838 assert_matches!(iter.next(), Some((5, item)) => {
1839 assert_transaction_id!(item, "t1");
1840 });
1841 assert_matches!(iter.next(), Some((6, item)) => {
1842 assert_transaction_id!(item, "t2");
1843 });
1844 assert!(iter.next().is_none());
1845 }
1846}
1847
1848#[derive(Clone, Debug, Default)]
1854pub struct AllRemoteEvents(VecDeque<EventMeta>);
1855
1856impl AllRemoteEvents {
1857 pub fn get(&self, event_index: usize) -> Option<&EventMeta> {
1859 self.0.get(event_index)
1860 }
1861
1862 pub fn iter(&self) -> Iter<'_, EventMeta> {
1864 self.0.iter()
1865 }
1866
1867 pub fn range<R>(&self, range: R) -> Iter<'_, EventMeta>
1870 where
1871 R: RangeBounds<usize>,
1872 {
1873 self.0.range(range)
1874 }
1875
1876 fn clear(&mut self) {
1878 self.0.clear();
1879 }
1880
1881 fn push_front(&mut self, event_meta: EventMeta) {
1883 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1886 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1887 }
1888
1889 self.0.push_front(event_meta)
1891 }
1892
1893 fn push_back(&mut self, event_meta: EventMeta) {
1895 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1898 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1899 }
1900
1901 self.0.push_back(event_meta)
1903 }
1904
1905 fn insert(&mut self, event_index: usize, event_meta: EventMeta) {
1907 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1910 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1911 }
1912
1913 self.0.insert(event_index, event_meta)
1915 }
1916
1917 fn remove(&mut self, event_index: usize) -> Option<EventMeta> {
1919 let event_meta = self.0.remove(event_index)?;
1921
1922 if let Some(removed_timeline_item_index) = event_meta.timeline_item_index {
1925 self.decrement_all_timeline_item_index_after(removed_timeline_item_index);
1926 }
1927
1928 Some(event_meta)
1929 }
1930
1931 #[cfg(test)]
1933 pub fn last(&self) -> Option<&EventMeta> {
1934 self.0.back()
1935 }
1936
1937 pub fn last_index(&self) -> Option<usize> {
1939 self.0.len().checked_sub(1)
1940 }
1941
1942 pub fn get_by_event_id_mut(&mut self, event_id: &EventId) -> Option<&mut EventMeta> {
1944 self.0.iter_mut().rev().find(|event_meta| event_meta.event_id == event_id)
1945 }
1946
1947 pub fn get_by_event_id(&self, event_id: &EventId) -> Option<&EventMeta> {
1949 self.0.iter().rev().find(|event_meta| event_meta.event_id == event_id)
1950 }
1951
1952 pub fn position_by_event_id(&self, event_id: &EventId) -> Option<usize> {
1954 self.0
1957 .iter()
1958 .enumerate()
1959 .rev()
1960 .find_map(|(i, event_meta)| (event_meta.event_id == event_id).then_some(i))
1961 }
1962
1963 fn increment_all_timeline_item_index_after(&mut self, new_timeline_item_index: usize) {
1966 for event_meta in self.0.iter_mut().rev() {
1974 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
1975 if *timeline_item_index >= new_timeline_item_index {
1976 *timeline_item_index += 1;
1977 } else {
1978 break;
1980 }
1981 }
1982 }
1983 }
1984
1985 fn decrement_all_timeline_item_index_after(&mut self, removed_timeline_item_index: usize) {
1988 for event_meta in self.0.iter_mut().rev() {
1996 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
1997 if *timeline_item_index > removed_timeline_item_index {
1998 *timeline_item_index -= 1;
1999 } else {
2000 break;
2002 }
2003 }
2004 }
2005 }
2006
2007 fn timeline_item_has_been_inserted_at(
2012 &mut self,
2013 new_timeline_item_index: usize,
2014 event_index: Option<usize>,
2015 ) {
2016 self.increment_all_timeline_item_index_after(new_timeline_item_index);
2017
2018 if let Some(event_index) = event_index
2019 && let Some(event_meta) = self.0.get_mut(event_index)
2020 {
2021 event_meta.timeline_item_index = Some(new_timeline_item_index);
2022 }
2023 }
2024
2025 fn timeline_item_has_been_removed_at(&mut self, timeline_item_index_to_remove: usize) {
2028 for event_meta in self.0.iter_mut() {
2029 let mut remove_timeline_item_index = false;
2030
2031 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
2034 match (*timeline_item_index).cmp(&timeline_item_index_to_remove) {
2035 Ordering::Equal => {
2036 remove_timeline_item_index = true;
2037 }
2038
2039 Ordering::Greater => {
2040 *timeline_item_index -= 1;
2041 }
2042
2043 Ordering::Less => {}
2044 }
2045 }
2046
2047 if remove_timeline_item_index {
2050 event_meta.timeline_item_index = None;
2051 }
2052 }
2053 }
2054}
2055
2056#[cfg(test)]
2057mod all_remote_events_tests {
2058 use assert_matches::assert_matches;
2059 use ruma::event_id;
2060
2061 use super::{AllRemoteEvents, EventMeta};
2062
2063 fn event_meta(event_id: &str, timeline_item_index: Option<usize>) -> EventMeta {
2064 EventMeta {
2065 event_id: event_id.parse().unwrap(),
2066 thread_root_id: None,
2067 timeline_item_index,
2068 visible: false,
2069 can_show_read_receipts: false,
2070 }
2071 }
2072
2073 macro_rules! assert_events {
2074 ( $events:ident, [ $( ( $event_id:literal, $timeline_item_index:expr ) ),* $(,)? ] ) => {
2075 let mut iter = $events .iter();
2076
2077 $(
2078 assert_matches!(iter.next(), Some(EventMeta { event_id, timeline_item_index, .. }) => {
2079 assert_eq!(event_id.as_str(), $event_id );
2080 assert_eq!(*timeline_item_index, $timeline_item_index );
2081 });
2082 )*
2083
2084 assert!(iter.next().is_none(), "Not all events have been asserted");
2085 }
2086 }
2087
2088 #[test]
2089 fn test_range() {
2090 let mut events = AllRemoteEvents::default();
2091
2092 events.push_back(event_meta("$ev0", None));
2094 events.push_back(event_meta("$ev1", None));
2095 events.push_back(event_meta("$ev2", None));
2096
2097 assert_eq!(events.iter().count(), 3);
2098
2099 assert_eq!(events.range(..).count(), 3);
2101 assert_eq!(events.range(1..).count(), 2);
2102 assert_eq!(events.range(0..=1).count(), 2);
2103
2104 let mut some_events = events.range(1..);
2106
2107 assert_matches!(some_events.next(), Some(EventMeta { event_id, .. }) => {
2108 assert_eq!(event_id.as_str(), "$ev1");
2109 });
2110 assert_matches!(some_events.next(), Some(EventMeta { event_id, .. }) => {
2111 assert_eq!(event_id.as_str(), "$ev2");
2112 });
2113 assert!(some_events.next().is_none());
2114 }
2115
2116 #[test]
2117 fn test_clear() {
2118 let mut events = AllRemoteEvents::default();
2119
2120 events.push_back(event_meta("$ev0", None));
2122 events.push_back(event_meta("$ev1", None));
2123 events.push_back(event_meta("$ev2", None));
2124
2125 assert_eq!(events.iter().count(), 3);
2126
2127 events.clear();
2129
2130 assert_eq!(events.iter().count(), 0);
2131 }
2132
2133 #[test]
2134 fn test_push_front() {
2135 let mut events = AllRemoteEvents::default();
2136
2137 events.push_front(event_meta("$ev0", Some(1)));
2139
2140 events.push_front(event_meta("$ev1", None));
2142
2143 events.push_front(event_meta("$ev2", Some(0)));
2145
2146 events.push_front(event_meta("$ev3", Some(0)));
2148
2149 assert_events!(
2150 events,
2151 [
2152 ("$ev3", Some(0)),
2154 ("$ev2", Some(1)),
2156 ("$ev1", None),
2158 ("$ev0", Some(3)),
2160 ]
2161 );
2162 }
2163
2164 #[test]
2165 fn test_push_back() {
2166 let mut events = AllRemoteEvents::default();
2167
2168 events.push_back(event_meta("$ev0", Some(0)));
2170
2171 events.push_back(event_meta("$ev1", None));
2173
2174 events.push_back(event_meta("$ev2", Some(1)));
2176
2177 events.push_back(event_meta("$ev3", Some(1)));
2181
2182 assert_events!(
2183 events,
2184 [
2185 ("$ev0", Some(0)),
2187 ("$ev1", None),
2189 ("$ev2", Some(2)),
2191 ("$ev3", Some(1)),
2193 ]
2194 );
2195 }
2196
2197 #[test]
2198 fn test_insert() {
2199 let mut events = AllRemoteEvents::default();
2200
2201 events.insert(0, event_meta("$ev0", Some(0)));
2203
2204 events.insert(1, event_meta("$ev1", None));
2206
2207 events.insert(2, event_meta("$ev2", Some(1)));
2209
2210 events.insert(0, event_meta("$ev3", Some(0)));
2212
2213 assert_events!(
2214 events,
2215 [
2216 ("$ev3", Some(0)),
2218 ("$ev0", Some(1)),
2220 ("$ev1", None),
2222 ("$ev2", Some(2)),
2224 ]
2225 );
2226 }
2227
2228 #[test]
2229 fn test_remove() {
2230 let mut events = AllRemoteEvents::default();
2231
2232 events.push_back(event_meta("$ev0", Some(0)));
2234 events.push_back(event_meta("$ev1", Some(1)));
2235 events.push_back(event_meta("$ev2", None));
2236 events.push_back(event_meta("$ev3", Some(2)));
2237
2238 assert_events!(
2240 events,
2241 [("$ev0", Some(0)), ("$ev1", Some(1)), ("$ev2", None), ("$ev3", Some(2))]
2242 );
2243
2244 events.remove(2); events.remove(1); assert_events!(
2249 events,
2250 [
2251 ("$ev0", Some(0)),
2252 ("$ev3", Some(1)),
2254 ]
2255 );
2256 }
2257
2258 #[test]
2259 fn test_last() {
2260 let mut events = AllRemoteEvents::default();
2261
2262 assert!(events.last().is_none());
2263 assert!(events.last_index().is_none());
2264
2265 events.push_back(event_meta("$ev0", Some(0)));
2267 events.push_back(event_meta("$ev1", Some(1)));
2268
2269 assert_matches!(events.last(), Some(EventMeta { event_id, .. }) => {
2270 assert_eq!(event_id.as_str(), "$ev1");
2271 });
2272 assert_eq!(events.last_index(), Some(1));
2273 }
2274
2275 #[test]
2276 fn test_get_by_event_by_mut() {
2277 let mut events = AllRemoteEvents::default();
2278
2279 events.push_back(event_meta("$ev0", Some(0)));
2281 events.push_back(event_meta("$ev1", Some(1)));
2282
2283 assert!(events.get_by_event_id_mut(event_id!("$ev0")).is_some());
2284 assert!(events.get_by_event_id_mut(event_id!("$ev42")).is_none());
2285 }
2286
2287 #[test]
2288 fn test_timeline_item_has_been_inserted_at() {
2289 let mut events = AllRemoteEvents::default();
2290
2291 events.push_back(event_meta("$ev0", Some(0)));
2293 events.push_back(event_meta("$ev1", Some(1)));
2294 events.push_back(event_meta("$ev2", None));
2295 events.push_back(event_meta("$ev3", None));
2296 events.push_back(event_meta("$ev4", Some(2)));
2297 events.push_back(event_meta("$ev5", Some(3)));
2298 events.push_back(event_meta("$ev6", None));
2299
2300 events.timeline_item_has_been_inserted_at(2, None);
2302
2303 assert_events!(
2304 events,
2305 [
2306 ("$ev0", Some(0)),
2307 ("$ev1", Some(1)),
2308 ("$ev2", None),
2309 ("$ev3", None),
2310 ("$ev4", Some(3)),
2312 ("$ev5", Some(4)),
2314 ("$ev6", None),
2315 ]
2316 );
2317
2318 events.timeline_item_has_been_inserted_at(5, Some(6));
2320
2321 assert_events!(
2322 events,
2323 [
2324 ("$ev0", Some(0)),
2325 ("$ev1", Some(1)),
2326 ("$ev2", None),
2327 ("$ev3", None),
2328 ("$ev4", Some(3)),
2329 ("$ev5", Some(4)),
2330 ("$ev6", Some(5)),
2332 ]
2333 );
2334 }
2335
2336 #[test]
2337 fn test_timeline_item_has_been_removed_at() {
2338 let mut events = AllRemoteEvents::default();
2339
2340 events.push_back(event_meta("$ev0", Some(0)));
2342 events.push_back(event_meta("$ev1", Some(1)));
2343 events.push_back(event_meta("$ev2", None));
2344 events.push_back(event_meta("$ev3", None));
2345 events.push_back(event_meta("$ev4", Some(3)));
2346 events.push_back(event_meta("$ev5", Some(4)));
2347 events.push_back(event_meta("$ev6", None));
2348
2349 events.timeline_item_has_been_removed_at(2);
2351
2352 assert_events!(
2353 events,
2354 [
2355 ("$ev0", Some(0)),
2356 ("$ev1", Some(1)),
2357 ("$ev2", None),
2358 ("$ev3", None),
2359 ("$ev4", Some(2)),
2361 ("$ev5", Some(3)),
2363 ("$ev6", None),
2364 ]
2365 );
2366
2367 events.timeline_item_has_been_removed_at(2);
2369
2370 assert_events!(
2371 events,
2372 [
2373 ("$ev0", Some(0)),
2374 ("$ev1", Some(1)),
2375 ("$ev2", None),
2376 ("$ev3", None),
2377 ("$ev4", None),
2379 ("$ev5", Some(2)),
2381 ("$ev6", None),
2382 ]
2383 );
2384
2385 events.timeline_item_has_been_removed_at(0);
2387
2388 assert_events!(
2389 events,
2390 [
2391 ("$ev0", None),
2393 ("$ev1", Some(0)),
2395 ("$ev2", None),
2396 ("$ev3", None),
2397 ("$ev4", None),
2398 ("$ev5", Some(1)),
2400 ("$ev6", None),
2401 ]
2402 );
2403 }
2404}