1use std::{
16 cmp::Ordering,
17 collections::{vec_deque::Iter, VecDeque},
18 ops::{Deref, RangeBounds},
19 sync::Arc,
20};
21
22use eyeball_im::{
23 ObservableVector, ObservableVectorEntries, ObservableVectorEntry, ObservableVectorTransaction,
24 ObservableVectorTransactionEntry, VectorSubscriber,
25};
26use imbl::Vector;
27use ruma::EventId;
28
29use super::{metadata::EventMeta, TimelineItem};
30
31#[derive(Debug)]
35pub struct ObservableItems {
36 items: ObservableVector<Arc<TimelineItem>>,
44
45 all_remote_events: AllRemoteEvents,
53}
54
55impl ObservableItems {
56 pub fn new() -> Self {
58 Self {
59 items: ObservableVector::with_capacity(32),
63 all_remote_events: AllRemoteEvents::default(),
64 }
65 }
66
67 pub fn all_remote_events(&self) -> &AllRemoteEvents {
69 &self.all_remote_events
70 }
71
72 pub fn is_empty(&self) -> bool {
74 self.items.is_empty()
75 }
76
77 pub fn subscribe(&self) -> VectorSubscriber<Arc<TimelineItem>> {
79 self.items.subscribe()
80 }
81
82 pub fn clone_items(&self) -> Vector<Arc<TimelineItem>> {
86 self.items.clone()
87 }
88
89 pub fn transaction(&mut self) -> ObservableItemsTransaction<'_> {
91 ObservableItemsTransaction {
92 items: self.items.transaction(),
93 all_remote_events: &mut self.all_remote_events,
94 }
95 }
96
97 pub fn replace(
104 &mut self,
105 timeline_item_index: usize,
106 timeline_item: Arc<TimelineItem>,
107 ) -> Arc<TimelineItem> {
108 self.items.set(timeline_item_index, timeline_item)
109 }
110
111 pub fn entries(&mut self) -> ObservableItemsEntries<'_> {
113 ObservableItemsEntries(self.items.entries())
114 }
115
116 pub fn for_each<F>(&mut self, mut f: F)
119 where
120 F: FnMut(ObservableItemsEntry<'_>),
121 {
122 self.items.for_each(|entry| f(ObservableItemsEntry(entry)))
123 }
124}
125
126impl Deref for ObservableItems {
132 type Target = Vector<Arc<TimelineItem>>;
133
134 fn deref(&self) -> &Self::Target {
135 &self.items
136 }
137}
138
139pub struct ObservableItemsEntries<'a>(ObservableVectorEntries<'a, Arc<TimelineItem>>);
146
147impl ObservableItemsEntries<'_> {
148 pub fn next(&mut self) -> Option<ObservableItemsEntry<'_>> {
151 self.0.next().map(ObservableItemsEntry)
152 }
153}
154
155#[derive(Debug)]
157pub struct ObservableItemsEntry<'a>(ObservableVectorEntry<'a, Arc<TimelineItem>>);
158
159impl ObservableItemsEntry<'_> {
160 pub fn replace(this: &mut Self, timeline_item: Arc<TimelineItem>) -> Arc<TimelineItem> {
162 ObservableVectorEntry::set(&mut this.0, timeline_item)
163 }
164}
165
166impl Deref for ObservableItemsEntry<'_> {
172 type Target = Arc<TimelineItem>;
173
174 fn deref(&self) -> &Self::Target {
175 &self.0
176 }
177}
178
179#[derive(Debug)]
186pub struct ObservableItemsTransaction<'observable_items> {
187 items: ObservableVectorTransaction<'observable_items, Arc<TimelineItem>>,
188 all_remote_events: &'observable_items mut AllRemoteEvents,
189}
190
191impl<'observable_items> ObservableItemsTransaction<'observable_items> {
192 pub fn get(&self, timeline_item_index: usize) -> Option<&Arc<TimelineItem>> {
194 self.items.get(timeline_item_index)
195 }
196
197 pub fn all_remote_events(&self) -> &AllRemoteEvents {
199 self.all_remote_events
200 }
201
202 pub fn remove_remote_event(&mut self, event_index: usize) -> Option<EventMeta> {
206 self.all_remote_events.remove(event_index)
207 }
208
209 pub fn push_front_remote_event(&mut self, event_meta: EventMeta) {
213 self.all_remote_events.push_front(event_meta);
214 }
215
216 pub fn push_back_remote_event(&mut self, event_meta: EventMeta) {
220 self.all_remote_events.push_back(event_meta);
221 }
222
223 pub fn insert_remote_event(&mut self, event_index: usize, event_meta: EventMeta) {
227 self.all_remote_events.insert(event_index, event_meta);
228 }
229
230 pub fn get_remote_event_by_event_id_mut(
232 &mut self,
233 event_id: &EventId,
234 ) -> Option<&mut EventMeta> {
235 self.all_remote_events.get_by_event_id_mut(event_id)
236 }
237
238 pub fn get_remote_event_by_event_id(&self, event_id: &EventId) -> Option<&EventMeta> {
240 self.all_remote_events.get_by_event_id(event_id)
241 }
242
243 pub fn replace(
246 &mut self,
247 timeline_item_index: usize,
248 timeline_item: Arc<TimelineItem>,
249 ) -> Arc<TimelineItem> {
250 self.items.set(timeline_item_index, timeline_item)
251 }
252
253 pub fn remove(&mut self, timeline_item_index: usize) -> Arc<TimelineItem> {
255 let removed_timeline_item = self.items.remove(timeline_item_index);
256 self.all_remote_events.timeline_item_has_been_removed_at(timeline_item_index);
257
258 removed_timeline_item
259 }
260
261 pub fn insert(
270 &mut self,
271 timeline_item_index: usize,
272 timeline_item: Arc<TimelineItem>,
273 event_index: Option<usize>,
274 ) {
275 self.items.insert(timeline_item_index, timeline_item);
276 self.all_remote_events.timeline_item_has_been_inserted_at(timeline_item_index, event_index);
277 }
278
279 pub fn push_front(&mut self, timeline_item: Arc<TimelineItem>, event_index: Option<usize>) {
288 self.items.push_front(timeline_item);
289 self.all_remote_events.timeline_item_has_been_inserted_at(0, event_index);
290 }
291
292 pub fn push_back(&mut self, timeline_item: Arc<TimelineItem>, event_index: Option<usize>) {
301 self.items.push_back(timeline_item);
302 self.all_remote_events
303 .timeline_item_has_been_inserted_at(self.items.len().saturating_sub(1), event_index);
304 }
305
306 pub fn clear(&mut self) {
308 self.items.clear();
309 self.all_remote_events.clear();
310 }
311
312 pub fn for_each<F>(&mut self, mut f: F)
315 where
316 F: FnMut(ObservableItemsTransactionEntry<'_, 'observable_items>),
317 {
318 self.items.for_each(|entry| {
319 f(ObservableItemsTransactionEntry { entry, all_remote_events: self.all_remote_events })
320 })
321 }
322
323 pub fn commit(self) {
326 self.items.commit()
327 }
328}
329
330impl Deref for ObservableItemsTransaction<'_> {
336 type Target = Vector<Arc<TimelineItem>>;
337
338 fn deref(&self) -> &Self::Target {
339 &self.items
340 }
341}
342
343pub struct ObservableItemsTransactionEntry<'observable_transaction_items, 'observable_items> {
345 entry: ObservableVectorTransactionEntry<
346 'observable_transaction_items,
347 'observable_items,
348 Arc<TimelineItem>,
349 >,
350 all_remote_events: &'observable_transaction_items mut AllRemoteEvents,
351}
352
353impl ObservableItemsTransactionEntry<'_, '_> {
354 pub fn remove(this: Self) {
356 let entry_index = ObservableVectorTransactionEntry::index(&this.entry);
357
358 ObservableVectorTransactionEntry::remove(this.entry);
359 this.all_remote_events.timeline_item_has_been_removed_at(entry_index);
360 }
361}
362
363impl Deref for ObservableItemsTransactionEntry<'_, '_> {
369 type Target = Arc<TimelineItem>;
370
371 fn deref(&self) -> &Self::Target {
372 &self.entry
373 }
374}
375
376#[cfg(test)]
377mod observable_items_tests {
378 use std::ops::Not;
379
380 use assert_matches::assert_matches;
381 use eyeball_im::VectorDiff;
382 use ruma::{
383 events::room::message::{MessageType, TextMessageEventContent},
384 owned_user_id, MilliSecondsSinceUnixEpoch,
385 };
386 use stream_assert::assert_next_matches;
387
388 use super::*;
389 use crate::timeline::{
390 controller::{EventTimelineItemKind, RemoteEventOrigin},
391 event_item::RemoteEventTimelineItem,
392 EventTimelineItem, Message, TimelineDetails, TimelineItemContent, TimelineUniqueId,
393 };
394
395 fn item(event_id: &str) -> Arc<TimelineItem> {
396 TimelineItem::new(
397 EventTimelineItem::new(
398 owned_user_id!("@ivan:mnt.io"),
399 TimelineDetails::Unavailable,
400 MilliSecondsSinceUnixEpoch(0u32.into()),
401 TimelineItemContent::Message(Message {
402 msgtype: MessageType::Text(TextMessageEventContent::plain("hello")),
403 in_reply_to: None,
404 thread_root: None,
405 edited: false,
406 mentions: None,
407 reactions: Default::default(),
408 }),
409 EventTimelineItemKind::Remote(RemoteEventTimelineItem {
410 event_id: event_id.parse().unwrap(),
411 transaction_id: None,
412 read_receipts: Default::default(),
413 is_own: false,
414 is_highlighted: false,
415 encryption_info: None,
416 original_json: None,
417 latest_edit_json: None,
418 origin: RemoteEventOrigin::Sync,
419 }),
420 false,
421 ),
422 TimelineUniqueId(format!("__id_{event_id}")),
423 )
424 }
425
426 fn read_marker() -> Arc<TimelineItem> {
427 TimelineItem::read_marker()
428 }
429
430 fn event_meta(event_id: &str) -> EventMeta {
431 EventMeta { event_id: event_id.parse().unwrap(), timeline_item_index: None, visible: false }
432 }
433
434 macro_rules! assert_event_id {
435 ( $timeline_item:expr, $event_id:literal $( , $message:expr )? $(,)? ) => {
436 assert_eq!($timeline_item.as_event().unwrap().event_id().unwrap().as_str(), $event_id $( , $message)? );
437 };
438 }
439
440 macro_rules! assert_mapping {
441 ( on $transaction:ident:
442 | event_id | event_index | timeline_item_index |
443 | $( - )+ | $( - )+ | $( - )+ |
444 $(
445 | $event_id:literal | $event_index:literal | $( $timeline_item_index:literal )? |
446 )+
447 ) => {
448 let all_remote_events = $transaction .all_remote_events();
449
450 $(
451 assert_matches!(all_remote_events.0.get( $event_index ), Some(EventMeta { event_id, timeline_item_index, .. }) => {
453 assert_eq!(
455 event_id.as_str(),
456 $event_id ,
457 concat!("event #", $event_index, " should have ID ", $event_id)
458 );
459
460
461 #[allow(unused_variables)]
463 let timeline_item_index_is_expected = false;
464 $(
465 let timeline_item_index_is_expected = true;
466 let _ = $timeline_item_index;
467 )?
468
469 if timeline_item_index_is_expected.not() {
470 assert!(
472 timeline_item_index.is_none(),
473 concat!("event #", $event_index, " with ID ", $event_id, " should NOT map to a timeline item index" )
474 );
475 }
476
477 $(
478 assert_eq!(
480 *timeline_item_index,
481 Some( $timeline_item_index ),
482 concat!("event #", $event_index, " with ID ", $event_id, " should map to timeline item #", $timeline_item_index )
483 );
484
485 assert_matches!( $transaction .get( $timeline_item_index ), Some(timeline_item) => {
487 assert_event_id!(
489 timeline_item,
490 $event_id ,
491 concat!("timeline item #", $timeline_item_index, " should map to event ID ", $event_id )
492 );
493 });
494 )?
495 });
496 )*
497 }
498 }
499
500 #[test]
501 fn test_is_empty() {
502 let mut items = ObservableItems::new();
503
504 assert!(items.is_empty());
505
506 let mut transaction = items.transaction();
508 transaction.push_back(item("$ev0"), Some(0));
509 transaction.commit();
510
511 assert!(items.is_empty().not());
512 }
513
514 #[test]
515 fn test_subscribe() {
516 let mut items = ObservableItems::new();
517 let mut subscriber = items.subscribe().into_stream();
518
519 let mut transaction = items.transaction();
521 transaction.push_back(item("$ev0"), Some(0));
522 transaction.commit();
523
524 assert_next_matches!(subscriber, VectorDiff::PushBack { value: event } => {
526 assert_event_id!(event, "$ev0");
527 });
528 }
529
530 #[test]
531 fn test_clone_items() {
532 let mut items = ObservableItems::new();
533
534 let mut transaction = items.transaction();
535 transaction.push_back(item("$ev0"), Some(0));
536 transaction.push_back(item("$ev1"), Some(1));
537 transaction.commit();
538
539 let items = items.clone_items();
540 assert_eq!(items.len(), 2);
541 assert_event_id!(items[0], "$ev0");
542 assert_event_id!(items[1], "$ev1");
543 }
544
545 #[test]
546 fn test_replace() {
547 let mut items = ObservableItems::new();
548
549 let mut transaction = items.transaction();
551 transaction.push_back(item("$ev0"), Some(0));
552 transaction.commit();
553
554 items.replace(0, item("$ev1"));
556
557 let items = items.clone_items();
558 assert_eq!(items.len(), 1);
559 assert_event_id!(items[0], "$ev1");
560 }
561
562 #[test]
563 fn test_entries() {
564 let mut items = ObservableItems::new();
565
566 let mut transaction = items.transaction();
568 transaction.push_back(item("$ev0"), Some(0));
569 transaction.push_back(item("$ev1"), Some(1));
570 transaction.push_back(item("$ev2"), Some(2));
571 transaction.commit();
572
573 let mut entries = items.entries();
574
575 assert_matches!(entries.next(), Some(entry) => {
576 assert_event_id!(entry, "$ev0");
577 });
578 assert_matches!(entries.next(), Some(entry) => {
579 assert_event_id!(entry, "$ev1");
580 });
581 assert_matches!(entries.next(), Some(entry) => {
582 assert_event_id!(entry, "$ev2");
583 });
584 assert_matches!(entries.next(), None);
585 }
586
587 #[test]
588 fn test_entry_replace() {
589 let mut items = ObservableItems::new();
590
591 let mut transaction = items.transaction();
593 transaction.push_back(item("$ev0"), Some(0));
594 transaction.commit();
595
596 let mut entries = items.entries();
597
598 assert_matches!(entries.next(), Some(mut entry) => {
600 assert_event_id!(entry, "$ev0");
601 ObservableItemsEntry::replace(&mut entry, item("$ev1"));
602 });
603 assert_matches!(entries.next(), None);
604
605 let mut entries = items.entries();
607
608 assert_matches!(entries.next(), Some(entry) => {
609 assert_event_id!(entry, "$ev1");
610 });
611 assert_matches!(entries.next(), None);
612 }
613
614 #[test]
615 fn test_for_each() {
616 let mut items = ObservableItems::new();
617
618 let mut transaction = items.transaction();
620 transaction.push_back(item("$ev0"), Some(0));
621 transaction.push_back(item("$ev1"), Some(1));
622 transaction.push_back(item("$ev2"), Some(2));
623 transaction.commit();
624
625 let mut nth = 0;
626
627 items.for_each(|entry| {
629 match nth {
630 0 => {
631 assert_event_id!(entry, "$ev0");
632 }
633 1 => {
634 assert_event_id!(entry, "$ev1");
635 }
636 2 => {
637 assert_event_id!(entry, "$ev2");
638 }
639 _ => unreachable!(),
640 }
641
642 nth += 1;
643 });
644 }
645
646 #[test]
647 fn test_transaction_commit() {
648 let mut items = ObservableItems::new();
649
650 let mut transaction = items.transaction();
652 transaction.push_back(item("$ev0"), Some(0));
653 drop(transaction);
654
655 assert!(items.is_empty());
656
657 let mut transaction = items.transaction();
659 transaction.push_back(item("$ev0"), Some(0));
660 transaction.commit();
661
662 assert!(items.is_empty().not());
663 }
664
665 #[test]
666 fn test_transaction_get() {
667 let mut items = ObservableItems::new();
668
669 let mut transaction = items.transaction();
670 transaction.push_back(item("$ev0"), Some(0));
671
672 assert_matches!(transaction.get(0), Some(event) => {
673 assert_event_id!(event, "$ev0");
674 });
675 }
676
677 #[test]
678 fn test_transaction_replace() {
679 let mut items = ObservableItems::new();
680
681 let mut transaction = items.transaction();
682 transaction.push_back(item("$ev0"), Some(0));
683 transaction.replace(0, item("$ev1"));
684
685 assert_matches!(transaction.get(0), Some(event) => {
686 assert_event_id!(event, "$ev1");
687 });
688 }
689
690 #[test]
691 fn test_transaction_insert() {
692 let mut items = ObservableItems::new();
693
694 let mut transaction = items.transaction();
695
696 transaction.push_back_remote_event(event_meta("$ev0"));
698 transaction.insert(0, item("$ev0"), Some(0));
699
700 assert_mapping! {
701 on transaction:
702
703 | event_id | event_index | timeline_item_index |
704 |----------|-------------|---------------------|
705 | "$ev0" | 0 | 0 | }
707
708 transaction.insert(0, read_marker(), None);
710
711 assert_mapping! {
712 on transaction:
713
714 | event_id | event_index | timeline_item_index |
715 |----------|-------------|---------------------|
716 | "$ev0" | 0 | 1 | }
718
719 transaction.push_back_remote_event(event_meta("$ev1"));
721 transaction.insert(2, item("$ev1"), Some(1));
722
723 assert_mapping! {
724 on transaction:
725
726 | event_id | event_index | timeline_item_index |
727 |----------|-------------|---------------------|
728 | "$ev0" | 0 | 1 |
729 | "$ev1" | 1 | 2 | }
731
732 transaction.push_back_remote_event(event_meta("$ev2"));
734
735 assert_mapping! {
736 on transaction:
737
738 | event_id | event_index | timeline_item_index |
739 |----------|-------------|---------------------|
740 | "$ev0" | 0 | 1 |
741 | "$ev1" | 1 | 2 |
742 | "$ev2" | 2 | | }
744
745 transaction.push_back_remote_event(event_meta("$ev3"));
747 transaction.insert(3, item("$ev3"), Some(3));
748
749 assert_mapping! {
750 on transaction:
751
752 | event_id | event_index | timeline_item_index |
753 |----------|-------------|---------------------|
754 | "$ev0" | 0 | 1 |
755 | "$ev1" | 1 | 2 |
756 | "$ev2" | 2 | |
757 | "$ev3" | 3 | 3 | }
759
760 transaction.insert(3, item("$ev2"), Some(2));
763
764 assert_mapping! {
765 on transaction:
766
767 | event_id | event_index | timeline_item_index |
768 |----------|-------------|---------------------|
769 | "$ev0" | 0 | 1 |
770 | "$ev1" | 1 | 2 |
771 | "$ev2" | 2 | 3 | | "$ev3" | 3 | 4 | }
774
775 transaction.remove(0);
777 transaction.insert(2, read_marker(), None);
778
779 assert_mapping! {
780 on transaction:
781
782 | event_id | event_index | timeline_item_index |
783 |----------|-------------|---------------------|
784 | "$ev0" | 0 | 0 | | "$ev1" | 1 | 1 | | "$ev2" | 2 | 3 |
787 | "$ev3" | 3 | 4 |
788 }
789
790 assert_eq!(transaction.len(), 5);
791 }
792
793 #[test]
794 fn test_transaction_push_front() {
795 let mut items = ObservableItems::new();
796
797 let mut transaction = items.transaction();
798
799 transaction.push_front_remote_event(event_meta("$ev0"));
801 transaction.push_front(item("$ev0"), Some(0));
802
803 assert_mapping! {
804 on transaction:
805
806 | event_id | event_index | timeline_item_index |
807 |----------|-------------|---------------------|
808 | "$ev0" | 0 | 0 | }
810
811 transaction.push_front(read_marker(), None);
813
814 assert_mapping! {
815 on transaction:
816
817 | event_id | event_index | timeline_item_index |
818 |----------|-------------|---------------------|
819 | "$ev0" | 0 | 1 | }
821
822 transaction.push_front_remote_event(event_meta("$ev1"));
824 transaction.push_front(item("$ev1"), Some(0));
825
826 assert_mapping! {
827 on transaction:
828
829 | event_id | event_index | timeline_item_index |
830 |----------|-------------|---------------------|
831 | "$ev1" | 0 | 0 | | "$ev0" | 1 | 2 | }
834
835 transaction.push_front_remote_event(event_meta("$ev2"));
837
838 assert_mapping! {
839 on transaction:
840
841 | event_id | event_index | timeline_item_index |
842 |----------|-------------|---------------------|
843 | "$ev2" | 0 | |
844 | "$ev1" | 1 | 0 | | "$ev0" | 2 | 2 | }
847
848 transaction.push_front_remote_event(event_meta("$ev3"));
850 transaction.push_front(item("$ev3"), Some(0));
851
852 assert_mapping! {
853 on transaction:
854
855 | event_id | event_index | timeline_item_index |
856 |----------|-------------|---------------------|
857 | "$ev3" | 0 | 0 | | "$ev2" | 1 | |
859 | "$ev1" | 2 | 1 | | "$ev0" | 3 | 3 | }
862
863 assert_eq!(transaction.len(), 4);
864 }
865
866 #[test]
867 fn test_transaction_push_back() {
868 let mut items = ObservableItems::new();
869
870 let mut transaction = items.transaction();
871
872 transaction.push_back_remote_event(event_meta("$ev0"));
874 transaction.push_back(item("$ev0"), Some(0));
875
876 assert_mapping! {
877 on transaction:
878
879 | event_id | event_index | timeline_item_index |
880 |----------|-------------|---------------------|
881 | "$ev0" | 0 | 0 | }
883
884 transaction.push_back(read_marker(), None);
886
887 assert_mapping! {
888 on transaction:
889
890 | event_id | event_index | timeline_item_index |
891 |----------|-------------|---------------------|
892 | "$ev0" | 0 | 0 |
893 }
894
895 transaction.push_back_remote_event(event_meta("$ev1"));
897 transaction.push_back(item("$ev1"), Some(1));
898
899 assert_mapping! {
900 on transaction:
901
902 | event_id | event_index | timeline_item_index |
903 |----------|-------------|---------------------|
904 | "$ev0" | 0 | 0 |
905 | "$ev1" | 1 | 2 | }
907
908 transaction.push_back_remote_event(event_meta("$ev2"));
910
911 assert_mapping! {
912 on transaction:
913
914 | event_id | event_index | timeline_item_index |
915 |----------|-------------|---------------------|
916 | "$ev0" | 0 | 0 |
917 | "$ev1" | 1 | 2 |
918 | "$ev2" | 2 | | }
920
921 transaction.push_back_remote_event(event_meta("$ev3"));
923 transaction.push_back(item("$ev3"), Some(3));
924
925 assert_mapping! {
926 on transaction:
927
928 | event_id | event_index | timeline_item_index |
929 |----------|-------------|---------------------|
930 | "$ev0" | 0 | 0 |
931 | "$ev1" | 1 | 2 |
932 | "$ev2" | 2 | |
933 | "$ev3" | 3 | 3 | }
935
936 assert_eq!(transaction.len(), 4);
937 }
938
939 #[test]
940 fn test_transaction_remove() {
941 let mut items = ObservableItems::new();
942
943 let mut transaction = items.transaction();
944
945 transaction.push_back_remote_event(event_meta("$ev0"));
947 transaction.push_back(item("$ev0"), Some(0));
948
949 transaction.push_back(read_marker(), None);
951
952 transaction.push_back_remote_event(event_meta("$ev1"));
954 transaction.push_back(item("$ev1"), Some(1));
955
956 transaction.push_back_remote_event(event_meta("$ev2"));
958
959 transaction.push_back_remote_event(event_meta("$ev3"));
961 transaction.push_back(item("$ev3"), Some(3));
962
963 assert_mapping! {
964 on transaction:
965
966 | event_id | event_index | timeline_item_index |
967 |----------|-------------|---------------------|
968 | "$ev0" | 0 | 0 |
969 | "$ev1" | 1 | 2 |
970 | "$ev2" | 2 | |
971 | "$ev3" | 3 | 3 |
972 }
973
974 transaction.remove(1);
976
977 assert_mapping! {
978 on transaction:
979
980 | event_id | event_index | timeline_item_index |
981 |----------|-------------|---------------------|
982 | "$ev0" | 0 | 0 |
983 | "$ev1" | 1 | 1 | | "$ev2" | 2 | |
985 | "$ev3" | 3 | 2 | }
987
988 transaction.remove(1);
990
991 assert_mapping! {
992 on transaction:
993
994 | event_id | event_index | timeline_item_index |
995 |----------|-------------|---------------------|
996 | "$ev0" | 0 | 0 |
997 | "$ev1" | 1 | | | "$ev2" | 2 | |
999 | "$ev3" | 3 | 1 | }
1001
1002 transaction.remove(1);
1004
1005 assert_mapping! {
1006 on transaction:
1007
1008 | event_id | event_index | timeline_item_index |
1009 |----------|-------------|---------------------|
1010 | "$ev0" | 0 | 0 |
1011 | "$ev1" | 1 | |
1012 | "$ev2" | 2 | |
1013 | "$ev3" | 3 | | }
1015
1016 transaction.remove(0);
1018
1019 assert_mapping! {
1020 on transaction:
1021
1022 | event_id | event_index | timeline_item_index |
1023 |----------|-------------|---------------------|
1024 | "$ev0" | 0 | | | "$ev1" | 1 | |
1026 | "$ev2" | 2 | |
1027 | "$ev3" | 3 | |
1028 }
1029
1030 assert!(transaction.is_empty());
1031 }
1032
1033 #[test]
1034 fn test_transaction_clear() {
1035 let mut items = ObservableItems::new();
1036
1037 let mut transaction = items.transaction();
1038
1039 transaction.push_back_remote_event(event_meta("$ev0"));
1041 transaction.push_back(item("$ev0"), Some(0));
1042
1043 transaction.push_back(read_marker(), None);
1045
1046 transaction.push_back_remote_event(event_meta("$ev1"));
1048 transaction.push_back(item("$ev1"), Some(1));
1049
1050 transaction.push_back_remote_event(event_meta("$ev2"));
1052
1053 transaction.push_back_remote_event(event_meta("$ev3"));
1055 transaction.push_back(item("$ev3"), Some(3));
1056
1057 assert_mapping! {
1058 on transaction:
1059
1060 | event_id | event_index | timeline_item_index |
1061 |----------|-------------|---------------------|
1062 | "$ev0" | 0 | 0 |
1063 | "$ev1" | 1 | 2 |
1064 | "$ev2" | 2 | |
1065 | "$ev3" | 3 | 3 |
1066 }
1067
1068 assert_eq!(transaction.all_remote_events().0.len(), 4);
1069 assert_eq!(transaction.len(), 4);
1070
1071 transaction.clear();
1073
1074 assert!(transaction.all_remote_events().0.is_empty());
1075 assert!(transaction.is_empty());
1076 }
1077
1078 #[test]
1079 fn test_transaction_for_each() {
1080 let mut items = ObservableItems::new();
1081
1082 let mut transaction = items.transaction();
1084 transaction.push_back(item("$ev0"), Some(0));
1085 transaction.push_back(item("$ev1"), Some(1));
1086 transaction.push_back(item("$ev2"), Some(2));
1087
1088 let mut nth = 0;
1089
1090 transaction.for_each(|entry| {
1092 match nth {
1093 0 => {
1094 assert_event_id!(entry, "$ev0");
1095 }
1096 1 => {
1097 assert_event_id!(entry, "$ev1");
1098 }
1099 2 => {
1100 assert_event_id!(entry, "$ev2");
1101 }
1102 _ => unreachable!(),
1103 }
1104
1105 nth += 1;
1106 });
1107 }
1108
1109 #[test]
1110 fn test_transaction_for_each_remove() {
1111 let mut items = ObservableItems::new();
1112
1113 let mut transaction = items.transaction();
1115
1116 transaction.push_back_remote_event(event_meta("$ev0"));
1117 transaction.push_back(item("$ev0"), Some(0));
1118
1119 transaction.push_back_remote_event(event_meta("$ev1"));
1120 transaction.push_back(item("$ev1"), Some(1));
1121
1122 transaction.push_back_remote_event(event_meta("$ev2"));
1123 transaction.push_back(item("$ev2"), Some(2));
1124
1125 assert_mapping! {
1126 on transaction:
1127
1128 | event_id | event_index | timeline_item_index |
1129 |----------|-------------|---------------------|
1130 | "$ev0" | 0 | 0 |
1131 | "$ev1" | 1 | 1 |
1132 | "$ev2" | 2 | 2 |
1133 }
1134
1135 transaction.for_each(|entry| {
1137 if entry.as_event().unwrap().event_id().unwrap().as_str() == "$ev1" {
1138 ObservableItemsTransactionEntry::remove(entry);
1139 }
1140 });
1141
1142 assert_mapping! {
1143 on transaction:
1144
1145 | event_id | event_index | timeline_item_index |
1146 |----------|-------------|---------------------|
1147 | "$ev0" | 0 | 0 |
1148 | "$ev2" | 2 | 1 | }
1150
1151 assert_eq!(transaction.all_remote_events().0.len(), 3);
1152 assert_eq!(transaction.len(), 2);
1153 }
1154}
1155
1156#[derive(Clone, Debug, Default)]
1162pub struct AllRemoteEvents(VecDeque<EventMeta>);
1163
1164impl AllRemoteEvents {
1165 pub fn get(&self, event_index: usize) -> Option<&EventMeta> {
1167 self.0.get(event_index)
1168 }
1169
1170 pub fn iter(&self) -> Iter<'_, EventMeta> {
1172 self.0.iter()
1173 }
1174
1175 pub fn range<R>(&self, range: R) -> Iter<'_, EventMeta>
1178 where
1179 R: RangeBounds<usize>,
1180 {
1181 self.0.range(range)
1182 }
1183
1184 fn clear(&mut self) {
1186 self.0.clear();
1187 }
1188
1189 fn push_front(&mut self, event_meta: EventMeta) {
1191 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1194 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1195 }
1196
1197 self.0.push_front(event_meta)
1199 }
1200
1201 fn push_back(&mut self, event_meta: EventMeta) {
1203 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1206 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1207 }
1208
1209 self.0.push_back(event_meta)
1211 }
1212
1213 fn insert(&mut self, event_index: usize, event_meta: EventMeta) {
1215 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1218 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1219 }
1220
1221 self.0.insert(event_index, event_meta)
1223 }
1224
1225 fn remove(&mut self, event_index: usize) -> Option<EventMeta> {
1227 let event_meta = self.0.remove(event_index)?;
1229
1230 if let Some(removed_timeline_item_index) = event_meta.timeline_item_index {
1233 self.decrement_all_timeline_item_index_after(removed_timeline_item_index);
1234 };
1235
1236 Some(event_meta)
1237 }
1238
1239 pub fn last(&self) -> Option<&EventMeta> {
1241 self.0.back()
1242 }
1243
1244 pub fn last_index(&self) -> Option<usize> {
1246 self.0.len().checked_sub(1)
1247 }
1248
1249 pub fn get_by_event_id_mut(&mut self, event_id: &EventId) -> Option<&mut EventMeta> {
1251 self.0.iter_mut().rev().find(|event_meta| event_meta.event_id == event_id)
1252 }
1253
1254 pub fn get_by_event_id(&self, event_id: &EventId) -> Option<&EventMeta> {
1256 self.0.iter().rev().find(|event_meta| event_meta.event_id == event_id)
1257 }
1258
1259 fn increment_all_timeline_item_index_after(&mut self, new_timeline_item_index: usize) {
1262 for event_meta in self.0.iter_mut().rev() {
1270 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
1271 if *timeline_item_index >= new_timeline_item_index {
1272 *timeline_item_index += 1;
1273 } else {
1274 break;
1276 }
1277 }
1278 }
1279 }
1280
1281 fn decrement_all_timeline_item_index_after(&mut self, removed_timeline_item_index: usize) {
1284 for event_meta in self.0.iter_mut().rev() {
1292 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
1293 if *timeline_item_index > removed_timeline_item_index {
1294 *timeline_item_index -= 1;
1295 } else {
1296 break;
1298 }
1299 }
1300 }
1301 }
1302
1303 fn timeline_item_has_been_inserted_at(
1308 &mut self,
1309 new_timeline_item_index: usize,
1310 event_index: Option<usize>,
1311 ) {
1312 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1313
1314 if let Some(event_index) = event_index {
1315 if let Some(event_meta) = self.0.get_mut(event_index) {
1316 event_meta.timeline_item_index = Some(new_timeline_item_index);
1317 }
1318 }
1319 }
1320
1321 fn timeline_item_has_been_removed_at(&mut self, timeline_item_index_to_remove: usize) {
1324 for event_meta in self.0.iter_mut() {
1325 let mut remove_timeline_item_index = false;
1326
1327 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
1330 match (*timeline_item_index).cmp(&timeline_item_index_to_remove) {
1331 Ordering::Equal => {
1332 remove_timeline_item_index = true;
1333 }
1334
1335 Ordering::Greater => {
1336 *timeline_item_index -= 1;
1337 }
1338
1339 Ordering::Less => {}
1340 }
1341 }
1342
1343 if remove_timeline_item_index {
1346 event_meta.timeline_item_index = None;
1347 }
1348 }
1349 }
1350}
1351
1352#[cfg(test)]
1353mod all_remote_events_tests {
1354 use assert_matches::assert_matches;
1355 use ruma::event_id;
1356
1357 use super::{AllRemoteEvents, EventMeta};
1358
1359 fn event_meta(event_id: &str, timeline_item_index: Option<usize>) -> EventMeta {
1360 EventMeta { event_id: event_id.parse().unwrap(), timeline_item_index, visible: false }
1361 }
1362
1363 macro_rules! assert_events {
1364 ( $events:ident, [ $( ( $event_id:literal, $timeline_item_index:expr ) ),* $(,)? ] ) => {
1365 let mut iter = $events .iter();
1366
1367 $(
1368 assert_matches!(iter.next(), Some(EventMeta { event_id, timeline_item_index, .. }) => {
1369 assert_eq!(event_id.as_str(), $event_id );
1370 assert_eq!(*timeline_item_index, $timeline_item_index );
1371 });
1372 )*
1373
1374 assert!(iter.next().is_none(), "Not all events have been asserted");
1375 }
1376 }
1377
1378 #[test]
1379 fn test_range() {
1380 let mut events = AllRemoteEvents::default();
1381
1382 events.push_back(event_meta("$ev0", None));
1384 events.push_back(event_meta("$ev1", None));
1385 events.push_back(event_meta("$ev2", None));
1386
1387 assert_eq!(events.iter().count(), 3);
1388
1389 assert_eq!(events.range(..).count(), 3);
1391 assert_eq!(events.range(1..).count(), 2);
1392 assert_eq!(events.range(0..=1).count(), 2);
1393
1394 let mut some_events = events.range(1..);
1396
1397 assert_matches!(some_events.next(), Some(EventMeta { event_id, .. }) => {
1398 assert_eq!(event_id.as_str(), "$ev1");
1399 });
1400 assert_matches!(some_events.next(), Some(EventMeta { event_id, .. }) => {
1401 assert_eq!(event_id.as_str(), "$ev2");
1402 });
1403 assert!(some_events.next().is_none());
1404 }
1405
1406 #[test]
1407 fn test_clear() {
1408 let mut events = AllRemoteEvents::default();
1409
1410 events.push_back(event_meta("$ev0", None));
1412 events.push_back(event_meta("$ev1", None));
1413 events.push_back(event_meta("$ev2", None));
1414
1415 assert_eq!(events.iter().count(), 3);
1416
1417 events.clear();
1419
1420 assert_eq!(events.iter().count(), 0);
1421 }
1422
1423 #[test]
1424 fn test_push_front() {
1425 let mut events = AllRemoteEvents::default();
1426
1427 events.push_front(event_meta("$ev0", Some(1)));
1429
1430 events.push_front(event_meta("$ev1", None));
1432
1433 events.push_front(event_meta("$ev2", Some(0)));
1435
1436 events.push_front(event_meta("$ev3", Some(0)));
1438
1439 assert_events!(
1440 events,
1441 [
1442 ("$ev3", Some(0)),
1444 ("$ev2", Some(1)),
1446 ("$ev1", None),
1448 ("$ev0", Some(3)),
1450 ]
1451 );
1452 }
1453
1454 #[test]
1455 fn test_push_back() {
1456 let mut events = AllRemoteEvents::default();
1457
1458 events.push_back(event_meta("$ev0", Some(0)));
1460
1461 events.push_back(event_meta("$ev1", None));
1463
1464 events.push_back(event_meta("$ev2", Some(1)));
1466
1467 events.push_back(event_meta("$ev3", Some(1)));
1471
1472 assert_events!(
1473 events,
1474 [
1475 ("$ev0", Some(0)),
1477 ("$ev1", None),
1479 ("$ev2", Some(2)),
1481 ("$ev3", Some(1)),
1483 ]
1484 );
1485 }
1486
1487 #[test]
1488 fn test_insert() {
1489 let mut events = AllRemoteEvents::default();
1490
1491 events.insert(0, event_meta("$ev0", Some(0)));
1493
1494 events.insert(1, event_meta("$ev1", None));
1496
1497 events.insert(2, event_meta("$ev2", Some(1)));
1499
1500 events.insert(0, event_meta("$ev3", Some(0)));
1502
1503 assert_events!(
1504 events,
1505 [
1506 ("$ev3", Some(0)),
1508 ("$ev0", Some(1)),
1510 ("$ev1", None),
1512 ("$ev2", Some(2)),
1514 ]
1515 );
1516 }
1517
1518 #[test]
1519 fn test_remove() {
1520 let mut events = AllRemoteEvents::default();
1521
1522 events.push_back(event_meta("$ev0", Some(0)));
1524 events.push_back(event_meta("$ev1", Some(1)));
1525 events.push_back(event_meta("$ev2", None));
1526 events.push_back(event_meta("$ev3", Some(2)));
1527
1528 assert_events!(
1530 events,
1531 [("$ev0", Some(0)), ("$ev1", Some(1)), ("$ev2", None), ("$ev3", Some(2))]
1532 );
1533
1534 events.remove(2); events.remove(1); assert_events!(
1539 events,
1540 [
1541 ("$ev0", Some(0)),
1542 ("$ev3", Some(1)),
1544 ]
1545 );
1546 }
1547
1548 #[test]
1549 fn test_last() {
1550 let mut events = AllRemoteEvents::default();
1551
1552 assert!(events.last().is_none());
1553 assert!(events.last_index().is_none());
1554
1555 events.push_back(event_meta("$ev0", Some(0)));
1557 events.push_back(event_meta("$ev1", Some(1)));
1558
1559 assert_matches!(events.last(), Some(EventMeta { event_id, .. }) => {
1560 assert_eq!(event_id.as_str(), "$ev1");
1561 });
1562 assert_eq!(events.last_index(), Some(1));
1563 }
1564
1565 #[test]
1566 fn test_get_by_event_by_mut() {
1567 let mut events = AllRemoteEvents::default();
1568
1569 events.push_back(event_meta("$ev0", Some(0)));
1571 events.push_back(event_meta("$ev1", Some(1)));
1572
1573 assert!(events.get_by_event_id_mut(event_id!("$ev0")).is_some());
1574 assert!(events.get_by_event_id_mut(event_id!("$ev42")).is_none());
1575 }
1576
1577 #[test]
1578 fn test_timeline_item_has_been_inserted_at() {
1579 let mut events = AllRemoteEvents::default();
1580
1581 events.push_back(event_meta("$ev0", Some(0)));
1583 events.push_back(event_meta("$ev1", Some(1)));
1584 events.push_back(event_meta("$ev2", None));
1585 events.push_back(event_meta("$ev3", None));
1586 events.push_back(event_meta("$ev4", Some(2)));
1587 events.push_back(event_meta("$ev5", Some(3)));
1588 events.push_back(event_meta("$ev6", None));
1589
1590 events.timeline_item_has_been_inserted_at(2, None);
1592
1593 assert_events!(
1594 events,
1595 [
1596 ("$ev0", Some(0)),
1597 ("$ev1", Some(1)),
1598 ("$ev2", None),
1599 ("$ev3", None),
1600 ("$ev4", Some(3)),
1602 ("$ev5", Some(4)),
1604 ("$ev6", None),
1605 ]
1606 );
1607
1608 events.timeline_item_has_been_inserted_at(5, Some(6));
1610
1611 assert_events!(
1612 events,
1613 [
1614 ("$ev0", Some(0)),
1615 ("$ev1", Some(1)),
1616 ("$ev2", None),
1617 ("$ev3", None),
1618 ("$ev4", Some(3)),
1619 ("$ev5", Some(4)),
1620 ("$ev6", Some(5)),
1622 ]
1623 );
1624 }
1625
1626 #[test]
1627 fn test_timeline_item_has_been_removed_at() {
1628 let mut events = AllRemoteEvents::default();
1629
1630 events.push_back(event_meta("$ev0", Some(0)));
1632 events.push_back(event_meta("$ev1", Some(1)));
1633 events.push_back(event_meta("$ev2", None));
1634 events.push_back(event_meta("$ev3", None));
1635 events.push_back(event_meta("$ev4", Some(3)));
1636 events.push_back(event_meta("$ev5", Some(4)));
1637 events.push_back(event_meta("$ev6", None));
1638
1639 events.timeline_item_has_been_removed_at(2);
1641
1642 assert_events!(
1643 events,
1644 [
1645 ("$ev0", Some(0)),
1646 ("$ev1", Some(1)),
1647 ("$ev2", None),
1648 ("$ev3", None),
1649 ("$ev4", Some(2)),
1651 ("$ev5", Some(3)),
1653 ("$ev6", None),
1654 ]
1655 );
1656
1657 events.timeline_item_has_been_removed_at(2);
1659
1660 assert_events!(
1661 events,
1662 [
1663 ("$ev0", Some(0)),
1664 ("$ev1", Some(1)),
1665 ("$ev2", None),
1666 ("$ev3", None),
1667 ("$ev4", None),
1669 ("$ev5", Some(2)),
1671 ("$ev6", None),
1672 ]
1673 );
1674
1675 events.timeline_item_has_been_removed_at(0);
1677
1678 assert_events!(
1679 events,
1680 [
1681 ("$ev0", None),
1683 ("$ev1", Some(0)),
1685 ("$ev2", None),
1686 ("$ev3", None),
1687 ("$ev4", None),
1688 ("$ev5", Some(1)),
1690 ("$ev6", None),
1691 ]
1692 );
1693 }
1694}