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 None,
738 None,
739 MilliSecondsSinceUnixEpoch(0u32.into()),
740 TimelineItemContent::MsgLike(MsgLikeContent {
741 kind: MsgLikeKind::Message(Message {
742 msgtype: MessageType::Text(TextMessageEventContent::plain("hello")),
743 edited: false,
744 mentions: None,
745 }),
746 reactions: Default::default(),
747 thread_root: None,
748 in_reply_to: None,
749 thread_summary: None,
750 }),
751 EventTimelineItemKind::Remote(RemoteEventTimelineItem {
752 event_id: event_id.parse().unwrap(),
753 transaction_id: None,
754 read_receipts: Default::default(),
755 is_own: false,
756 is_highlighted: false,
757 encryption_info: None,
758 original_json: None,
759 latest_edit_json: None,
760 origin: RemoteEventOrigin::Sync,
761 }),
762 false,
763 ),
764 TimelineUniqueId(format!("__eid_{event_id}")),
765 )
766 }
767
768 fn local_item(transaction_id: &str) -> Arc<TimelineItem> {
769 TimelineItem::new(
770 EventTimelineItem::new(
771 owned_user_id!("@ivan:mnt.io"),
772 TimelineDetails::Unavailable,
773 None,
774 None,
775 MilliSecondsSinceUnixEpoch(0u32.into()),
776 TimelineItemContent::MsgLike(MsgLikeContent {
777 kind: MsgLikeKind::Message(Message {
778 msgtype: MessageType::Text(TextMessageEventContent::plain("hello")),
779 edited: false,
780 mentions: None,
781 }),
782 reactions: Default::default(),
783 thread_root: None,
784 in_reply_to: None,
785 thread_summary: None,
786 }),
787 EventTimelineItemKind::Local(LocalEventTimelineItem {
788 send_state: EventSendState::NotSentYet { progress: None },
789 transaction_id: transaction_id.into(),
790 send_handle: None,
791 }),
792 false,
793 ),
794 TimelineUniqueId(format!("__tid_{transaction_id}")),
795 )
796 }
797
798 fn read_marker() -> Arc<TimelineItem> {
799 TimelineItem::read_marker()
800 }
801
802 fn event_meta(event_id: &str) -> EventMeta {
803 EventMeta {
804 event_id: event_id.parse().unwrap(),
805 thread_root_id: None,
806 timeline_item_index: None,
807 visible: false,
808 can_show_read_receipts: false,
809 }
810 }
811
812 macro_rules! assert_event_id {
813 ( $timeline_item:expr, $event_id:literal $( , $message:expr )? $(,)? ) => {
814 assert_eq!($timeline_item.as_event().unwrap().event_id().unwrap().as_str(), $event_id $( , $message)? );
815 };
816 }
817
818 macro_rules! assert_transaction_id {
819 ( $timeline_item:expr, $transaction_id:literal $( , $message:expr )? $(,)? ) => {
820 assert_eq!($timeline_item.as_event().unwrap().transaction_id().unwrap().as_str(), $transaction_id $( , $message)? );
821 };
822 }
823
824 macro_rules! assert_mapping {
825 ( on $transaction:ident:
826 | event_id | event_index | timeline_item_index |
827 | $( - )+ | $( - )+ | $( - )+ |
828 $(
829 | $event_id:literal | $event_index:literal | $( $timeline_item_index:literal )? |
830 )+
831 ) => {
832 let all_remote_events = $transaction .all_remote_events();
833
834 $(
835 assert_matches!(all_remote_events.0.get( $event_index ), Some(EventMeta { event_id, timeline_item_index, .. }) => {
837 assert_eq!(
839 event_id.as_str(),
840 $event_id ,
841 concat!("event #", $event_index, " should have ID ", $event_id)
842 );
843
844
845 #[allow(unused_variables)]
847 let timeline_item_index_is_expected = false;
848 $(
849 let timeline_item_index_is_expected = true;
850 let _ = $timeline_item_index;
851 )?
852
853 if timeline_item_index_is_expected.not() {
854 assert!(
856 timeline_item_index.is_none(),
857 concat!("event #", $event_index, " with ID ", $event_id, " should NOT map to a timeline item index" )
858 );
859 }
860
861 $(
862 assert_eq!(
864 *timeline_item_index,
865 Some( $timeline_item_index ),
866 concat!("event #", $event_index, " with ID ", $event_id, " should map to timeline item #", $timeline_item_index )
867 );
868
869 assert_matches!( $transaction .get( $timeline_item_index ), Some(timeline_item) => {
871 assert_event_id!(
873 timeline_item,
874 $event_id ,
875 concat!("timeline item #", $timeline_item_index, " should map to event ID ", $event_id )
876 );
877 });
878 )?
879 });
880 )*
881 }
882 }
883
884 #[test]
885 fn test_is_empty() {
886 let mut items = ObservableItems::new();
887
888 assert!(items.is_empty());
889
890 let mut transaction = items.transaction();
892 transaction.push_back(item("$ev0"), Some(0));
893 transaction.commit();
894
895 assert!(items.is_empty().not());
896 }
897
898 #[test]
899 fn test_subscribe() {
900 let mut items = ObservableItems::new();
901 let mut subscriber = items.subscribe().into_stream();
902
903 let mut transaction = items.transaction();
905 transaction.push_back(item("$ev0"), Some(0));
906 transaction.commit();
907
908 assert_next_matches!(subscriber, VectorDiff::PushBack { value: event } => {
910 assert_event_id!(event, "$ev0");
911 });
912 }
913
914 #[test]
915 fn test_clone_items() {
916 let mut items = ObservableItems::new();
917
918 let mut transaction = items.transaction();
919 transaction.push_back(item("$ev0"), Some(0));
920 transaction.push_back(item("$ev1"), Some(1));
921 transaction.commit();
922
923 let items = items.clone_items();
924 assert_eq!(items.len(), 2);
925 assert_event_id!(items[0], "$ev0");
926 assert_event_id!(items[1], "$ev1");
927 }
928
929 #[test]
930 fn test_replace() {
931 let mut items = ObservableItems::new();
932
933 let mut transaction = items.transaction();
935 transaction.push_back(item("$ev0"), Some(0));
936 transaction.commit();
937
938 items.replace(0, item("$ev1"));
940
941 let items = items.clone_items();
942 assert_eq!(items.len(), 1);
943 assert_event_id!(items[0], "$ev1");
944 }
945
946 #[test]
947 fn test_entries() {
948 let mut items = ObservableItems::new();
949
950 let mut transaction = items.transaction();
952 transaction.push_back(item("$ev0"), Some(0));
953 transaction.push_back(item("$ev1"), Some(1));
954 transaction.push_back(item("$ev2"), Some(2));
955 transaction.commit();
956
957 let mut entries = items.entries();
958
959 assert_matches!(entries.next(), Some(entry) => {
960 assert_event_id!(entry, "$ev0");
961 });
962 assert_matches!(entries.next(), Some(entry) => {
963 assert_event_id!(entry, "$ev1");
964 });
965 assert_matches!(entries.next(), Some(entry) => {
966 assert_event_id!(entry, "$ev2");
967 });
968 assert_matches!(entries.next(), None);
969 }
970
971 #[test]
972 fn test_entry_replace() {
973 let mut items = ObservableItems::new();
974
975 let mut transaction = items.transaction();
977 transaction.push_back(item("$ev0"), Some(0));
978 transaction.commit();
979
980 let mut entries = items.entries();
981
982 assert_matches!(entries.next(), Some(mut entry) => {
984 assert_event_id!(entry, "$ev0");
985 ObservableItemsEntry::replace(&mut entry, item("$ev1"));
986 });
987 assert_matches!(entries.next(), None);
988
989 let mut entries = items.entries();
991
992 assert_matches!(entries.next(), Some(entry) => {
993 assert_event_id!(entry, "$ev1");
994 });
995 assert_matches!(entries.next(), None);
996 }
997
998 #[test]
999 fn test_for_each() {
1000 let mut items = ObservableItems::new();
1001
1002 let mut transaction = items.transaction();
1004 transaction.push_back(item("$ev0"), Some(0));
1005 transaction.push_back(item("$ev1"), Some(1));
1006 transaction.push_back(item("$ev2"), Some(2));
1007 transaction.commit();
1008
1009 let mut nth = 0;
1010
1011 items.for_each(|entry| {
1013 match nth {
1014 0 => {
1015 assert_event_id!(entry, "$ev0");
1016 }
1017 1 => {
1018 assert_event_id!(entry, "$ev1");
1019 }
1020 2 => {
1021 assert_event_id!(entry, "$ev2");
1022 }
1023 _ => unreachable!(),
1024 }
1025
1026 nth += 1;
1027 });
1028 }
1029
1030 #[test]
1031 fn test_transaction_commit() {
1032 let mut items = ObservableItems::new();
1033
1034 let mut transaction = items.transaction();
1036 transaction.push_back(item("$ev0"), Some(0));
1037 drop(transaction);
1038
1039 assert!(items.is_empty());
1040
1041 let mut transaction = items.transaction();
1043 transaction.push_back(item("$ev0"), Some(0));
1044 transaction.commit();
1045
1046 assert!(items.is_empty().not());
1047 }
1048
1049 #[test]
1050 fn test_transaction_get() {
1051 let mut items = ObservableItems::new();
1052
1053 let mut transaction = items.transaction();
1054 transaction.push_back(item("$ev0"), Some(0));
1055
1056 assert_matches!(transaction.get(0), Some(event) => {
1057 assert_event_id!(event, "$ev0");
1058 });
1059 }
1060
1061 #[test]
1062 fn test_transaction_replace() {
1063 let mut items = ObservableItems::new();
1064
1065 let mut transaction = items.transaction();
1066 transaction.push_back(item("$ev0"), Some(0));
1067 transaction.replace(0, item("$ev1"));
1068
1069 assert_matches!(transaction.get(0), Some(event) => {
1070 assert_event_id!(event, "$ev1");
1071 });
1072 }
1073
1074 #[test]
1075 fn test_transaction_insert() {
1076 let mut items = ObservableItems::new();
1077
1078 let mut transaction = items.transaction();
1079
1080 transaction.push_back_remote_event(event_meta("$ev0"));
1082 transaction.insert(0, item("$ev0"), Some(0));
1083
1084 assert_mapping! {
1085 on transaction:
1086
1087 | event_id | event_index | timeline_item_index |
1088 |----------|-------------|---------------------|
1089 | "$ev0" | 0 | 0 | }
1091
1092 transaction.insert(0, read_marker(), None);
1094
1095 assert_mapping! {
1096 on transaction:
1097
1098 | event_id | event_index | timeline_item_index |
1099 |----------|-------------|---------------------|
1100 | "$ev0" | 0 | 1 | }
1102
1103 transaction.push_back_remote_event(event_meta("$ev1"));
1105 transaction.insert(2, item("$ev1"), Some(1));
1106
1107 assert_mapping! {
1108 on transaction:
1109
1110 | event_id | event_index | timeline_item_index |
1111 |----------|-------------|---------------------|
1112 | "$ev0" | 0 | 1 |
1113 | "$ev1" | 1 | 2 | }
1115
1116 transaction.push_back_remote_event(event_meta("$ev2"));
1118
1119 assert_mapping! {
1120 on transaction:
1121
1122 | event_id | event_index | timeline_item_index |
1123 |----------|-------------|---------------------|
1124 | "$ev0" | 0 | 1 |
1125 | "$ev1" | 1 | 2 |
1126 | "$ev2" | 2 | | }
1128
1129 transaction.push_back_remote_event(event_meta("$ev3"));
1131 transaction.insert(3, item("$ev3"), Some(3));
1132
1133 assert_mapping! {
1134 on transaction:
1135
1136 | event_id | event_index | timeline_item_index |
1137 |----------|-------------|---------------------|
1138 | "$ev0" | 0 | 1 |
1139 | "$ev1" | 1 | 2 |
1140 | "$ev2" | 2 | |
1141 | "$ev3" | 3 | 3 | }
1143
1144 transaction.insert(3, item("$ev2"), Some(2));
1147
1148 assert_mapping! {
1149 on transaction:
1150
1151 | event_id | event_index | timeline_item_index |
1152 |----------|-------------|---------------------|
1153 | "$ev0" | 0 | 1 |
1154 | "$ev1" | 1 | 2 |
1155 | "$ev2" | 2 | 3 | | "$ev3" | 3 | 4 | }
1158
1159 transaction.remove(0);
1161 transaction.insert(2, read_marker(), None);
1162
1163 assert_mapping! {
1164 on transaction:
1165
1166 | event_id | event_index | timeline_item_index |
1167 |----------|-------------|---------------------|
1168 | "$ev0" | 0 | 0 | | "$ev1" | 1 | 1 | | "$ev2" | 2 | 3 |
1171 | "$ev3" | 3 | 4 |
1172 }
1173
1174 assert_eq!(transaction.len(), 5);
1175 }
1176
1177 #[test]
1178 fn test_transaction_push_front() {
1179 let mut items = ObservableItems::new();
1180
1181 let mut transaction = items.transaction();
1182
1183 transaction.push_front_remote_event(event_meta("$ev0"));
1185 transaction.push_front(item("$ev0"), Some(0));
1186
1187 assert_mapping! {
1188 on transaction:
1189
1190 | event_id | event_index | timeline_item_index |
1191 |----------|-------------|---------------------|
1192 | "$ev0" | 0 | 0 | }
1194
1195 transaction.push_front(read_marker(), None);
1197
1198 assert_mapping! {
1199 on transaction:
1200
1201 | event_id | event_index | timeline_item_index |
1202 |----------|-------------|---------------------|
1203 | "$ev0" | 0 | 1 | }
1205
1206 transaction.push_front_remote_event(event_meta("$ev1"));
1208 transaction.push_front(item("$ev1"), Some(0));
1209
1210 assert_mapping! {
1211 on transaction:
1212
1213 | event_id | event_index | timeline_item_index |
1214 |----------|-------------|---------------------|
1215 | "$ev1" | 0 | 0 | | "$ev0" | 1 | 2 | }
1218
1219 transaction.push_front_remote_event(event_meta("$ev2"));
1221
1222 assert_mapping! {
1223 on transaction:
1224
1225 | event_id | event_index | timeline_item_index |
1226 |----------|-------------|---------------------|
1227 | "$ev2" | 0 | |
1228 | "$ev1" | 1 | 0 | | "$ev0" | 2 | 2 | }
1231
1232 transaction.push_front_remote_event(event_meta("$ev3"));
1234 transaction.push_front(item("$ev3"), Some(0));
1235
1236 assert_mapping! {
1237 on transaction:
1238
1239 | event_id | event_index | timeline_item_index |
1240 |----------|-------------|---------------------|
1241 | "$ev3" | 0 | 0 | | "$ev2" | 1 | |
1243 | "$ev1" | 2 | 1 | | "$ev0" | 3 | 3 | }
1246
1247 assert_eq!(transaction.len(), 4);
1248 }
1249
1250 #[test]
1251 fn test_transaction_push_back() {
1252 let mut items = ObservableItems::new();
1253
1254 let mut transaction = items.transaction();
1255
1256 transaction.push_back_remote_event(event_meta("$ev0"));
1258 transaction.push_back(item("$ev0"), Some(0));
1259
1260 assert_mapping! {
1261 on transaction:
1262
1263 | event_id | event_index | timeline_item_index |
1264 |----------|-------------|---------------------|
1265 | "$ev0" | 0 | 0 | }
1267
1268 transaction.push_back(read_marker(), None);
1270
1271 assert_mapping! {
1272 on transaction:
1273
1274 | event_id | event_index | timeline_item_index |
1275 |----------|-------------|---------------------|
1276 | "$ev0" | 0 | 0 |
1277 }
1278
1279 transaction.push_back_remote_event(event_meta("$ev1"));
1281 transaction.push_back(item("$ev1"), Some(1));
1282
1283 assert_mapping! {
1284 on transaction:
1285
1286 | event_id | event_index | timeline_item_index |
1287 |----------|-------------|---------------------|
1288 | "$ev0" | 0 | 0 |
1289 | "$ev1" | 1 | 2 | }
1291
1292 transaction.push_back_remote_event(event_meta("$ev2"));
1294
1295 assert_mapping! {
1296 on transaction:
1297
1298 | event_id | event_index | timeline_item_index |
1299 |----------|-------------|---------------------|
1300 | "$ev0" | 0 | 0 |
1301 | "$ev1" | 1 | 2 |
1302 | "$ev2" | 2 | | }
1304
1305 transaction.push_back_remote_event(event_meta("$ev3"));
1307 transaction.push_back(item("$ev3"), Some(3));
1308
1309 assert_mapping! {
1310 on transaction:
1311
1312 | event_id | event_index | timeline_item_index |
1313 |----------|-------------|---------------------|
1314 | "$ev0" | 0 | 0 |
1315 | "$ev1" | 1 | 2 |
1316 | "$ev2" | 2 | |
1317 | "$ev3" | 3 | 3 | }
1319
1320 assert_eq!(transaction.len(), 4);
1321 }
1322
1323 #[test]
1324 fn test_transaction_remove() {
1325 let mut items = ObservableItems::new();
1326
1327 let mut transaction = items.transaction();
1328
1329 transaction.push_back_remote_event(event_meta("$ev0"));
1331 transaction.push_back(item("$ev0"), Some(0));
1332
1333 transaction.push_back(read_marker(), None);
1335
1336 transaction.push_back_remote_event(event_meta("$ev1"));
1338 transaction.push_back(item("$ev1"), Some(1));
1339
1340 transaction.push_back_remote_event(event_meta("$ev2"));
1342
1343 transaction.push_back_remote_event(event_meta("$ev3"));
1345 transaction.push_back(item("$ev3"), Some(3));
1346
1347 assert_mapping! {
1348 on transaction:
1349
1350 | event_id | event_index | timeline_item_index |
1351 |----------|-------------|---------------------|
1352 | "$ev0" | 0 | 0 |
1353 | "$ev1" | 1 | 2 |
1354 | "$ev2" | 2 | |
1355 | "$ev3" | 3 | 3 |
1356 }
1357
1358 transaction.remove(1);
1360
1361 assert_mapping! {
1362 on transaction:
1363
1364 | event_id | event_index | timeline_item_index |
1365 |----------|-------------|---------------------|
1366 | "$ev0" | 0 | 0 |
1367 | "$ev1" | 1 | 1 | | "$ev2" | 2 | |
1369 | "$ev3" | 3 | 2 | }
1371
1372 transaction.remove(1);
1374
1375 assert_mapping! {
1376 on transaction:
1377
1378 | event_id | event_index | timeline_item_index |
1379 |----------|-------------|---------------------|
1380 | "$ev0" | 0 | 0 |
1381 | "$ev1" | 1 | | | "$ev2" | 2 | |
1383 | "$ev3" | 3 | 1 | }
1385
1386 transaction.remove(1);
1388
1389 assert_mapping! {
1390 on transaction:
1391
1392 | event_id | event_index | timeline_item_index |
1393 |----------|-------------|---------------------|
1394 | "$ev0" | 0 | 0 |
1395 | "$ev1" | 1 | |
1396 | "$ev2" | 2 | |
1397 | "$ev3" | 3 | | }
1399
1400 transaction.remove(0);
1402
1403 assert_mapping! {
1404 on transaction:
1405
1406 | event_id | event_index | timeline_item_index |
1407 |----------|-------------|---------------------|
1408 | "$ev0" | 0 | | | "$ev1" | 1 | |
1410 | "$ev2" | 2 | |
1411 | "$ev3" | 3 | |
1412 }
1413
1414 assert!(transaction.is_empty());
1415 }
1416
1417 #[test]
1418 fn test_transaction_clear() {
1419 let mut items = ObservableItems::new();
1420
1421 let mut transaction = items.transaction();
1422
1423 transaction.push_back_remote_event(event_meta("$ev0"));
1425 transaction.push_back(item("$ev0"), Some(0));
1426
1427 transaction.push_back(read_marker(), None);
1429
1430 transaction.push_back_remote_event(event_meta("$ev1"));
1432 transaction.push_back(item("$ev1"), Some(1));
1433
1434 transaction.push_back_remote_event(event_meta("$ev2"));
1436
1437 transaction.push_back_remote_event(event_meta("$ev3"));
1439 transaction.push_back(item("$ev3"), Some(3));
1440
1441 assert_mapping! {
1442 on transaction:
1443
1444 | event_id | event_index | timeline_item_index |
1445 |----------|-------------|---------------------|
1446 | "$ev0" | 0 | 0 |
1447 | "$ev1" | 1 | 2 |
1448 | "$ev2" | 2 | |
1449 | "$ev3" | 3 | 3 |
1450 }
1451
1452 assert_eq!(transaction.all_remote_events().0.len(), 4);
1453 assert_eq!(transaction.len(), 4);
1454
1455 transaction.clear();
1457
1458 assert!(transaction.all_remote_events().0.is_empty());
1459 assert!(transaction.is_empty());
1460 }
1461
1462 #[test]
1463 fn test_transaction_for_each() {
1464 let mut items = ObservableItems::new();
1465
1466 let mut transaction = items.transaction();
1468 transaction.push_back(item("$ev0"), Some(0));
1469 transaction.push_back(item("$ev1"), Some(1));
1470 transaction.push_back(item("$ev2"), Some(2));
1471
1472 let mut nth = 0;
1473
1474 transaction.for_each(|entry| {
1476 match nth {
1477 0 => {
1478 assert_event_id!(entry, "$ev0");
1479 }
1480 1 => {
1481 assert_event_id!(entry, "$ev1");
1482 }
1483 2 => {
1484 assert_event_id!(entry, "$ev2");
1485 }
1486 _ => unreachable!(),
1487 }
1488
1489 nth += 1;
1490 });
1491 }
1492
1493 #[test]
1494 fn test_transaction_for_each_remove() {
1495 let mut items = ObservableItems::new();
1496
1497 let mut transaction = items.transaction();
1499
1500 transaction.push_back_remote_event(event_meta("$ev0"));
1501 transaction.push_back(item("$ev0"), Some(0));
1502
1503 transaction.push_back_remote_event(event_meta("$ev1"));
1504 transaction.push_back(item("$ev1"), Some(1));
1505
1506 transaction.push_back_remote_event(event_meta("$ev2"));
1507 transaction.push_back(item("$ev2"), Some(2));
1508
1509 assert_mapping! {
1510 on transaction:
1511
1512 | event_id | event_index | timeline_item_index |
1513 |----------|-------------|---------------------|
1514 | "$ev0" | 0 | 0 |
1515 | "$ev1" | 1 | 1 |
1516 | "$ev2" | 2 | 2 |
1517 }
1518
1519 transaction.for_each(|entry| {
1521 if entry.as_event().unwrap().event_id().unwrap().as_str() == "$ev1" {
1522 ObservableItemsTransactionEntry::remove(entry);
1523 }
1524 });
1525
1526 assert_mapping! {
1527 on transaction:
1528
1529 | event_id | event_index | timeline_item_index |
1530 |----------|-------------|---------------------|
1531 | "$ev0" | 0 | 0 |
1532 | "$ev2" | 2 | 1 | }
1534
1535 assert_eq!(transaction.all_remote_events().0.len(), 3);
1536 assert_eq!(transaction.len(), 2);
1537 }
1538
1539 #[test]
1540 fn test_transaction_push_local() {
1541 let mut items = ObservableItems::new();
1542
1543 let mut transaction = items.transaction();
1544
1545 transaction.push_back(item("$ev0"), None);
1547
1548 transaction.push_local(local_item("t0"));
1550
1551 transaction.push_local(local_item("t1"));
1553
1554 transaction.commit();
1555
1556 let mut entries = items.entries();
1557
1558 assert_matches!(entries.next(), Some(entry) => {
1559 assert_event_id!(entry, "$ev0");
1560 });
1561 assert_matches!(entries.next(), Some(entry) => {
1562 assert_transaction_id!(entry, "t0");
1563 });
1564 assert_matches!(entries.next(), Some(entry) => {
1565 assert_transaction_id!(entry, "t1");
1566 });
1567 assert_matches!(entries.next(), None);
1568 }
1569
1570 #[test]
1571 #[should_panic]
1572 fn test_transaction_push_local_panic_not_a_local() {
1573 let mut items = ObservableItems::new();
1574 let mut transaction = items.transaction();
1575 transaction.push_local(item("$ev0"));
1576 }
1577
1578 #[test]
1579 fn test_transaction_push_date_divider() {
1580 let mut items = ObservableItems::new();
1581 let mut stream = items.subscribe().into_stream();
1582
1583 let mut transaction = items.transaction();
1584
1585 transaction.push_date_divider(
1586 0,
1587 TimelineItem::new(
1588 TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(
1589 MilliSecondsSinceUnixEpoch(uint!(10)),
1590 )),
1591 TimelineUniqueId("__foo".to_owned()),
1592 ),
1593 );
1594 transaction.push_date_divider(
1595 0,
1596 TimelineItem::new(
1597 TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(
1598 MilliSecondsSinceUnixEpoch(uint!(20)),
1599 )),
1600 TimelineUniqueId("__bar".to_owned()),
1601 ),
1602 );
1603 transaction.push_date_divider(
1604 1,
1605 TimelineItem::new(
1606 TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(
1607 MilliSecondsSinceUnixEpoch(uint!(30)),
1608 )),
1609 TimelineUniqueId("__baz".to_owned()),
1610 ),
1611 );
1612 transaction.commit();
1613
1614 assert_next_matches!(stream, VectorDiff::PushBack { value: timeline_item } => {
1615 assert_matches!(timeline_item.as_virtual(), Some(VirtualTimelineItem::DateDivider(ms)) => {
1616 assert_eq!(u64::from(ms.0), 10);
1617 });
1618 });
1619 assert_next_matches!(stream, VectorDiff::PushFront { value: timeline_item } => {
1620 assert_matches!(timeline_item.as_virtual(), Some(VirtualTimelineItem::DateDivider(ms)) => {
1621 assert_eq!(u64::from(ms.0), 20);
1622 });
1623 });
1624 assert_next_matches!(stream, VectorDiff::Insert { index: 1, value: timeline_item } => {
1625 assert_matches!(timeline_item.as_virtual(), Some(VirtualTimelineItem::DateDivider(ms)) => {
1626 assert_eq!(u64::from(ms.0), 30);
1627 });
1628 });
1629 assert_pending!(stream);
1630 }
1631
1632 #[test]
1633 #[should_panic]
1634 fn test_transaction_push_date_divider_panic_not_a_date_divider() {
1635 let mut items = ObservableItems::new();
1636 let mut transaction = items.transaction();
1637
1638 transaction.push_date_divider(0, item("$ev0"));
1639 }
1640
1641 #[test]
1642 #[should_panic]
1643 fn test_transaction_push_date_divider_panic_not_in_remotes_region() {
1644 let mut items = ObservableItems::new();
1645 let mut transaction = items.transaction();
1646
1647 transaction.push_timeline_start_if_missing(TimelineItem::new(
1648 VirtualTimelineItem::TimelineStart,
1649 TimelineUniqueId("__id_start".to_owned()),
1650 ));
1651 transaction.push_date_divider(
1652 0,
1653 TimelineItem::new(
1654 VirtualTimelineItem::DateDivider(MilliSecondsSinceUnixEpoch(uint!(10))),
1655 TimelineUniqueId("__date_divider".to_owned()),
1656 ),
1657 );
1658 }
1659
1660 #[test]
1661 fn test_transaction_push_timeline_start_if_missing() {
1662 let mut items = ObservableItems::new();
1663
1664 let mut transaction = items.transaction();
1665
1666 transaction.push_back(item("$ev0"), None);
1668
1669 transaction.push_timeline_start_if_missing(TimelineItem::new(
1671 VirtualTimelineItem::TimelineStart,
1672 TimelineUniqueId("__id_start".to_owned()),
1673 ));
1674
1675 transaction.push_back(item("$ev1"), None);
1677
1678 transaction.push_timeline_start_if_missing(TimelineItem::new(
1680 VirtualTimelineItem::TimelineStart,
1681 TimelineUniqueId("__id_start_again".to_owned()),
1682 ));
1683
1684 transaction.commit();
1685
1686 let mut entries = items.entries();
1687
1688 assert_matches!(entries.next(), Some(entry) => {
1689 assert!(entry.is_timeline_start());
1690 });
1691 assert_matches!(entries.next(), Some(entry) => {
1692 assert_event_id!(entry, "$ev0");
1693 });
1694 assert_matches!(entries.next(), Some(entry) => {
1695 assert_event_id!(entry, "$ev1");
1696 });
1697 assert_matches!(entries.next(), None);
1698 }
1699
1700 #[test]
1701 fn test_transaction_iter_all_regions() {
1702 let mut items = ObservableItems::new();
1703
1704 let mut transaction = items.transaction();
1705 transaction.push_timeline_start_if_missing(TimelineItem::new(
1706 VirtualTimelineItem::TimelineStart,
1707 TimelineUniqueId("__start".to_owned()),
1708 ));
1709 transaction.push_back(item("$ev0"), None);
1710 transaction.push_back(item("$ev1"), None);
1711 transaction.push_back(item("$ev2"), None);
1712 transaction.push_local(local_item("t0"));
1713 transaction.push_local(local_item("t1"));
1714 transaction.push_local(local_item("t2"));
1715
1716 let mut iter = transaction.iter_all_regions();
1718 assert_matches!(iter.next(), Some((0, item)) => {
1719 assert!(item.is_timeline_start());
1720 });
1721 assert_matches!(iter.next(), Some((1, item)) => {
1722 assert_event_id!(item, "$ev0");
1723 });
1724 assert_matches!(iter.next(), Some((2, item)) => {
1725 assert_event_id!(item, "$ev1");
1726 });
1727 assert_matches!(iter.next(), Some((3, item)) => {
1728 assert_event_id!(item, "$ev2");
1729 });
1730 assert_matches!(iter.next(), Some((4, item)) => {
1731 assert_transaction_id!(item, "t0");
1732 });
1733 assert_matches!(iter.next(), Some((5, item)) => {
1734 assert_transaction_id!(item, "t1");
1735 });
1736 assert_matches!(iter.next(), Some((6, item)) => {
1737 assert_transaction_id!(item, "t2");
1738 });
1739 assert!(iter.next().is_none());
1740 }
1741
1742 #[test]
1743 fn test_transaction_iter_remotes_regions() {
1744 let mut items = ObservableItems::new();
1745
1746 let mut transaction = items.transaction();
1747 transaction.push_timeline_start_if_missing(TimelineItem::new(
1748 VirtualTimelineItem::TimelineStart,
1749 TimelineUniqueId("__start".to_owned()),
1750 ));
1751 transaction.push_back(item("$ev0"), None);
1752 transaction.push_back(item("$ev1"), None);
1753 transaction.push_back(item("$ev2"), None);
1754 transaction.push_local(local_item("t0"));
1755 transaction.push_local(local_item("t1"));
1756 transaction.push_local(local_item("t2"));
1757
1758 let mut iter = transaction.iter_remotes_region();
1760 assert_matches!(iter.next(), Some((1, item)) => {
1761 assert_event_id!(item, "$ev0");
1762 });
1763 assert_matches!(iter.next(), Some((2, item)) => {
1764 assert_event_id!(item, "$ev1");
1765 });
1766 assert_matches!(iter.next(), Some((3, item)) => {
1767 assert_event_id!(item, "$ev2");
1768 });
1769 assert!(iter.next().is_none());
1770 }
1771
1772 #[test]
1773 fn test_transaction_iter_remotes_regions_with_no_start_region() {
1774 let mut items = ObservableItems::new();
1775
1776 let mut transaction = items.transaction();
1777 transaction.push_back(item("$ev0"), None);
1778 transaction.push_back(item("$ev1"), None);
1779 transaction.push_back(item("$ev2"), None);
1780 transaction.push_local(local_item("t0"));
1781 transaction.push_local(local_item("t1"));
1782 transaction.push_local(local_item("t2"));
1783
1784 let mut iter = transaction.iter_remotes_region();
1786 assert_matches!(iter.next(), Some((0, item)) => {
1787 assert_event_id!(item, "$ev0");
1788 });
1789 assert_matches!(iter.next(), Some((1, item)) => {
1790 assert_event_id!(item, "$ev1");
1791 });
1792 assert_matches!(iter.next(), Some((2, item)) => {
1793 assert_event_id!(item, "$ev2");
1794 });
1795 assert!(iter.next().is_none());
1796 }
1797
1798 #[test]
1799 fn test_transaction_iter_remotes_regions_with_no_locals_region() {
1800 let mut items = ObservableItems::new();
1801
1802 let mut transaction = items.transaction();
1803 transaction.push_back(item("$ev0"), None);
1804 transaction.push_back(item("$ev1"), None);
1805 transaction.push_back(item("$ev2"), None);
1806
1807 let mut iter = transaction.iter_remotes_region();
1809 assert_matches!(iter.next(), Some((0, item)) => {
1810 assert_event_id!(item, "$ev0");
1811 });
1812 assert_matches!(iter.next(), Some((1, item)) => {
1813 assert_event_id!(item, "$ev1");
1814 });
1815 assert_matches!(iter.next(), Some((2, item)) => {
1816 assert_event_id!(item, "$ev2");
1817 });
1818 assert!(iter.next().is_none());
1819 }
1820
1821 #[test]
1822 fn test_transaction_iter_locals_region() {
1823 let mut items = ObservableItems::new();
1824
1825 let mut transaction = items.transaction();
1826 transaction.push_timeline_start_if_missing(TimelineItem::new(
1827 VirtualTimelineItem::TimelineStart,
1828 TimelineUniqueId("__start".to_owned()),
1829 ));
1830 transaction.push_back(item("$ev0"), None);
1831 transaction.push_back(item("$ev1"), None);
1832 transaction.push_back(item("$ev2"), None);
1833 transaction.push_local(local_item("t0"));
1834 transaction.push_local(local_item("t1"));
1835 transaction.push_local(local_item("t2"));
1836
1837 let mut iter = transaction.iter_locals_region();
1839 assert_matches!(iter.next(), Some((4, item)) => {
1840 assert_transaction_id!(item, "t0");
1841 });
1842 assert_matches!(iter.next(), Some((5, item)) => {
1843 assert_transaction_id!(item, "t1");
1844 });
1845 assert_matches!(iter.next(), Some((6, item)) => {
1846 assert_transaction_id!(item, "t2");
1847 });
1848 assert!(iter.next().is_none());
1849 }
1850}
1851
1852#[derive(Clone, Debug, Default)]
1858pub struct AllRemoteEvents(VecDeque<EventMeta>);
1859
1860impl AllRemoteEvents {
1861 pub fn get(&self, event_index: usize) -> Option<&EventMeta> {
1863 self.0.get(event_index)
1864 }
1865
1866 pub fn iter(&self) -> Iter<'_, EventMeta> {
1868 self.0.iter()
1869 }
1870
1871 pub fn range<R>(&self, range: R) -> Iter<'_, EventMeta>
1874 where
1875 R: RangeBounds<usize>,
1876 {
1877 self.0.range(range)
1878 }
1879
1880 fn clear(&mut self) {
1882 self.0.clear();
1883 }
1884
1885 fn push_front(&mut self, event_meta: EventMeta) {
1887 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1890 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1891 }
1892
1893 self.0.push_front(event_meta)
1895 }
1896
1897 fn push_back(&mut self, event_meta: EventMeta) {
1899 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1902 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1903 }
1904
1905 self.0.push_back(event_meta)
1907 }
1908
1909 fn insert(&mut self, event_index: usize, event_meta: EventMeta) {
1911 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1914 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1915 }
1916
1917 self.0.insert(event_index, event_meta)
1919 }
1920
1921 fn remove(&mut self, event_index: usize) -> Option<EventMeta> {
1923 let event_meta = self.0.remove(event_index)?;
1925
1926 if let Some(removed_timeline_item_index) = event_meta.timeline_item_index {
1929 self.decrement_all_timeline_item_index_after(removed_timeline_item_index);
1930 }
1931
1932 Some(event_meta)
1933 }
1934
1935 #[cfg(test)]
1937 pub fn last(&self) -> Option<&EventMeta> {
1938 self.0.back()
1939 }
1940
1941 pub fn last_index(&self) -> Option<usize> {
1943 self.0.len().checked_sub(1)
1944 }
1945
1946 pub fn get_by_event_id_mut(&mut self, event_id: &EventId) -> Option<&mut EventMeta> {
1948 self.0.iter_mut().rev().find(|event_meta| event_meta.event_id == event_id)
1949 }
1950
1951 pub fn get_by_event_id(&self, event_id: &EventId) -> Option<&EventMeta> {
1953 self.0.iter().rev().find(|event_meta| event_meta.event_id == event_id)
1954 }
1955
1956 pub fn position_by_event_id(&self, event_id: &EventId) -> Option<usize> {
1958 self.0
1961 .iter()
1962 .enumerate()
1963 .rev()
1964 .find_map(|(i, event_meta)| (event_meta.event_id == event_id).then_some(i))
1965 }
1966
1967 fn increment_all_timeline_item_index_after(&mut self, new_timeline_item_index: usize) {
1970 for event_meta in self.0.iter_mut().rev() {
1978 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
1979 if *timeline_item_index >= new_timeline_item_index {
1980 *timeline_item_index += 1;
1981 } else {
1982 break;
1984 }
1985 }
1986 }
1987 }
1988
1989 fn decrement_all_timeline_item_index_after(&mut self, removed_timeline_item_index: usize) {
1992 for event_meta in self.0.iter_mut().rev() {
2000 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
2001 if *timeline_item_index > removed_timeline_item_index {
2002 *timeline_item_index -= 1;
2003 } else {
2004 break;
2006 }
2007 }
2008 }
2009 }
2010
2011 fn timeline_item_has_been_inserted_at(
2016 &mut self,
2017 new_timeline_item_index: usize,
2018 event_index: Option<usize>,
2019 ) {
2020 self.increment_all_timeline_item_index_after(new_timeline_item_index);
2021
2022 if let Some(event_index) = event_index
2023 && let Some(event_meta) = self.0.get_mut(event_index)
2024 {
2025 event_meta.timeline_item_index = Some(new_timeline_item_index);
2026 }
2027 }
2028
2029 fn timeline_item_has_been_removed_at(&mut self, timeline_item_index_to_remove: usize) {
2032 for event_meta in self.0.iter_mut() {
2033 let mut remove_timeline_item_index = false;
2034
2035 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
2038 match (*timeline_item_index).cmp(&timeline_item_index_to_remove) {
2039 Ordering::Equal => {
2040 remove_timeline_item_index = true;
2041 }
2042
2043 Ordering::Greater => {
2044 *timeline_item_index -= 1;
2045 }
2046
2047 Ordering::Less => {}
2048 }
2049 }
2050
2051 if remove_timeline_item_index {
2054 event_meta.timeline_item_index = None;
2055 }
2056 }
2057 }
2058}
2059
2060#[cfg(test)]
2061mod all_remote_events_tests {
2062 use assert_matches::assert_matches;
2063 use ruma::event_id;
2064
2065 use super::{AllRemoteEvents, EventMeta};
2066
2067 fn event_meta(event_id: &str, timeline_item_index: Option<usize>) -> EventMeta {
2068 EventMeta {
2069 event_id: event_id.parse().unwrap(),
2070 thread_root_id: None,
2071 timeline_item_index,
2072 visible: false,
2073 can_show_read_receipts: false,
2074 }
2075 }
2076
2077 macro_rules! assert_events {
2078 ( $events:ident, [ $( ( $event_id:literal, $timeline_item_index:expr ) ),* $(,)? ] ) => {
2079 let mut iter = $events .iter();
2080
2081 $(
2082 assert_matches!(iter.next(), Some(EventMeta { event_id, timeline_item_index, .. }) => {
2083 assert_eq!(event_id.as_str(), $event_id );
2084 assert_eq!(*timeline_item_index, $timeline_item_index );
2085 });
2086 )*
2087
2088 assert!(iter.next().is_none(), "Not all events have been asserted");
2089 }
2090 }
2091
2092 #[test]
2093 fn test_range() {
2094 let mut events = AllRemoteEvents::default();
2095
2096 events.push_back(event_meta("$ev0", None));
2098 events.push_back(event_meta("$ev1", None));
2099 events.push_back(event_meta("$ev2", None));
2100
2101 assert_eq!(events.iter().count(), 3);
2102
2103 assert_eq!(events.range(..).count(), 3);
2105 assert_eq!(events.range(1..).count(), 2);
2106 assert_eq!(events.range(0..=1).count(), 2);
2107
2108 let mut some_events = events.range(1..);
2110
2111 assert_matches!(some_events.next(), Some(EventMeta { event_id, .. }) => {
2112 assert_eq!(event_id.as_str(), "$ev1");
2113 });
2114 assert_matches!(some_events.next(), Some(EventMeta { event_id, .. }) => {
2115 assert_eq!(event_id.as_str(), "$ev2");
2116 });
2117 assert!(some_events.next().is_none());
2118 }
2119
2120 #[test]
2121 fn test_clear() {
2122 let mut events = AllRemoteEvents::default();
2123
2124 events.push_back(event_meta("$ev0", None));
2126 events.push_back(event_meta("$ev1", None));
2127 events.push_back(event_meta("$ev2", None));
2128
2129 assert_eq!(events.iter().count(), 3);
2130
2131 events.clear();
2133
2134 assert_eq!(events.iter().count(), 0);
2135 }
2136
2137 #[test]
2138 fn test_push_front() {
2139 let mut events = AllRemoteEvents::default();
2140
2141 events.push_front(event_meta("$ev0", Some(1)));
2143
2144 events.push_front(event_meta("$ev1", None));
2146
2147 events.push_front(event_meta("$ev2", Some(0)));
2149
2150 events.push_front(event_meta("$ev3", Some(0)));
2152
2153 assert_events!(
2154 events,
2155 [
2156 ("$ev3", Some(0)),
2158 ("$ev2", Some(1)),
2160 ("$ev1", None),
2162 ("$ev0", Some(3)),
2164 ]
2165 );
2166 }
2167
2168 #[test]
2169 fn test_push_back() {
2170 let mut events = AllRemoteEvents::default();
2171
2172 events.push_back(event_meta("$ev0", Some(0)));
2174
2175 events.push_back(event_meta("$ev1", None));
2177
2178 events.push_back(event_meta("$ev2", Some(1)));
2180
2181 events.push_back(event_meta("$ev3", Some(1)));
2185
2186 assert_events!(
2187 events,
2188 [
2189 ("$ev0", Some(0)),
2191 ("$ev1", None),
2193 ("$ev2", Some(2)),
2195 ("$ev3", Some(1)),
2197 ]
2198 );
2199 }
2200
2201 #[test]
2202 fn test_insert() {
2203 let mut events = AllRemoteEvents::default();
2204
2205 events.insert(0, event_meta("$ev0", Some(0)));
2207
2208 events.insert(1, event_meta("$ev1", None));
2210
2211 events.insert(2, event_meta("$ev2", Some(1)));
2213
2214 events.insert(0, event_meta("$ev3", Some(0)));
2216
2217 assert_events!(
2218 events,
2219 [
2220 ("$ev3", Some(0)),
2222 ("$ev0", Some(1)),
2224 ("$ev1", None),
2226 ("$ev2", Some(2)),
2228 ]
2229 );
2230 }
2231
2232 #[test]
2233 fn test_remove() {
2234 let mut events = AllRemoteEvents::default();
2235
2236 events.push_back(event_meta("$ev0", Some(0)));
2238 events.push_back(event_meta("$ev1", Some(1)));
2239 events.push_back(event_meta("$ev2", None));
2240 events.push_back(event_meta("$ev3", Some(2)));
2241
2242 assert_events!(
2244 events,
2245 [("$ev0", Some(0)), ("$ev1", Some(1)), ("$ev2", None), ("$ev3", Some(2))]
2246 );
2247
2248 events.remove(2); events.remove(1); assert_events!(
2253 events,
2254 [
2255 ("$ev0", Some(0)),
2256 ("$ev3", Some(1)),
2258 ]
2259 );
2260 }
2261
2262 #[test]
2263 fn test_last() {
2264 let mut events = AllRemoteEvents::default();
2265
2266 assert!(events.last().is_none());
2267 assert!(events.last_index().is_none());
2268
2269 events.push_back(event_meta("$ev0", Some(0)));
2271 events.push_back(event_meta("$ev1", Some(1)));
2272
2273 assert_matches!(events.last(), Some(EventMeta { event_id, .. }) => {
2274 assert_eq!(event_id.as_str(), "$ev1");
2275 });
2276 assert_eq!(events.last_index(), Some(1));
2277 }
2278
2279 #[test]
2280 fn test_get_by_event_by_mut() {
2281 let mut events = AllRemoteEvents::default();
2282
2283 events.push_back(event_meta("$ev0", Some(0)));
2285 events.push_back(event_meta("$ev1", Some(1)));
2286
2287 assert!(events.get_by_event_id_mut(event_id!("$ev0")).is_some());
2288 assert!(events.get_by_event_id_mut(event_id!("$ev42")).is_none());
2289 }
2290
2291 #[test]
2292 fn test_timeline_item_has_been_inserted_at() {
2293 let mut events = AllRemoteEvents::default();
2294
2295 events.push_back(event_meta("$ev0", Some(0)));
2297 events.push_back(event_meta("$ev1", Some(1)));
2298 events.push_back(event_meta("$ev2", None));
2299 events.push_back(event_meta("$ev3", None));
2300 events.push_back(event_meta("$ev4", Some(2)));
2301 events.push_back(event_meta("$ev5", Some(3)));
2302 events.push_back(event_meta("$ev6", None));
2303
2304 events.timeline_item_has_been_inserted_at(2, None);
2306
2307 assert_events!(
2308 events,
2309 [
2310 ("$ev0", Some(0)),
2311 ("$ev1", Some(1)),
2312 ("$ev2", None),
2313 ("$ev3", None),
2314 ("$ev4", Some(3)),
2316 ("$ev5", Some(4)),
2318 ("$ev6", None),
2319 ]
2320 );
2321
2322 events.timeline_item_has_been_inserted_at(5, Some(6));
2324
2325 assert_events!(
2326 events,
2327 [
2328 ("$ev0", Some(0)),
2329 ("$ev1", Some(1)),
2330 ("$ev2", None),
2331 ("$ev3", None),
2332 ("$ev4", Some(3)),
2333 ("$ev5", Some(4)),
2334 ("$ev6", Some(5)),
2336 ]
2337 );
2338 }
2339
2340 #[test]
2341 fn test_timeline_item_has_been_removed_at() {
2342 let mut events = AllRemoteEvents::default();
2343
2344 events.push_back(event_meta("$ev0", Some(0)));
2346 events.push_back(event_meta("$ev1", Some(1)));
2347 events.push_back(event_meta("$ev2", None));
2348 events.push_back(event_meta("$ev3", None));
2349 events.push_back(event_meta("$ev4", Some(3)));
2350 events.push_back(event_meta("$ev5", Some(4)));
2351 events.push_back(event_meta("$ev6", None));
2352
2353 events.timeline_item_has_been_removed_at(2);
2355
2356 assert_events!(
2357 events,
2358 [
2359 ("$ev0", Some(0)),
2360 ("$ev1", Some(1)),
2361 ("$ev2", None),
2362 ("$ev3", None),
2363 ("$ev4", Some(2)),
2365 ("$ev5", Some(3)),
2367 ("$ev6", None),
2368 ]
2369 );
2370
2371 events.timeline_item_has_been_removed_at(2);
2373
2374 assert_events!(
2375 events,
2376 [
2377 ("$ev0", Some(0)),
2378 ("$ev1", Some(1)),
2379 ("$ev2", None),
2380 ("$ev3", None),
2381 ("$ev4", None),
2383 ("$ev5", Some(2)),
2385 ("$ev6", None),
2386 ]
2387 );
2388
2389 events.timeline_item_has_been_removed_at(0);
2391
2392 assert_events!(
2393 events,
2394 [
2395 ("$ev0", None),
2397 ("$ev1", Some(0)),
2399 ("$ev2", None),
2400 ("$ev3", None),
2401 ("$ev4", None),
2402 ("$ev5", Some(1)),
2404 ("$ev6", None),
2405 ]
2406 );
2407 }
2408}