1use std::{
16 cmp::Ordering,
17 collections::{vec_deque::Iter, VecDeque},
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::{metadata::EventMeta, TimelineItem};
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()) {
454 1
455 } else {
456 0
457 }
458 }
459
460 pub fn iter_remotes_region(&self) -> ObservableItemsTransactionIter<'_> {
462 ObservableItemsTransactionIterBuilder::new(&self.items).with_remotes().build()
463 }
464
465 pub fn iter_remotes_and_locals_regions(&self) -> ObservableItemsTransactionIter<'_> {
467 ObservableItemsTransactionIterBuilder::new(&self.items).with_remotes().with_locals().build()
468 }
469
470 pub fn iter_locals_region(&self) -> ObservableItemsTransactionIter<'_> {
472 ObservableItemsTransactionIterBuilder::new(&self.items).with_locals().build()
473 }
474
475 pub fn iter_all_regions(&self) -> ObservableItemsTransactionIter<'_> {
477 ObservableItemsTransactionIterBuilder::new(&self.items)
478 .with_start()
479 .with_remotes()
480 .with_locals()
481 .build()
482 }
483
484 #[allow(unused)] #[deprecated = "This method is now aliased to `Self::iter_all_regions`"]
492 pub fn iter(&self) -> ObservableItemsTransactionIter<'_> {
493 self.iter_all_regions()
494 }
495
496 pub fn commit(self) {
499 self.items.commit()
500 }
501}
502
503bitflags! {
504 struct Regions: u8 {
505 const START = 0b0000_0001;
509
510 const REMOTES = 0b0000_0010;
517
518 const LOCALS = 0b0000_0100;
524 }
525}
526
527struct ObservableItemsTransactionIterBuilder<'e> {
529 items: &'e ObservableVectorTransaction<'e, Arc<TimelineItem>>,
531
532 regions: Regions,
534}
535
536impl<'e> ObservableItemsTransactionIterBuilder<'e> {
537 fn new(items: &'e ObservableVectorTransaction<'e, Arc<TimelineItem>>) -> Self {
539 Self { items, regions: Regions::empty() }
540 }
541
542 fn with_start(mut self) -> Self {
544 self.regions.insert(Regions::START);
545 self
546 }
547
548 fn with_remotes(mut self) -> Self {
550 self.regions.insert(Regions::REMOTES);
551 self
552 }
553
554 fn with_locals(mut self) -> Self {
556 self.regions.insert(Regions::LOCALS);
557 self
558 }
559
560 #[allow(clippy::iter_skip_zero)]
562 fn build(self) -> ObservableItemsTransactionIter<'e> {
563 let size_of_start_region = if matches!(
565 self.items.get(0),
566 Some(first_timeline_item) if first_timeline_item.is_timeline_start()
567 ) {
568 1
569 } else {
570 0
571 };
572
573 let size_of_locals_region = self
575 .items
576 .deref()
577 .iter()
578 .rev()
579 .take_while(|timeline_item| timeline_item.is_local_echo())
580 .count();
581
582 let size_of_remotes_region =
584 self.items.len() - size_of_start_region - size_of_locals_region;
585
586 let with_start = self.regions.contains(Regions::START);
587 let with_remotes = self.regions.contains(Regions::REMOTES);
588 let with_locals = self.regions.contains(Regions::LOCALS);
589
590 let iter = self.items.deref().iter().enumerate();
592 let inner = match (with_start, with_remotes, with_locals) {
593 (false, false, false) => iter.skip(0).take(0),
595
596 (true, false, false) => iter.skip(0).take(size_of_start_region),
598
599 (false, true, false) => iter.skip(size_of_start_region).take(size_of_remotes_region),
601
602 (true, true, false) => iter.skip(0).take(size_of_start_region + size_of_remotes_region),
604
605 (false, false, true) => {
607 iter.skip(size_of_start_region + size_of_remotes_region).take(size_of_locals_region)
608 }
609
610 (true, false, true) => unimplemented!(
615 "Iterating over the start and the locals regions is not implemented yet"
616 ),
617
618 (false, true, true) => {
620 iter.skip(size_of_start_region).take(size_of_remotes_region + size_of_locals_region)
621 }
622
623 (true, true, true) => iter
625 .skip(0)
626 .take(size_of_start_region + size_of_remotes_region + size_of_locals_region),
627 };
628
629 ObservableItemsTransactionIter { inner }
630 }
631}
632
633pub(crate) struct ObservableItemsTransactionIter<'observable_items_transaction> {
635 #[allow(clippy::type_complexity)]
636 inner: Take<
637 Skip<
638 Enumerate<
639 imbl::vector::Iter<
640 'observable_items_transaction,
641 Arc<TimelineItem>,
642 imbl::shared_ptr::DefaultSharedPtr,
643 >,
644 >,
645 >,
646 >,
647}
648
649impl<'e> Iterator for ObservableItemsTransactionIter<'e> {
650 type Item = (usize, &'e Arc<TimelineItem>);
651
652 fn next(&mut self) -> Option<Self::Item> {
653 self.inner.next()
654 }
655}
656
657impl ExactSizeIterator for ObservableItemsTransactionIter<'_> {
658 fn len(&self) -> usize {
659 self.inner.len()
660 }
661}
662
663impl DoubleEndedIterator for ObservableItemsTransactionIter<'_> {
664 fn next_back(&mut self) -> Option<Self::Item> {
665 self.inner.next_back()
666 }
667}
668
669impl Deref for ObservableItemsTransaction<'_> {
675 type Target = Vector<Arc<TimelineItem>>;
676
677 fn deref(&self) -> &Self::Target {
678 &self.items
679 }
680}
681
682pub struct ObservableItemsTransactionEntry<'observable_transaction_items, 'observable_items> {
684 entry: ObservableVectorTransactionEntry<
685 'observable_transaction_items,
686 'observable_items,
687 Arc<TimelineItem>,
688 >,
689 all_remote_events: &'observable_transaction_items mut AllRemoteEvents,
690}
691
692impl ObservableItemsTransactionEntry<'_, '_> {
693 pub fn remove(this: Self) {
695 let entry_index = ObservableVectorTransactionEntry::index(&this.entry);
696
697 ObservableVectorTransactionEntry::remove(this.entry);
698 this.all_remote_events.timeline_item_has_been_removed_at(entry_index);
699 }
700}
701
702impl Deref for ObservableItemsTransactionEntry<'_, '_> {
708 type Target = Arc<TimelineItem>;
709
710 fn deref(&self) -> &Self::Target {
711 &self.entry
712 }
713}
714
715#[cfg(test)]
716mod observable_items_tests {
717 use std::ops::Not;
718
719 use assert_matches::assert_matches;
720 use eyeball_im::VectorDiff;
721 use ruma::{
722 events::room::message::{MessageType, TextMessageEventContent},
723 owned_user_id, uint, MilliSecondsSinceUnixEpoch,
724 };
725 use stream_assert::{assert_next_matches, assert_pending};
726
727 use super::*;
728 use crate::timeline::{
729 controller::{EventTimelineItemKind, RemoteEventOrigin},
730 event_item::{LocalEventTimelineItem, RemoteEventTimelineItem},
731 EventSendState, EventTimelineItem, Message, MsgLikeContent, MsgLikeKind, TimelineDetails,
732 TimelineItemContent, TimelineItemKind, TimelineUniqueId, VirtualTimelineItem,
733 };
734
735 fn item(event_id: &str) -> Arc<TimelineItem> {
736 TimelineItem::new(
737 EventTimelineItem::new(
738 owned_user_id!("@ivan:mnt.io"),
739 TimelineDetails::Unavailable,
740 MilliSecondsSinceUnixEpoch(0u32.into()),
741 TimelineItemContent::MsgLike(MsgLikeContent {
742 kind: MsgLikeKind::Message(Message {
743 msgtype: MessageType::Text(TextMessageEventContent::plain("hello")),
744 edited: false,
745 mentions: None,
746 }),
747 reactions: Default::default(),
748 thread_root: None,
749 in_reply_to: None,
750 thread_summary: None,
751 }),
752 EventTimelineItemKind::Remote(RemoteEventTimelineItem {
753 event_id: event_id.parse().unwrap(),
754 transaction_id: None,
755 read_receipts: Default::default(),
756 is_own: false,
757 is_highlighted: false,
758 encryption_info: None,
759 original_json: None,
760 latest_edit_json: None,
761 origin: RemoteEventOrigin::Sync,
762 }),
763 false,
764 ),
765 TimelineUniqueId(format!("__eid_{event_id}")),
766 )
767 }
768
769 fn local_item(transaction_id: &str) -> Arc<TimelineItem> {
770 TimelineItem::new(
771 EventTimelineItem::new(
772 owned_user_id!("@ivan:mnt.io"),
773 TimelineDetails::Unavailable,
774 MilliSecondsSinceUnixEpoch(0u32.into()),
775 TimelineItemContent::MsgLike(MsgLikeContent {
776 kind: MsgLikeKind::Message(Message {
777 msgtype: MessageType::Text(TextMessageEventContent::plain("hello")),
778 edited: false,
779 mentions: None,
780 }),
781 reactions: Default::default(),
782 thread_root: None,
783 in_reply_to: None,
784 thread_summary: None,
785 }),
786 EventTimelineItemKind::Local(LocalEventTimelineItem {
787 send_state: EventSendState::NotSentYet,
788 transaction_id: transaction_id.into(),
789 send_handle: None,
790 }),
791 false,
792 ),
793 TimelineUniqueId(format!("__tid_{transaction_id}")),
794 )
795 }
796
797 fn read_marker() -> Arc<TimelineItem> {
798 TimelineItem::read_marker()
799 }
800
801 fn event_meta(event_id: &str) -> EventMeta {
802 EventMeta { event_id: event_id.parse().unwrap(), timeline_item_index: None, visible: false }
803 }
804
805 macro_rules! assert_event_id {
806 ( $timeline_item:expr, $event_id:literal $( , $message:expr )? $(,)? ) => {
807 assert_eq!($timeline_item.as_event().unwrap().event_id().unwrap().as_str(), $event_id $( , $message)? );
808 };
809 }
810
811 macro_rules! assert_transaction_id {
812 ( $timeline_item:expr, $transaction_id:literal $( , $message:expr )? $(,)? ) => {
813 assert_eq!($timeline_item.as_event().unwrap().transaction_id().unwrap().as_str(), $transaction_id $( , $message)? );
814 };
815 }
816
817 macro_rules! assert_mapping {
818 ( on $transaction:ident:
819 | event_id | event_index | timeline_item_index |
820 | $( - )+ | $( - )+ | $( - )+ |
821 $(
822 | $event_id:literal | $event_index:literal | $( $timeline_item_index:literal )? |
823 )+
824 ) => {
825 let all_remote_events = $transaction .all_remote_events();
826
827 $(
828 assert_matches!(all_remote_events.0.get( $event_index ), Some(EventMeta { event_id, timeline_item_index, .. }) => {
830 assert_eq!(
832 event_id.as_str(),
833 $event_id ,
834 concat!("event #", $event_index, " should have ID ", $event_id)
835 );
836
837
838 #[allow(unused_variables)]
840 let timeline_item_index_is_expected = false;
841 $(
842 let timeline_item_index_is_expected = true;
843 let _ = $timeline_item_index;
844 )?
845
846 if timeline_item_index_is_expected.not() {
847 assert!(
849 timeline_item_index.is_none(),
850 concat!("event #", $event_index, " with ID ", $event_id, " should NOT map to a timeline item index" )
851 );
852 }
853
854 $(
855 assert_eq!(
857 *timeline_item_index,
858 Some( $timeline_item_index ),
859 concat!("event #", $event_index, " with ID ", $event_id, " should map to timeline item #", $timeline_item_index )
860 );
861
862 assert_matches!( $transaction .get( $timeline_item_index ), Some(timeline_item) => {
864 assert_event_id!(
866 timeline_item,
867 $event_id ,
868 concat!("timeline item #", $timeline_item_index, " should map to event ID ", $event_id )
869 );
870 });
871 )?
872 });
873 )*
874 }
875 }
876
877 #[test]
878 fn test_is_empty() {
879 let mut items = ObservableItems::new();
880
881 assert!(items.is_empty());
882
883 let mut transaction = items.transaction();
885 transaction.push_back(item("$ev0"), Some(0));
886 transaction.commit();
887
888 assert!(items.is_empty().not());
889 }
890
891 #[test]
892 fn test_subscribe() {
893 let mut items = ObservableItems::new();
894 let mut subscriber = items.subscribe().into_stream();
895
896 let mut transaction = items.transaction();
898 transaction.push_back(item("$ev0"), Some(0));
899 transaction.commit();
900
901 assert_next_matches!(subscriber, VectorDiff::PushBack { value: event } => {
903 assert_event_id!(event, "$ev0");
904 });
905 }
906
907 #[test]
908 fn test_clone_items() {
909 let mut items = ObservableItems::new();
910
911 let mut transaction = items.transaction();
912 transaction.push_back(item("$ev0"), Some(0));
913 transaction.push_back(item("$ev1"), Some(1));
914 transaction.commit();
915
916 let items = items.clone_items();
917 assert_eq!(items.len(), 2);
918 assert_event_id!(items[0], "$ev0");
919 assert_event_id!(items[1], "$ev1");
920 }
921
922 #[test]
923 fn test_replace() {
924 let mut items = ObservableItems::new();
925
926 let mut transaction = items.transaction();
928 transaction.push_back(item("$ev0"), Some(0));
929 transaction.commit();
930
931 items.replace(0, item("$ev1"));
933
934 let items = items.clone_items();
935 assert_eq!(items.len(), 1);
936 assert_event_id!(items[0], "$ev1");
937 }
938
939 #[test]
940 fn test_entries() {
941 let mut items = ObservableItems::new();
942
943 let mut transaction = items.transaction();
945 transaction.push_back(item("$ev0"), Some(0));
946 transaction.push_back(item("$ev1"), Some(1));
947 transaction.push_back(item("$ev2"), Some(2));
948 transaction.commit();
949
950 let mut entries = items.entries();
951
952 assert_matches!(entries.next(), Some(entry) => {
953 assert_event_id!(entry, "$ev0");
954 });
955 assert_matches!(entries.next(), Some(entry) => {
956 assert_event_id!(entry, "$ev1");
957 });
958 assert_matches!(entries.next(), Some(entry) => {
959 assert_event_id!(entry, "$ev2");
960 });
961 assert_matches!(entries.next(), None);
962 }
963
964 #[test]
965 fn test_entry_replace() {
966 let mut items = ObservableItems::new();
967
968 let mut transaction = items.transaction();
970 transaction.push_back(item("$ev0"), Some(0));
971 transaction.commit();
972
973 let mut entries = items.entries();
974
975 assert_matches!(entries.next(), Some(mut entry) => {
977 assert_event_id!(entry, "$ev0");
978 ObservableItemsEntry::replace(&mut entry, item("$ev1"));
979 });
980 assert_matches!(entries.next(), None);
981
982 let mut entries = items.entries();
984
985 assert_matches!(entries.next(), Some(entry) => {
986 assert_event_id!(entry, "$ev1");
987 });
988 assert_matches!(entries.next(), None);
989 }
990
991 #[test]
992 fn test_for_each() {
993 let mut items = ObservableItems::new();
994
995 let mut transaction = items.transaction();
997 transaction.push_back(item("$ev0"), Some(0));
998 transaction.push_back(item("$ev1"), Some(1));
999 transaction.push_back(item("$ev2"), Some(2));
1000 transaction.commit();
1001
1002 let mut nth = 0;
1003
1004 items.for_each(|entry| {
1006 match nth {
1007 0 => {
1008 assert_event_id!(entry, "$ev0");
1009 }
1010 1 => {
1011 assert_event_id!(entry, "$ev1");
1012 }
1013 2 => {
1014 assert_event_id!(entry, "$ev2");
1015 }
1016 _ => unreachable!(),
1017 }
1018
1019 nth += 1;
1020 });
1021 }
1022
1023 #[test]
1024 fn test_transaction_commit() {
1025 let mut items = ObservableItems::new();
1026
1027 let mut transaction = items.transaction();
1029 transaction.push_back(item("$ev0"), Some(0));
1030 drop(transaction);
1031
1032 assert!(items.is_empty());
1033
1034 let mut transaction = items.transaction();
1036 transaction.push_back(item("$ev0"), Some(0));
1037 transaction.commit();
1038
1039 assert!(items.is_empty().not());
1040 }
1041
1042 #[test]
1043 fn test_transaction_get() {
1044 let mut items = ObservableItems::new();
1045
1046 let mut transaction = items.transaction();
1047 transaction.push_back(item("$ev0"), Some(0));
1048
1049 assert_matches!(transaction.get(0), Some(event) => {
1050 assert_event_id!(event, "$ev0");
1051 });
1052 }
1053
1054 #[test]
1055 fn test_transaction_replace() {
1056 let mut items = ObservableItems::new();
1057
1058 let mut transaction = items.transaction();
1059 transaction.push_back(item("$ev0"), Some(0));
1060 transaction.replace(0, item("$ev1"));
1061
1062 assert_matches!(transaction.get(0), Some(event) => {
1063 assert_event_id!(event, "$ev1");
1064 });
1065 }
1066
1067 #[test]
1068 fn test_transaction_insert() {
1069 let mut items = ObservableItems::new();
1070
1071 let mut transaction = items.transaction();
1072
1073 transaction.push_back_remote_event(event_meta("$ev0"));
1075 transaction.insert(0, item("$ev0"), Some(0));
1076
1077 assert_mapping! {
1078 on transaction:
1079
1080 | event_id | event_index | timeline_item_index |
1081 |----------|-------------|---------------------|
1082 | "$ev0" | 0 | 0 | }
1084
1085 transaction.insert(0, read_marker(), None);
1087
1088 assert_mapping! {
1089 on transaction:
1090
1091 | event_id | event_index | timeline_item_index |
1092 |----------|-------------|---------------------|
1093 | "$ev0" | 0 | 1 | }
1095
1096 transaction.push_back_remote_event(event_meta("$ev1"));
1098 transaction.insert(2, item("$ev1"), Some(1));
1099
1100 assert_mapping! {
1101 on transaction:
1102
1103 | event_id | event_index | timeline_item_index |
1104 |----------|-------------|---------------------|
1105 | "$ev0" | 0 | 1 |
1106 | "$ev1" | 1 | 2 | }
1108
1109 transaction.push_back_remote_event(event_meta("$ev2"));
1111
1112 assert_mapping! {
1113 on transaction:
1114
1115 | event_id | event_index | timeline_item_index |
1116 |----------|-------------|---------------------|
1117 | "$ev0" | 0 | 1 |
1118 | "$ev1" | 1 | 2 |
1119 | "$ev2" | 2 | | }
1121
1122 transaction.push_back_remote_event(event_meta("$ev3"));
1124 transaction.insert(3, item("$ev3"), Some(3));
1125
1126 assert_mapping! {
1127 on transaction:
1128
1129 | event_id | event_index | timeline_item_index |
1130 |----------|-------------|---------------------|
1131 | "$ev0" | 0 | 1 |
1132 | "$ev1" | 1 | 2 |
1133 | "$ev2" | 2 | |
1134 | "$ev3" | 3 | 3 | }
1136
1137 transaction.insert(3, item("$ev2"), Some(2));
1140
1141 assert_mapping! {
1142 on transaction:
1143
1144 | event_id | event_index | timeline_item_index |
1145 |----------|-------------|---------------------|
1146 | "$ev0" | 0 | 1 |
1147 | "$ev1" | 1 | 2 |
1148 | "$ev2" | 2 | 3 | | "$ev3" | 3 | 4 | }
1151
1152 transaction.remove(0);
1154 transaction.insert(2, read_marker(), None);
1155
1156 assert_mapping! {
1157 on transaction:
1158
1159 | event_id | event_index | timeline_item_index |
1160 |----------|-------------|---------------------|
1161 | "$ev0" | 0 | 0 | | "$ev1" | 1 | 1 | | "$ev2" | 2 | 3 |
1164 | "$ev3" | 3 | 4 |
1165 }
1166
1167 assert_eq!(transaction.len(), 5);
1168 }
1169
1170 #[test]
1171 fn test_transaction_push_front() {
1172 let mut items = ObservableItems::new();
1173
1174 let mut transaction = items.transaction();
1175
1176 transaction.push_front_remote_event(event_meta("$ev0"));
1178 transaction.push_front(item("$ev0"), Some(0));
1179
1180 assert_mapping! {
1181 on transaction:
1182
1183 | event_id | event_index | timeline_item_index |
1184 |----------|-------------|---------------------|
1185 | "$ev0" | 0 | 0 | }
1187
1188 transaction.push_front(read_marker(), None);
1190
1191 assert_mapping! {
1192 on transaction:
1193
1194 | event_id | event_index | timeline_item_index |
1195 |----------|-------------|---------------------|
1196 | "$ev0" | 0 | 1 | }
1198
1199 transaction.push_front_remote_event(event_meta("$ev1"));
1201 transaction.push_front(item("$ev1"), Some(0));
1202
1203 assert_mapping! {
1204 on transaction:
1205
1206 | event_id | event_index | timeline_item_index |
1207 |----------|-------------|---------------------|
1208 | "$ev1" | 0 | 0 | | "$ev0" | 1 | 2 | }
1211
1212 transaction.push_front_remote_event(event_meta("$ev2"));
1214
1215 assert_mapping! {
1216 on transaction:
1217
1218 | event_id | event_index | timeline_item_index |
1219 |----------|-------------|---------------------|
1220 | "$ev2" | 0 | |
1221 | "$ev1" | 1 | 0 | | "$ev0" | 2 | 2 | }
1224
1225 transaction.push_front_remote_event(event_meta("$ev3"));
1227 transaction.push_front(item("$ev3"), Some(0));
1228
1229 assert_mapping! {
1230 on transaction:
1231
1232 | event_id | event_index | timeline_item_index |
1233 |----------|-------------|---------------------|
1234 | "$ev3" | 0 | 0 | | "$ev2" | 1 | |
1236 | "$ev1" | 2 | 1 | | "$ev0" | 3 | 3 | }
1239
1240 assert_eq!(transaction.len(), 4);
1241 }
1242
1243 #[test]
1244 fn test_transaction_push_back() {
1245 let mut items = ObservableItems::new();
1246
1247 let mut transaction = items.transaction();
1248
1249 transaction.push_back_remote_event(event_meta("$ev0"));
1251 transaction.push_back(item("$ev0"), Some(0));
1252
1253 assert_mapping! {
1254 on transaction:
1255
1256 | event_id | event_index | timeline_item_index |
1257 |----------|-------------|---------------------|
1258 | "$ev0" | 0 | 0 | }
1260
1261 transaction.push_back(read_marker(), None);
1263
1264 assert_mapping! {
1265 on transaction:
1266
1267 | event_id | event_index | timeline_item_index |
1268 |----------|-------------|---------------------|
1269 | "$ev0" | 0 | 0 |
1270 }
1271
1272 transaction.push_back_remote_event(event_meta("$ev1"));
1274 transaction.push_back(item("$ev1"), Some(1));
1275
1276 assert_mapping! {
1277 on transaction:
1278
1279 | event_id | event_index | timeline_item_index |
1280 |----------|-------------|---------------------|
1281 | "$ev0" | 0 | 0 |
1282 | "$ev1" | 1 | 2 | }
1284
1285 transaction.push_back_remote_event(event_meta("$ev2"));
1287
1288 assert_mapping! {
1289 on transaction:
1290
1291 | event_id | event_index | timeline_item_index |
1292 |----------|-------------|---------------------|
1293 | "$ev0" | 0 | 0 |
1294 | "$ev1" | 1 | 2 |
1295 | "$ev2" | 2 | | }
1297
1298 transaction.push_back_remote_event(event_meta("$ev3"));
1300 transaction.push_back(item("$ev3"), Some(3));
1301
1302 assert_mapping! {
1303 on transaction:
1304
1305 | event_id | event_index | timeline_item_index |
1306 |----------|-------------|---------------------|
1307 | "$ev0" | 0 | 0 |
1308 | "$ev1" | 1 | 2 |
1309 | "$ev2" | 2 | |
1310 | "$ev3" | 3 | 3 | }
1312
1313 assert_eq!(transaction.len(), 4);
1314 }
1315
1316 #[test]
1317 fn test_transaction_remove() {
1318 let mut items = ObservableItems::new();
1319
1320 let mut transaction = items.transaction();
1321
1322 transaction.push_back_remote_event(event_meta("$ev0"));
1324 transaction.push_back(item("$ev0"), Some(0));
1325
1326 transaction.push_back(read_marker(), None);
1328
1329 transaction.push_back_remote_event(event_meta("$ev1"));
1331 transaction.push_back(item("$ev1"), Some(1));
1332
1333 transaction.push_back_remote_event(event_meta("$ev2"));
1335
1336 transaction.push_back_remote_event(event_meta("$ev3"));
1338 transaction.push_back(item("$ev3"), Some(3));
1339
1340 assert_mapping! {
1341 on transaction:
1342
1343 | event_id | event_index | timeline_item_index |
1344 |----------|-------------|---------------------|
1345 | "$ev0" | 0 | 0 |
1346 | "$ev1" | 1 | 2 |
1347 | "$ev2" | 2 | |
1348 | "$ev3" | 3 | 3 |
1349 }
1350
1351 transaction.remove(1);
1353
1354 assert_mapping! {
1355 on transaction:
1356
1357 | event_id | event_index | timeline_item_index |
1358 |----------|-------------|---------------------|
1359 | "$ev0" | 0 | 0 |
1360 | "$ev1" | 1 | 1 | | "$ev2" | 2 | |
1362 | "$ev3" | 3 | 2 | }
1364
1365 transaction.remove(1);
1367
1368 assert_mapping! {
1369 on transaction:
1370
1371 | event_id | event_index | timeline_item_index |
1372 |----------|-------------|---------------------|
1373 | "$ev0" | 0 | 0 |
1374 | "$ev1" | 1 | | | "$ev2" | 2 | |
1376 | "$ev3" | 3 | 1 | }
1378
1379 transaction.remove(1);
1381
1382 assert_mapping! {
1383 on transaction:
1384
1385 | event_id | event_index | timeline_item_index |
1386 |----------|-------------|---------------------|
1387 | "$ev0" | 0 | 0 |
1388 | "$ev1" | 1 | |
1389 | "$ev2" | 2 | |
1390 | "$ev3" | 3 | | }
1392
1393 transaction.remove(0);
1395
1396 assert_mapping! {
1397 on transaction:
1398
1399 | event_id | event_index | timeline_item_index |
1400 |----------|-------------|---------------------|
1401 | "$ev0" | 0 | | | "$ev1" | 1 | |
1403 | "$ev2" | 2 | |
1404 | "$ev3" | 3 | |
1405 }
1406
1407 assert!(transaction.is_empty());
1408 }
1409
1410 #[test]
1411 fn test_transaction_clear() {
1412 let mut items = ObservableItems::new();
1413
1414 let mut transaction = items.transaction();
1415
1416 transaction.push_back_remote_event(event_meta("$ev0"));
1418 transaction.push_back(item("$ev0"), Some(0));
1419
1420 transaction.push_back(read_marker(), None);
1422
1423 transaction.push_back_remote_event(event_meta("$ev1"));
1425 transaction.push_back(item("$ev1"), Some(1));
1426
1427 transaction.push_back_remote_event(event_meta("$ev2"));
1429
1430 transaction.push_back_remote_event(event_meta("$ev3"));
1432 transaction.push_back(item("$ev3"), Some(3));
1433
1434 assert_mapping! {
1435 on transaction:
1436
1437 | event_id | event_index | timeline_item_index |
1438 |----------|-------------|---------------------|
1439 | "$ev0" | 0 | 0 |
1440 | "$ev1" | 1 | 2 |
1441 | "$ev2" | 2 | |
1442 | "$ev3" | 3 | 3 |
1443 }
1444
1445 assert_eq!(transaction.all_remote_events().0.len(), 4);
1446 assert_eq!(transaction.len(), 4);
1447
1448 transaction.clear();
1450
1451 assert!(transaction.all_remote_events().0.is_empty());
1452 assert!(transaction.is_empty());
1453 }
1454
1455 #[test]
1456 fn test_transaction_for_each() {
1457 let mut items = ObservableItems::new();
1458
1459 let mut transaction = items.transaction();
1461 transaction.push_back(item("$ev0"), Some(0));
1462 transaction.push_back(item("$ev1"), Some(1));
1463 transaction.push_back(item("$ev2"), Some(2));
1464
1465 let mut nth = 0;
1466
1467 transaction.for_each(|entry| {
1469 match nth {
1470 0 => {
1471 assert_event_id!(entry, "$ev0");
1472 }
1473 1 => {
1474 assert_event_id!(entry, "$ev1");
1475 }
1476 2 => {
1477 assert_event_id!(entry, "$ev2");
1478 }
1479 _ => unreachable!(),
1480 }
1481
1482 nth += 1;
1483 });
1484 }
1485
1486 #[test]
1487 fn test_transaction_for_each_remove() {
1488 let mut items = ObservableItems::new();
1489
1490 let mut transaction = items.transaction();
1492
1493 transaction.push_back_remote_event(event_meta("$ev0"));
1494 transaction.push_back(item("$ev0"), Some(0));
1495
1496 transaction.push_back_remote_event(event_meta("$ev1"));
1497 transaction.push_back(item("$ev1"), Some(1));
1498
1499 transaction.push_back_remote_event(event_meta("$ev2"));
1500 transaction.push_back(item("$ev2"), Some(2));
1501
1502 assert_mapping! {
1503 on transaction:
1504
1505 | event_id | event_index | timeline_item_index |
1506 |----------|-------------|---------------------|
1507 | "$ev0" | 0 | 0 |
1508 | "$ev1" | 1 | 1 |
1509 | "$ev2" | 2 | 2 |
1510 }
1511
1512 transaction.for_each(|entry| {
1514 if entry.as_event().unwrap().event_id().unwrap().as_str() == "$ev1" {
1515 ObservableItemsTransactionEntry::remove(entry);
1516 }
1517 });
1518
1519 assert_mapping! {
1520 on transaction:
1521
1522 | event_id | event_index | timeline_item_index |
1523 |----------|-------------|---------------------|
1524 | "$ev0" | 0 | 0 |
1525 | "$ev2" | 2 | 1 | }
1527
1528 assert_eq!(transaction.all_remote_events().0.len(), 3);
1529 assert_eq!(transaction.len(), 2);
1530 }
1531
1532 #[test]
1533 fn test_transaction_push_local() {
1534 let mut items = ObservableItems::new();
1535
1536 let mut transaction = items.transaction();
1537
1538 transaction.push_back(item("$ev0"), None);
1540
1541 transaction.push_local(local_item("t0"));
1543
1544 transaction.push_local(local_item("t1"));
1546
1547 transaction.commit();
1548
1549 let mut entries = items.entries();
1550
1551 assert_matches!(entries.next(), Some(entry) => {
1552 assert_event_id!(entry, "$ev0");
1553 });
1554 assert_matches!(entries.next(), Some(entry) => {
1555 assert_transaction_id!(entry, "t0");
1556 });
1557 assert_matches!(entries.next(), Some(entry) => {
1558 assert_transaction_id!(entry, "t1");
1559 });
1560 assert_matches!(entries.next(), None);
1561 }
1562
1563 #[test]
1564 #[should_panic]
1565 fn test_transaction_push_local_panic_not_a_local() {
1566 let mut items = ObservableItems::new();
1567 let mut transaction = items.transaction();
1568 transaction.push_local(item("$ev0"));
1569 }
1570
1571 #[test]
1572 fn test_transaction_push_date_divider() {
1573 let mut items = ObservableItems::new();
1574 let mut stream = items.subscribe().into_stream();
1575
1576 let mut transaction = items.transaction();
1577
1578 transaction.push_date_divider(
1579 0,
1580 TimelineItem::new(
1581 TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(
1582 MilliSecondsSinceUnixEpoch(uint!(10)),
1583 )),
1584 TimelineUniqueId("__foo".to_owned()),
1585 ),
1586 );
1587 transaction.push_date_divider(
1588 0,
1589 TimelineItem::new(
1590 TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(
1591 MilliSecondsSinceUnixEpoch(uint!(20)),
1592 )),
1593 TimelineUniqueId("__bar".to_owned()),
1594 ),
1595 );
1596 transaction.push_date_divider(
1597 1,
1598 TimelineItem::new(
1599 TimelineItemKind::Virtual(VirtualTimelineItem::DateDivider(
1600 MilliSecondsSinceUnixEpoch(uint!(30)),
1601 )),
1602 TimelineUniqueId("__baz".to_owned()),
1603 ),
1604 );
1605 transaction.commit();
1606
1607 assert_next_matches!(stream, VectorDiff::PushBack { value: timeline_item } => {
1608 assert_matches!(timeline_item.as_virtual(), Some(VirtualTimelineItem::DateDivider(ms)) => {
1609 assert_eq!(u64::from(ms.0), 10);
1610 });
1611 });
1612 assert_next_matches!(stream, VectorDiff::PushFront { value: timeline_item } => {
1613 assert_matches!(timeline_item.as_virtual(), Some(VirtualTimelineItem::DateDivider(ms)) => {
1614 assert_eq!(u64::from(ms.0), 20);
1615 });
1616 });
1617 assert_next_matches!(stream, VectorDiff::Insert { index: 1, value: timeline_item } => {
1618 assert_matches!(timeline_item.as_virtual(), Some(VirtualTimelineItem::DateDivider(ms)) => {
1619 assert_eq!(u64::from(ms.0), 30);
1620 });
1621 });
1622 assert_pending!(stream);
1623 }
1624
1625 #[test]
1626 #[should_panic]
1627 fn test_transaction_push_date_divider_panic_not_a_date_divider() {
1628 let mut items = ObservableItems::new();
1629 let mut transaction = items.transaction();
1630
1631 transaction.push_date_divider(0, item("$ev0"));
1632 }
1633
1634 #[test]
1635 #[should_panic]
1636 fn test_transaction_push_date_divider_panic_not_in_remotes_region() {
1637 let mut items = ObservableItems::new();
1638 let mut transaction = items.transaction();
1639
1640 transaction.push_timeline_start_if_missing(TimelineItem::new(
1641 VirtualTimelineItem::TimelineStart,
1642 TimelineUniqueId("__id_start".to_owned()),
1643 ));
1644 transaction.push_date_divider(
1645 0,
1646 TimelineItem::new(
1647 VirtualTimelineItem::DateDivider(MilliSecondsSinceUnixEpoch(uint!(10))),
1648 TimelineUniqueId("__date_divider".to_owned()),
1649 ),
1650 );
1651 }
1652
1653 #[test]
1654 fn test_transaction_push_timeline_start_if_missing() {
1655 let mut items = ObservableItems::new();
1656
1657 let mut transaction = items.transaction();
1658
1659 transaction.push_back(item("$ev0"), None);
1661
1662 transaction.push_timeline_start_if_missing(TimelineItem::new(
1664 VirtualTimelineItem::TimelineStart,
1665 TimelineUniqueId("__id_start".to_owned()),
1666 ));
1667
1668 transaction.push_back(item("$ev1"), None);
1670
1671 transaction.push_timeline_start_if_missing(TimelineItem::new(
1673 VirtualTimelineItem::TimelineStart,
1674 TimelineUniqueId("__id_start_again".to_owned()),
1675 ));
1676
1677 transaction.commit();
1678
1679 let mut entries = items.entries();
1680
1681 assert_matches!(entries.next(), Some(entry) => {
1682 assert!(entry.is_timeline_start());
1683 });
1684 assert_matches!(entries.next(), Some(entry) => {
1685 assert_event_id!(entry, "$ev0");
1686 });
1687 assert_matches!(entries.next(), Some(entry) => {
1688 assert_event_id!(entry, "$ev1");
1689 });
1690 assert_matches!(entries.next(), None);
1691 }
1692
1693 #[test]
1694 fn test_transaction_iter_all_regions() {
1695 let mut items = ObservableItems::new();
1696
1697 let mut transaction = items.transaction();
1698 transaction.push_timeline_start_if_missing(TimelineItem::new(
1699 VirtualTimelineItem::TimelineStart,
1700 TimelineUniqueId("__start".to_owned()),
1701 ));
1702 transaction.push_back(item("$ev0"), None);
1703 transaction.push_back(item("$ev1"), None);
1704 transaction.push_back(item("$ev2"), None);
1705 transaction.push_local(local_item("t0"));
1706 transaction.push_local(local_item("t1"));
1707 transaction.push_local(local_item("t2"));
1708
1709 let mut iter = transaction.iter_all_regions();
1711 assert_matches!(iter.next(), Some((0, item)) => {
1712 assert!(item.is_timeline_start());
1713 });
1714 assert_matches!(iter.next(), Some((1, item)) => {
1715 assert_event_id!(item, "$ev0");
1716 });
1717 assert_matches!(iter.next(), Some((2, item)) => {
1718 assert_event_id!(item, "$ev1");
1719 });
1720 assert_matches!(iter.next(), Some((3, item)) => {
1721 assert_event_id!(item, "$ev2");
1722 });
1723 assert_matches!(iter.next(), Some((4, item)) => {
1724 assert_transaction_id!(item, "t0");
1725 });
1726 assert_matches!(iter.next(), Some((5, item)) => {
1727 assert_transaction_id!(item, "t1");
1728 });
1729 assert_matches!(iter.next(), Some((6, item)) => {
1730 assert_transaction_id!(item, "t2");
1731 });
1732 assert!(iter.next().is_none());
1733 }
1734
1735 #[test]
1736 fn test_transaction_iter_remotes_regions() {
1737 let mut items = ObservableItems::new();
1738
1739 let mut transaction = items.transaction();
1740 transaction.push_timeline_start_if_missing(TimelineItem::new(
1741 VirtualTimelineItem::TimelineStart,
1742 TimelineUniqueId("__start".to_owned()),
1743 ));
1744 transaction.push_back(item("$ev0"), None);
1745 transaction.push_back(item("$ev1"), None);
1746 transaction.push_back(item("$ev2"), None);
1747 transaction.push_local(local_item("t0"));
1748 transaction.push_local(local_item("t1"));
1749 transaction.push_local(local_item("t2"));
1750
1751 let mut iter = transaction.iter_remotes_region();
1753 assert_matches!(iter.next(), Some((1, item)) => {
1754 assert_event_id!(item, "$ev0");
1755 });
1756 assert_matches!(iter.next(), Some((2, item)) => {
1757 assert_event_id!(item, "$ev1");
1758 });
1759 assert_matches!(iter.next(), Some((3, item)) => {
1760 assert_event_id!(item, "$ev2");
1761 });
1762 assert!(iter.next().is_none());
1763 }
1764
1765 #[test]
1766 fn test_transaction_iter_remotes_regions_with_no_start_region() {
1767 let mut items = ObservableItems::new();
1768
1769 let mut transaction = items.transaction();
1770 transaction.push_back(item("$ev0"), None);
1771 transaction.push_back(item("$ev1"), None);
1772 transaction.push_back(item("$ev2"), None);
1773 transaction.push_local(local_item("t0"));
1774 transaction.push_local(local_item("t1"));
1775 transaction.push_local(local_item("t2"));
1776
1777 let mut iter = transaction.iter_remotes_region();
1779 assert_matches!(iter.next(), Some((0, item)) => {
1780 assert_event_id!(item, "$ev0");
1781 });
1782 assert_matches!(iter.next(), Some((1, item)) => {
1783 assert_event_id!(item, "$ev1");
1784 });
1785 assert_matches!(iter.next(), Some((2, item)) => {
1786 assert_event_id!(item, "$ev2");
1787 });
1788 assert!(iter.next().is_none());
1789 }
1790
1791 #[test]
1792 fn test_transaction_iter_remotes_regions_with_no_locals_region() {
1793 let mut items = ObservableItems::new();
1794
1795 let mut transaction = items.transaction();
1796 transaction.push_back(item("$ev0"), None);
1797 transaction.push_back(item("$ev1"), None);
1798 transaction.push_back(item("$ev2"), None);
1799
1800 let mut iter = transaction.iter_remotes_region();
1802 assert_matches!(iter.next(), Some((0, item)) => {
1803 assert_event_id!(item, "$ev0");
1804 });
1805 assert_matches!(iter.next(), Some((1, item)) => {
1806 assert_event_id!(item, "$ev1");
1807 });
1808 assert_matches!(iter.next(), Some((2, item)) => {
1809 assert_event_id!(item, "$ev2");
1810 });
1811 assert!(iter.next().is_none());
1812 }
1813
1814 #[test]
1815 fn test_transaction_iter_locals_region() {
1816 let mut items = ObservableItems::new();
1817
1818 let mut transaction = items.transaction();
1819 transaction.push_timeline_start_if_missing(TimelineItem::new(
1820 VirtualTimelineItem::TimelineStart,
1821 TimelineUniqueId("__start".to_owned()),
1822 ));
1823 transaction.push_back(item("$ev0"), None);
1824 transaction.push_back(item("$ev1"), None);
1825 transaction.push_back(item("$ev2"), None);
1826 transaction.push_local(local_item("t0"));
1827 transaction.push_local(local_item("t1"));
1828 transaction.push_local(local_item("t2"));
1829
1830 let mut iter = transaction.iter_locals_region();
1832 assert_matches!(iter.next(), Some((4, item)) => {
1833 assert_transaction_id!(item, "t0");
1834 });
1835 assert_matches!(iter.next(), Some((5, item)) => {
1836 assert_transaction_id!(item, "t1");
1837 });
1838 assert_matches!(iter.next(), Some((6, item)) => {
1839 assert_transaction_id!(item, "t2");
1840 });
1841 assert!(iter.next().is_none());
1842 }
1843}
1844
1845#[derive(Clone, Debug, Default)]
1851pub struct AllRemoteEvents(VecDeque<EventMeta>);
1852
1853impl AllRemoteEvents {
1854 pub fn get(&self, event_index: usize) -> Option<&EventMeta> {
1856 self.0.get(event_index)
1857 }
1858
1859 pub fn iter(&self) -> Iter<'_, EventMeta> {
1861 self.0.iter()
1862 }
1863
1864 pub fn range<R>(&self, range: R) -> Iter<'_, EventMeta>
1867 where
1868 R: RangeBounds<usize>,
1869 {
1870 self.0.range(range)
1871 }
1872
1873 fn clear(&mut self) {
1875 self.0.clear();
1876 }
1877
1878 fn push_front(&mut self, event_meta: EventMeta) {
1880 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1883 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1884 }
1885
1886 self.0.push_front(event_meta)
1888 }
1889
1890 fn push_back(&mut self, event_meta: EventMeta) {
1892 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1895 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1896 }
1897
1898 self.0.push_back(event_meta)
1900 }
1901
1902 fn insert(&mut self, event_index: usize, event_meta: EventMeta) {
1904 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1907 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1908 }
1909
1910 self.0.insert(event_index, event_meta)
1912 }
1913
1914 fn remove(&mut self, event_index: usize) -> Option<EventMeta> {
1916 let event_meta = self.0.remove(event_index)?;
1918
1919 if let Some(removed_timeline_item_index) = event_meta.timeline_item_index {
1922 self.decrement_all_timeline_item_index_after(removed_timeline_item_index);
1923 };
1924
1925 Some(event_meta)
1926 }
1927
1928 pub fn last(&self) -> Option<&EventMeta> {
1930 self.0.back()
1931 }
1932
1933 pub fn last_index(&self) -> Option<usize> {
1935 self.0.len().checked_sub(1)
1936 }
1937
1938 pub fn get_by_event_id_mut(&mut self, event_id: &EventId) -> Option<&mut EventMeta> {
1940 self.0.iter_mut().rev().find(|event_meta| event_meta.event_id == event_id)
1941 }
1942
1943 pub fn get_by_event_id(&self, event_id: &EventId) -> Option<&EventMeta> {
1945 self.0.iter().rev().find(|event_meta| event_meta.event_id == event_id)
1946 }
1947
1948 pub fn position_by_event_id(&self, event_id: &EventId) -> Option<usize> {
1950 self.0
1953 .iter()
1954 .enumerate()
1955 .rev()
1956 .find_map(|(i, event_meta)| (event_meta.event_id == event_id).then_some(i))
1957 }
1958
1959 fn increment_all_timeline_item_index_after(&mut self, new_timeline_item_index: usize) {
1962 for event_meta in self.0.iter_mut().rev() {
1970 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
1971 if *timeline_item_index >= new_timeline_item_index {
1972 *timeline_item_index += 1;
1973 } else {
1974 break;
1976 }
1977 }
1978 }
1979 }
1980
1981 fn decrement_all_timeline_item_index_after(&mut self, removed_timeline_item_index: usize) {
1984 for event_meta in self.0.iter_mut().rev() {
1992 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
1993 if *timeline_item_index > removed_timeline_item_index {
1994 *timeline_item_index -= 1;
1995 } else {
1996 break;
1998 }
1999 }
2000 }
2001 }
2002
2003 fn timeline_item_has_been_inserted_at(
2008 &mut self,
2009 new_timeline_item_index: usize,
2010 event_index: Option<usize>,
2011 ) {
2012 self.increment_all_timeline_item_index_after(new_timeline_item_index);
2013
2014 if let Some(event_index) = event_index {
2015 if let Some(event_meta) = self.0.get_mut(event_index) {
2016 event_meta.timeline_item_index = Some(new_timeline_item_index);
2017 }
2018 }
2019 }
2020
2021 fn timeline_item_has_been_removed_at(&mut self, timeline_item_index_to_remove: usize) {
2024 for event_meta in self.0.iter_mut() {
2025 let mut remove_timeline_item_index = false;
2026
2027 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
2030 match (*timeline_item_index).cmp(&timeline_item_index_to_remove) {
2031 Ordering::Equal => {
2032 remove_timeline_item_index = true;
2033 }
2034
2035 Ordering::Greater => {
2036 *timeline_item_index -= 1;
2037 }
2038
2039 Ordering::Less => {}
2040 }
2041 }
2042
2043 if remove_timeline_item_index {
2046 event_meta.timeline_item_index = None;
2047 }
2048 }
2049 }
2050}
2051
2052#[cfg(test)]
2053mod all_remote_events_tests {
2054 use assert_matches::assert_matches;
2055 use ruma::event_id;
2056
2057 use super::{AllRemoteEvents, EventMeta};
2058
2059 fn event_meta(event_id: &str, timeline_item_index: Option<usize>) -> EventMeta {
2060 EventMeta { event_id: event_id.parse().unwrap(), timeline_item_index, visible: false }
2061 }
2062
2063 macro_rules! assert_events {
2064 ( $events:ident, [ $( ( $event_id:literal, $timeline_item_index:expr ) ),* $(,)? ] ) => {
2065 let mut iter = $events .iter();
2066
2067 $(
2068 assert_matches!(iter.next(), Some(EventMeta { event_id, timeline_item_index, .. }) => {
2069 assert_eq!(event_id.as_str(), $event_id );
2070 assert_eq!(*timeline_item_index, $timeline_item_index );
2071 });
2072 )*
2073
2074 assert!(iter.next().is_none(), "Not all events have been asserted");
2075 }
2076 }
2077
2078 #[test]
2079 fn test_range() {
2080 let mut events = AllRemoteEvents::default();
2081
2082 events.push_back(event_meta("$ev0", None));
2084 events.push_back(event_meta("$ev1", None));
2085 events.push_back(event_meta("$ev2", None));
2086
2087 assert_eq!(events.iter().count(), 3);
2088
2089 assert_eq!(events.range(..).count(), 3);
2091 assert_eq!(events.range(1..).count(), 2);
2092 assert_eq!(events.range(0..=1).count(), 2);
2093
2094 let mut some_events = events.range(1..);
2096
2097 assert_matches!(some_events.next(), Some(EventMeta { event_id, .. }) => {
2098 assert_eq!(event_id.as_str(), "$ev1");
2099 });
2100 assert_matches!(some_events.next(), Some(EventMeta { event_id, .. }) => {
2101 assert_eq!(event_id.as_str(), "$ev2");
2102 });
2103 assert!(some_events.next().is_none());
2104 }
2105
2106 #[test]
2107 fn test_clear() {
2108 let mut events = AllRemoteEvents::default();
2109
2110 events.push_back(event_meta("$ev0", None));
2112 events.push_back(event_meta("$ev1", None));
2113 events.push_back(event_meta("$ev2", None));
2114
2115 assert_eq!(events.iter().count(), 3);
2116
2117 events.clear();
2119
2120 assert_eq!(events.iter().count(), 0);
2121 }
2122
2123 #[test]
2124 fn test_push_front() {
2125 let mut events = AllRemoteEvents::default();
2126
2127 events.push_front(event_meta("$ev0", Some(1)));
2129
2130 events.push_front(event_meta("$ev1", None));
2132
2133 events.push_front(event_meta("$ev2", Some(0)));
2135
2136 events.push_front(event_meta("$ev3", Some(0)));
2138
2139 assert_events!(
2140 events,
2141 [
2142 ("$ev3", Some(0)),
2144 ("$ev2", Some(1)),
2146 ("$ev1", None),
2148 ("$ev0", Some(3)),
2150 ]
2151 );
2152 }
2153
2154 #[test]
2155 fn test_push_back() {
2156 let mut events = AllRemoteEvents::default();
2157
2158 events.push_back(event_meta("$ev0", Some(0)));
2160
2161 events.push_back(event_meta("$ev1", None));
2163
2164 events.push_back(event_meta("$ev2", Some(1)));
2166
2167 events.push_back(event_meta("$ev3", Some(1)));
2171
2172 assert_events!(
2173 events,
2174 [
2175 ("$ev0", Some(0)),
2177 ("$ev1", None),
2179 ("$ev2", Some(2)),
2181 ("$ev3", Some(1)),
2183 ]
2184 );
2185 }
2186
2187 #[test]
2188 fn test_insert() {
2189 let mut events = AllRemoteEvents::default();
2190
2191 events.insert(0, event_meta("$ev0", Some(0)));
2193
2194 events.insert(1, event_meta("$ev1", None));
2196
2197 events.insert(2, event_meta("$ev2", Some(1)));
2199
2200 events.insert(0, event_meta("$ev3", Some(0)));
2202
2203 assert_events!(
2204 events,
2205 [
2206 ("$ev3", Some(0)),
2208 ("$ev0", Some(1)),
2210 ("$ev1", None),
2212 ("$ev2", Some(2)),
2214 ]
2215 );
2216 }
2217
2218 #[test]
2219 fn test_remove() {
2220 let mut events = AllRemoteEvents::default();
2221
2222 events.push_back(event_meta("$ev0", Some(0)));
2224 events.push_back(event_meta("$ev1", Some(1)));
2225 events.push_back(event_meta("$ev2", None));
2226 events.push_back(event_meta("$ev3", Some(2)));
2227
2228 assert_events!(
2230 events,
2231 [("$ev0", Some(0)), ("$ev1", Some(1)), ("$ev2", None), ("$ev3", Some(2))]
2232 );
2233
2234 events.remove(2); events.remove(1); assert_events!(
2239 events,
2240 [
2241 ("$ev0", Some(0)),
2242 ("$ev3", Some(1)),
2244 ]
2245 );
2246 }
2247
2248 #[test]
2249 fn test_last() {
2250 let mut events = AllRemoteEvents::default();
2251
2252 assert!(events.last().is_none());
2253 assert!(events.last_index().is_none());
2254
2255 events.push_back(event_meta("$ev0", Some(0)));
2257 events.push_back(event_meta("$ev1", Some(1)));
2258
2259 assert_matches!(events.last(), Some(EventMeta { event_id, .. }) => {
2260 assert_eq!(event_id.as_str(), "$ev1");
2261 });
2262 assert_eq!(events.last_index(), Some(1));
2263 }
2264
2265 #[test]
2266 fn test_get_by_event_by_mut() {
2267 let mut events = AllRemoteEvents::default();
2268
2269 events.push_back(event_meta("$ev0", Some(0)));
2271 events.push_back(event_meta("$ev1", Some(1)));
2272
2273 assert!(events.get_by_event_id_mut(event_id!("$ev0")).is_some());
2274 assert!(events.get_by_event_id_mut(event_id!("$ev42")).is_none());
2275 }
2276
2277 #[test]
2278 fn test_timeline_item_has_been_inserted_at() {
2279 let mut events = AllRemoteEvents::default();
2280
2281 events.push_back(event_meta("$ev0", Some(0)));
2283 events.push_back(event_meta("$ev1", Some(1)));
2284 events.push_back(event_meta("$ev2", None));
2285 events.push_back(event_meta("$ev3", None));
2286 events.push_back(event_meta("$ev4", Some(2)));
2287 events.push_back(event_meta("$ev5", Some(3)));
2288 events.push_back(event_meta("$ev6", None));
2289
2290 events.timeline_item_has_been_inserted_at(2, None);
2292
2293 assert_events!(
2294 events,
2295 [
2296 ("$ev0", Some(0)),
2297 ("$ev1", Some(1)),
2298 ("$ev2", None),
2299 ("$ev3", None),
2300 ("$ev4", Some(3)),
2302 ("$ev5", Some(4)),
2304 ("$ev6", None),
2305 ]
2306 );
2307
2308 events.timeline_item_has_been_inserted_at(5, Some(6));
2310
2311 assert_events!(
2312 events,
2313 [
2314 ("$ev0", Some(0)),
2315 ("$ev1", Some(1)),
2316 ("$ev2", None),
2317 ("$ev3", None),
2318 ("$ev4", Some(3)),
2319 ("$ev5", Some(4)),
2320 ("$ev6", Some(5)),
2322 ]
2323 );
2324 }
2325
2326 #[test]
2327 fn test_timeline_item_has_been_removed_at() {
2328 let mut events = AllRemoteEvents::default();
2329
2330 events.push_back(event_meta("$ev0", Some(0)));
2332 events.push_back(event_meta("$ev1", Some(1)));
2333 events.push_back(event_meta("$ev2", None));
2334 events.push_back(event_meta("$ev3", None));
2335 events.push_back(event_meta("$ev4", Some(3)));
2336 events.push_back(event_meta("$ev5", Some(4)));
2337 events.push_back(event_meta("$ev6", None));
2338
2339 events.timeline_item_has_been_removed_at(2);
2341
2342 assert_events!(
2343 events,
2344 [
2345 ("$ev0", Some(0)),
2346 ("$ev1", Some(1)),
2347 ("$ev2", None),
2348 ("$ev3", None),
2349 ("$ev4", Some(2)),
2351 ("$ev5", Some(3)),
2353 ("$ev6", None),
2354 ]
2355 );
2356
2357 events.timeline_item_has_been_removed_at(2);
2359
2360 assert_events!(
2361 events,
2362 [
2363 ("$ev0", Some(0)),
2364 ("$ev1", Some(1)),
2365 ("$ev2", None),
2366 ("$ev3", None),
2367 ("$ev4", None),
2369 ("$ev5", Some(2)),
2371 ("$ev6", None),
2372 ]
2373 );
2374
2375 events.timeline_item_has_been_removed_at(0);
2377
2378 assert_events!(
2379 events,
2380 [
2381 ("$ev0", None),
2383 ("$ev1", Some(0)),
2385 ("$ev2", None),
2386 ("$ev3", None),
2387 ("$ev4", None),
2388 ("$ev5", Some(1)),
2390 ("$ev6", None),
2391 ]
2392 );
2393 }
2394}