1use super::*;
7
8#[cfg(test)]
9mod tests_helper {
10 use super::*;
11
12 #[derive(Default)]
13 pub struct TestView {
14 pub changed_rows: RefCell<Vec<usize>>,
18 pub added_rows: RefCell<Vec<(usize, usize)>>,
19 pub removed_rows: RefCell<Vec<(usize, usize)>>,
20 pub reset: RefCell<usize>,
21 }
22
23 impl TestView {
24 pub fn clear(&self) {
25 self.changed_rows.borrow_mut().clear();
26 self.added_rows.borrow_mut().clear();
27 self.removed_rows.borrow_mut().clear();
28 }
29 }
30
31 impl ModelChangeListener for TestView {
32 fn row_changed(self: Pin<&Self>, row: usize) {
33 self.changed_rows.borrow_mut().push(row);
34 }
35
36 fn row_added(self: Pin<&Self>, index: usize, count: usize) {
37 self.added_rows.borrow_mut().push((index, count));
38 }
39
40 fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
41 self.removed_rows.borrow_mut().push((index, count));
42 }
43 fn reset(self: Pin<&Self>) {
44 *self.reset.borrow_mut() += 1;
45 }
46 }
47
48 pub struct ModelChecker<Data: PartialEq + core::fmt::Debug + 'static> {
49 pub model: Rc<dyn Model<Data = Data>>,
50 pub rows_copy: RefCell<Vec<Data>>,
51 }
52
53 impl<Data: PartialEq + core::fmt::Debug + 'static> ModelChangeListener for ModelChecker<Data> {
54 fn row_changed(self: Pin<&Self>, row: usize) {
55 self.rows_copy.borrow_mut()[row] = self.model.row_data(row).unwrap();
56 }
57
58 fn row_added(self: Pin<&Self>, index: usize, count: usize) {
59 let mut copy = self.rows_copy.borrow_mut();
60 for row in index..index + count {
61 copy.insert(row, self.model.row_data(row).unwrap());
62 }
63 }
64
65 fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
66 self.rows_copy.borrow_mut().drain(index..index + count);
67 }
68 fn reset(self: Pin<&Self>) {
69 *self.rows_copy.borrow_mut() = ModelRc::from(self.model.clone()).iter().collect()
70 }
71 }
72
73 impl<Data: PartialEq + core::fmt::Debug + 'static> ModelChecker<Data> {
74 pub fn new(
75 model: Rc<impl Model<Data = Data> + 'static>,
76 ) -> Pin<Box<ModelChangeListenerContainer<Self>>> {
77 let s = Self { rows_copy: RefCell::new(model.iter().collect()), model: model.clone() };
78 let s = Box::pin(ModelChangeListenerContainer::new(s));
79 model.model_tracker().attach_peer(s.as_ref().model_peer());
80 s
81 }
82
83 #[track_caller]
84 pub fn check(&self) {
85 assert_eq!(
86 *self.rows_copy.borrow(),
87 ModelRc::from(self.model.clone()).iter().collect::<Vec<_>>()
88 );
89 }
90 }
91
92 impl<Data: PartialEq + core::fmt::Debug + 'static> Drop for ModelChecker<Data> {
93 fn drop(&mut self) {
94 self.check();
95 }
96 }
97
98 #[derive(Default)]
99 pub struct BrokenModel<T> {
100 pub data: RefCell<Vec<Option<T>>>,
101 pub notify: ModelNotify,
102 }
103
104 #[cfg(test)]
105 impl<T: Clone> Model for BrokenModel<T> {
106 type Data = T;
107
108 fn row_count(&self) -> usize {
109 self.data.borrow().len()
110 }
111
112 fn row_data(&self, row: usize) -> Option<Self::Data> {
113 self.data.borrow().get(row).and_then(|x| x.clone())
114 }
115
116 fn set_row_data(&self, row: usize, data: Self::Data) {
117 self.data.borrow_mut()[row] = Some(data);
118 self.notify.row_changed(row);
119 }
120
121 fn model_tracker(&self) -> &dyn ModelTracker {
122 &self.notify
123 }
124 }
125
126 impl<T> BrokenModel<T> {
127 pub fn new(data: Vec<Option<T>>) -> Rc<Self> {
128 Rc::new(Self { data: RefCell::new(data), notify: Default::default() })
129 }
130 }
131}
132
133pub struct MapModel<M, F> {
216 wrapped_model: M,
217 map_function: F,
218}
219
220impl<M, F, T, U> Model for MapModel<M, F>
221where
222 M: 'static,
223 F: 'static,
224 F: Fn(T) -> U,
225 M: Model<Data = T>,
226{
227 type Data = U;
228
229 fn row_count(&self) -> usize {
230 self.wrapped_model.row_count()
231 }
232
233 fn row_data(&self, row: usize) -> Option<Self::Data> {
234 self.wrapped_model.row_data(row).map(|x| (self.map_function)(x))
235 }
236
237 fn model_tracker(&self) -> &dyn ModelTracker {
238 self.wrapped_model.model_tracker()
239 }
240
241 fn as_any(&self) -> &dyn core::any::Any {
242 self
243 }
244}
245
246impl<M, F, T, U> MapModel<M, F>
247where
248 M: 'static,
249 F: 'static,
250 F: Fn(T) -> U,
251 M: Model<Data = T>,
252{
253 pub fn new(wrapped_model: M, map_function: F) -> Self {
256 Self { wrapped_model, map_function }
257 }
258
259 pub fn source_model(&self) -> &M {
261 &self.wrapped_model
262 }
263}
264
265#[test]
266fn test_map_model() {
267 use alloc::string::ToString;
268 let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3]));
269 let map = MapModel::new(wrapped_rc.clone(), |x| x.to_string());
270
271 wrapped_rc.set_row_data(2, 42);
272 wrapped_rc.push(4);
273
274 assert_eq!(map.row_data(2).unwrap(), "42");
275 assert_eq!(map.row_data(3).unwrap(), "4");
276 assert_eq!(map.row_data(1).unwrap(), "2");
277}
278
279struct FilterModelInner<M, F>
280where
281 M: Model + 'static,
282 F: Fn(&M::Data) -> bool + 'static,
283{
284 wrapped_model: M,
285 filter_function: F,
286 mapping: RefCell<Vec<usize>>,
288 notify: ModelNotify,
289}
290
291impl<M, F> FilterModelInner<M, F>
292where
293 M: Model + 'static,
294 F: Fn(&M::Data) -> bool + 'static,
295{
296 fn build_mapping_vec(&self) {
297 let mut mapping = self.mapping.borrow_mut();
298 *mapping = (0..self.wrapped_model.row_count())
299 .filter_map(|i| {
300 self.wrapped_model.row_data(i).and_then(|e| (self.filter_function)(&e).then_some(i))
301 })
302 .collect();
303 }
304}
305
306impl<M, F> ModelChangeListener for FilterModelInner<M, F>
307where
308 M: Model + 'static,
309 F: Fn(&M::Data) -> bool + 'static,
310{
311 fn row_changed(self: Pin<&Self>, row: usize) {
312 let mut mapping = self.mapping.borrow_mut();
313
314 let (index, is_contained) = match mapping.binary_search(&row) {
315 Ok(index) => (index, true),
316 Err(index) => (index, false),
317 };
318
319 let should_be_contained =
320 self.wrapped_model.row_data(row).is_some_and(|data| (self.filter_function)(&data));
321
322 if is_contained && should_be_contained {
323 drop(mapping);
324 self.notify.row_changed(index);
325 } else if !is_contained && should_be_contained {
326 mapping.insert(index, row);
327 drop(mapping);
328 self.notify.row_added(index, 1);
329 } else if is_contained && !should_be_contained {
330 mapping.remove(index);
331 drop(mapping);
332 self.notify.row_removed(index, 1);
333 }
334 }
335
336 fn row_added(self: Pin<&Self>, index: usize, count: usize) {
337 if count == 0 {
338 return;
339 }
340
341 let insertion: Vec<usize> = self
342 .wrapped_model
343 .iter()
344 .enumerate()
345 .skip(index)
346 .take(count)
347 .filter_map(|(i, e)| (self.filter_function)(&e).then_some(i))
348 .collect();
349
350 let mut mapping = self.mapping.borrow_mut();
351 let insertion_point = mapping.binary_search(&index).unwrap_or_else(|ip| ip);
352 mapping[insertion_point..].iter_mut().for_each(|i| *i += count);
353
354 if !insertion.is_empty() {
355 let insertion_len = insertion.len();
356 mapping.splice(insertion_point..insertion_point, insertion);
357
358 drop(mapping);
359 self.notify.row_added(insertion_point, insertion_len);
360 }
361 }
362
363 fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
364 if count == 0 {
365 return;
366 }
367 let mut mapping = self.mapping.borrow_mut();
368
369 let start = mapping.binary_search(&index).unwrap_or_else(|s| s);
370 let end = mapping.binary_search(&(index + count)).unwrap_or_else(|e| e);
371 let range = start..end;
372
373 mapping[end..].iter_mut().for_each(|i| *i -= count);
374
375 if !range.is_empty() {
376 mapping.drain(range.clone());
377 drop(mapping);
378 self.notify.row_removed(start, range.len());
379 }
380 }
381
382 fn reset(self: Pin<&Self>) {
383 self.build_mapping_vec();
384 self.notify.reset();
385 }
386}
387
388pub struct FilterModel<M, F>(Pin<Box<ModelChangeListenerContainer<FilterModelInner<M, F>>>>)
449where
450 M: Model + 'static,
451 F: Fn(&M::Data) -> bool + 'static;
452
453impl<M, F> FilterModel<M, F>
454where
455 M: Model + 'static,
456 F: Fn(&M::Data) -> bool + 'static,
457{
458 pub fn new(wrapped_model: M, filter_function: F) -> Self {
461 let filter_model_inner = FilterModelInner {
462 wrapped_model,
463 filter_function,
464 mapping: RefCell::new(Vec::new()),
465 notify: Default::default(),
466 };
467
468 filter_model_inner.build_mapping_vec();
469
470 let container = Box::pin(ModelChangeListenerContainer::new(filter_model_inner));
471
472 container.wrapped_model.model_tracker().attach_peer(container.as_ref().model_peer());
473
474 Self(container)
475 }
476
477 pub fn reset(&self) {
480 self.0.as_ref().get().reset();
481 }
482
483 pub fn unfiltered_row(&self, filtered_row: usize) -> usize {
485 self.0.mapping.borrow()[filtered_row]
486 }
487
488 pub fn source_model(&self) -> &M {
490 &self.0.as_ref().get().get_ref().wrapped_model
491 }
492}
493
494impl<M, F> Model for FilterModel<M, F>
495where
496 M: Model + 'static,
497 F: Fn(&M::Data) -> bool + 'static,
498{
499 type Data = M::Data;
500
501 fn row_count(&self) -> usize {
502 self.0.mapping.borrow().len()
503 }
504
505 fn row_data(&self, row: usize) -> Option<Self::Data> {
506 self.0
507 .mapping
508 .borrow()
509 .get(row)
510 .and_then(|&wrapped_row| self.0.wrapped_model.row_data(wrapped_row))
511 }
512
513 fn set_row_data(&self, row: usize, data: Self::Data) {
514 let wrapped_row = self.0.mapping.borrow()[row];
515 self.0.wrapped_model.set_row_data(wrapped_row, data);
516 }
517
518 fn model_tracker(&self) -> &dyn ModelTracker {
519 &self.0.notify
520 }
521
522 fn as_any(&self) -> &dyn core::any::Any {
523 self
524 }
525}
526
527#[test]
528fn test_filter_model() {
529 use tests_helper::*;
530 let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3, 4, 5, 6]));
531 let filter = Rc::new(FilterModel::new(wrapped_rc.clone(), |x| x % 2 == 0));
532
533 let _checker = ModelChecker::new(filter.clone());
534
535 assert_eq!(filter.row_data(0).unwrap(), 2);
536 assert_eq!(filter.row_data(1).unwrap(), 4);
537 assert_eq!(filter.row_data(2).unwrap(), 6);
538 assert_eq!(filter.row_count(), 3);
539
540 wrapped_rc.remove(1);
541 assert_eq!(filter.row_data(0).unwrap(), 4);
542 assert_eq!(filter.row_data(1).unwrap(), 6);
543 assert_eq!(filter.row_count(), 2);
544
545 wrapped_rc.push(8);
546 wrapped_rc.push(7);
547 assert_eq!(filter.row_data(0).unwrap(), 4);
548 assert_eq!(filter.row_data(1).unwrap(), 6);
549 assert_eq!(filter.row_data(2).unwrap(), 8);
550 assert_eq!(filter.row_count(), 3);
551
552 wrapped_rc.set_row_data(1, 2);
553 assert_eq!(filter.row_data(0).unwrap(), 2);
554 assert_eq!(filter.row_data(1).unwrap(), 4);
555 assert_eq!(filter.row_data(2).unwrap(), 6);
556 assert_eq!(filter.row_data(3).unwrap(), 8);
557 assert_eq!(filter.row_count(), 4);
558
559 wrapped_rc.insert(2, 12);
560 assert_eq!(filter.row_data(0).unwrap(), 2);
561 assert_eq!(filter.row_data(1).unwrap(), 12);
562 assert_eq!(filter.row_data(2).unwrap(), 4);
563 assert_eq!(filter.row_data(3).unwrap(), 6);
564 assert_eq!(filter.row_data(4).unwrap(), 8);
565 assert_eq!(filter.row_count(), 5);
566}
567
568#[test]
569fn test_filter_model_source_model() {
570 use tests_helper::*;
571 let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3, 4]));
572 let model = Rc::new(FilterModel::new(wrapped_rc.clone(), |x| x % 2 == 0));
573
574 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
575 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
576
577 let _checker = ModelChecker::new(model.clone());
578
579 model.source_model().push(5);
580 model.source_model().push(6);
581
582 let expected = &[2, 4, 6];
583 assert_eq!(model.row_count(), expected.len());
584 for (i, v) in expected.iter().enumerate() {
585 assert_eq!(model.row_data(i), Some(*v), "Expected {v} at index {i}");
586 }
587}
588
589#[test]
590fn test_filter_model_broken_model() {
591 use tests_helper::*;
592 let wrapped_rc = BrokenModel::new(std::vec![Some(1), Some(2), None, Some(3), None, Some(4)]);
593 let model = Rc::new(FilterModel::new(wrapped_rc.clone(), |x| x % 2 == 0));
594
595 assert_eq!(model.row_count(), 2);
596 assert_eq!(model.row_data(0), Some(2));
597 assert_eq!(model.row_data(1), Some(4));
598
599 wrapped_rc.notify.row_removed(1, 2);
600 wrapped_rc.notify.row_added(1, 2);
601 wrapped_rc.data.borrow_mut()[1] = None;
602 wrapped_rc.data.borrow_mut()[2] = Some(8);
603 wrapped_rc.notify.row_changed(1);
604 wrapped_rc.notify.row_changed(2);
605
606 assert_eq!(model.row_count(), 2);
607 assert_eq!(model.row_data(0), Some(8));
608 assert_eq!(model.row_data(1), Some(4));
609}
610
611pub trait SortHelper<D> {
612 fn cmp(&mut self, lhs: &D, rhs: &D) -> core::cmp::Ordering;
613}
614
615pub struct AscendingSortHelper;
616
617impl<D> SortHelper<D> for AscendingSortHelper
618where
619 D: core::cmp::Ord,
620{
621 fn cmp(&mut self, lhs: &D, rhs: &D) -> core::cmp::Ordering {
622 lhs.cmp(rhs)
623 }
624}
625
626impl<F, D> SortHelper<D> for F
627where
628 F: FnMut(&D, &D) -> core::cmp::Ordering + 'static,
629{
630 fn cmp(&mut self, lhs: &D, rhs: &D) -> core::cmp::Ordering {
631 (self)(lhs, rhs)
632 }
633}
634
635struct SortModelInner<M, S>
636where
637 M: Model + 'static,
638 S: SortHelper<M::Data> + 'static,
639{
640 wrapped_model: M,
641 sort_helper: RefCell<S>,
642 mapping: RefCell<Vec<usize>>,
644 notify: ModelNotify,
645 sorted_rows_dirty: Cell<bool>,
646}
647
648impl<M, S> SortModelInner<M, S>
649where
650 M: Model + 'static,
651 S: SortHelper<M::Data>,
652{
653 fn build_mapping_vec(&self) {
654 if !self.sorted_rows_dirty.get() {
655 return;
656 }
657
658 let mut mapping = self.mapping.borrow_mut();
659
660 mapping.clear();
661 mapping.extend(0..self.wrapped_model.row_count());
662 mapping.sort_by(|lhs, rhs| {
663 let Some(lhs) = self.wrapped_model.row_data(*lhs) else {
664 return core::cmp::Ordering::Greater;
665 };
666 let Some(rhs) = self.wrapped_model.row_data(*rhs) else {
667 return core::cmp::Ordering::Less;
668 };
669 self.sort_helper.borrow_mut().cmp(&lhs, &rhs)
670 });
671
672 self.sorted_rows_dirty.set(false);
673 }
674}
675
676impl<M, S> ModelChangeListener for SortModelInner<M, S>
677where
678 M: Model + 'static,
679 S: SortHelper<M::Data> + 'static,
680{
681 fn row_changed(self: Pin<&Self>, row: usize) {
682 if self.sorted_rows_dirty.get() {
683 self.reset();
684 return;
685 }
686
687 let mut mapping = self.mapping.borrow_mut();
688 let removed_index = mapping.iter().position(|r| *r == row).unwrap();
689 mapping.remove(removed_index);
690
691 let insertion_index = if let Some(changed_data) = self.wrapped_model.row_data(row) {
692 mapping.partition_point(|existing_row| {
693 self.wrapped_model.row_data(*existing_row).is_some_and(|existing| {
694 self.sort_helper.borrow_mut().cmp(&existing, &changed_data)
695 == core::cmp::Ordering::Less
696 })
697 })
698 } else {
699 mapping.len()
700 };
701
702 mapping.insert(insertion_index, row);
703
704 drop(mapping);
705
706 if insertion_index == removed_index {
707 self.notify.row_changed(removed_index);
708 } else {
709 self.notify.row_removed(removed_index, 1);
710 self.notify.row_added(insertion_index, 1);
711 }
712 }
713
714 fn row_added(self: Pin<&Self>, index: usize, count: usize) {
715 if count == 0 {
716 return;
717 }
718
719 if self.sorted_rows_dirty.get() {
720 self.reset();
721 return;
722 }
723
724 for row in self.mapping.borrow_mut().iter_mut() {
726 if *row >= index {
727 *row += count;
728 }
729 }
730
731 for row in index..(index + count) {
732 let insertion_index = if let Some(added_data) = self.wrapped_model.row_data(row) {
733 self.mapping.borrow().partition_point(|existing_row| {
734 self.wrapped_model.row_data(*existing_row).is_some_and(|existing| {
735 self.sort_helper.borrow_mut().cmp(&existing, &added_data)
736 == core::cmp::Ordering::Less
737 })
738 })
739 } else {
740 self.mapping.borrow().len()
741 };
742 self.mapping.borrow_mut().insert(insertion_index, row);
743 self.notify.row_added(insertion_index, 1)
744 }
745 }
746
747 fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
748 if count == 0 {
749 return;
750 }
751
752 if self.sorted_rows_dirty.get() {
753 self.reset();
754 return;
755 }
756
757 let mut removed_rows = Vec::new();
758
759 let mut i = 0;
760
761 loop {
762 if i >= self.mapping.borrow().len() {
763 break;
764 }
765
766 let sort_index = self.mapping.borrow()[i];
767
768 if sort_index >= index {
769 if sort_index < index + count {
770 removed_rows.push(i);
771 self.mapping.borrow_mut().remove(i);
772 continue;
773 } else {
774 self.mapping.borrow_mut()[i] -= count;
775 }
776 }
777
778 i += 1;
779 }
780
781 for removed_row in removed_rows {
782 self.notify.row_removed(removed_row, 1);
783 }
784 }
785
786 fn reset(self: Pin<&Self>) {
787 self.sorted_rows_dirty.set(true);
788 self.notify.reset();
789 }
790}
791
792pub struct SortModel<M, F>(Pin<Box<ModelChangeListenerContainer<SortModelInner<M, F>>>>)
886where
887 M: Model + 'static,
888 F: SortHelper<M::Data> + 'static;
889
890impl<M, F> SortModel<M, F>
891where
892 M: Model + 'static,
893 F: FnMut(&M::Data, &M::Data) -> core::cmp::Ordering + 'static,
894{
895 pub fn new(wrapped_model: M, sort_function: F) -> Self
898 where
899 F: FnMut(&M::Data, &M::Data) -> core::cmp::Ordering + 'static,
900 {
901 let sorted_model_inner = SortModelInner {
902 wrapped_model,
903 sort_helper: RefCell::new(sort_function),
904 mapping: RefCell::new(Vec::new()),
905 notify: Default::default(),
906 sorted_rows_dirty: Cell::new(true),
907 };
908
909 let container = Box::pin(ModelChangeListenerContainer::new(sorted_model_inner));
910
911 container.wrapped_model.model_tracker().attach_peer(container.as_ref().model_peer());
912
913 Self(container)
914 }
915
916 pub fn source_model(&self) -> &M {
918 &self.0.as_ref().get().get_ref().wrapped_model
919 }
920}
921
922impl<M> SortModel<M, AscendingSortHelper>
923where
924 M: Model + 'static,
925 M::Data: core::cmp::Ord,
926{
927 pub fn new_ascending(wrapped_model: M) -> Self
930 where
931 M::Data: core::cmp::Ord,
932 {
933 let sorted_model_inner = SortModelInner {
934 wrapped_model,
935 sort_helper: RefCell::new(AscendingSortHelper),
936 mapping: RefCell::new(Vec::new()),
937 notify: Default::default(),
938 sorted_rows_dirty: Cell::new(true),
939 };
940
941 let container = Box::pin(ModelChangeListenerContainer::new(sorted_model_inner));
942
943 container.wrapped_model.model_tracker().attach_peer(container.as_ref().model_peer());
944
945 Self(container)
946 }
947
948 pub fn reset(&self) {
951 self.0.as_ref().get().reset();
952 }
953
954 pub fn unsorted_row(&self, sorted_row: usize) -> usize {
956 self.0.build_mapping_vec();
957 self.0.mapping.borrow()[sorted_row]
958 }
959}
960
961impl<M, S> Model for SortModel<M, S>
962where
963 M: Model + 'static,
964 S: SortHelper<M::Data>,
965{
966 type Data = M::Data;
967
968 fn row_count(&self) -> usize {
969 self.0.wrapped_model.row_count()
970 }
971
972 fn row_data(&self, row: usize) -> Option<Self::Data> {
973 self.0.build_mapping_vec();
974
975 self.0
976 .mapping
977 .borrow()
978 .get(row)
979 .and_then(|&wrapped_row| self.0.wrapped_model.row_data(wrapped_row))
980 }
981
982 fn set_row_data(&self, row: usize, data: Self::Data) {
983 let wrapped_row = self.0.mapping.borrow()[row];
984 self.0.wrapped_model.set_row_data(wrapped_row, data);
985 }
986
987 fn model_tracker(&self) -> &dyn ModelTracker {
988 &self.0.notify
989 }
990
991 fn as_any(&self) -> &dyn core::any::Any {
992 self
993 }
994}
995
996#[cfg(test)]
997mod sort_tests {
998 use super::*;
999 use std::vec;
1000 use tests_helper::*;
1001
1002 #[test]
1003 fn test_sorted_model_insert() {
1004 let wrapped_rc = Rc::new(VecModel::from(std::vec![3, 4, 1, 2]));
1005 let sorted_model = Rc::new(SortModel::new(wrapped_rc.clone(), |lhs, rhs| lhs.cmp(rhs)));
1006
1007 let _checker = ModelChecker::new(sorted_model.clone());
1008
1009 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1010 sorted_model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1011
1012 assert_eq!(sorted_model.row_count(), 4);
1013 assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1014 assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1015 assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1016 assert_eq!(sorted_model.row_data(3).unwrap(), 4);
1017
1018 wrapped_rc.insert(0, 10);
1019
1020 assert_eq!(observer.added_rows.borrow().len(), 1);
1021 assert!(observer.added_rows.borrow().eq(&[(4, 1)]));
1022 assert!(observer.changed_rows.borrow().is_empty());
1023 assert!(observer.removed_rows.borrow().is_empty());
1024 assert_eq!(*observer.reset.borrow(), 0);
1025 observer.clear();
1026
1027 assert_eq!(sorted_model.row_count(), 5);
1028 assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1029 assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1030 assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1031 assert_eq!(sorted_model.row_data(3).unwrap(), 4);
1032 assert_eq!(sorted_model.row_data(4).unwrap(), 10);
1033 }
1034
1035 #[test]
1036 fn test_sorted_model_remove() {
1037 let wrapped_rc = Rc::new(VecModel::from(vec![3, 4, 1, 2]));
1038 let sorted_model = Rc::new(SortModel::new(wrapped_rc.clone(), |lhs, rhs| lhs.cmp(rhs)));
1039
1040 let _checker = ModelChecker::new(sorted_model.clone());
1041
1042 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1043 sorted_model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1044
1045 assert_eq!(sorted_model.row_count(), 4);
1046 assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1047 assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1048 assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1049 assert_eq!(sorted_model.row_data(3).unwrap(), 4);
1050
1051 wrapped_rc.remove(1);
1053
1054 assert!(observer.added_rows.borrow().is_empty());
1055 assert!(observer.changed_rows.borrow().is_empty());
1056 assert_eq!(observer.removed_rows.borrow().len(), 1);
1057 assert!(observer.removed_rows.borrow().eq(&[(3, 1)]));
1058 assert_eq!(*observer.reset.borrow(), 0);
1059 observer.clear();
1060
1061 assert_eq!(sorted_model.row_count(), 3);
1062 assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1063 assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1064 assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1065 }
1066
1067 #[test]
1068 fn test_sorted_model_changed() {
1069 let wrapped_rc = Rc::new(VecModel::from(vec![3, 4, 1, 2]));
1070 let sorted_model = Rc::new(SortModel::new(wrapped_rc.clone(), |lhs, rhs| lhs.cmp(rhs)));
1071
1072 let _checker = ModelChecker::new(sorted_model.clone());
1073
1074 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1075 sorted_model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1076
1077 assert_eq!(sorted_model.row_count(), 4);
1078 assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1079 assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1080 assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1081 assert_eq!(sorted_model.row_data(3).unwrap(), 4);
1082
1083 wrapped_rc.set_row_data(1, 10);
1085
1086 assert!(observer.added_rows.borrow().is_empty());
1087 assert_eq!(observer.changed_rows.borrow().len(), 1);
1088 assert_eq!(*observer.changed_rows.borrow().first().unwrap(), 3);
1089 assert!(observer.removed_rows.borrow().is_empty());
1090 assert_eq!(*observer.reset.borrow(), 0);
1091 observer.clear();
1092
1093 assert_eq!(sorted_model.row_count(), 4);
1094 assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1095 assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1096 assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1097 assert_eq!(sorted_model.row_data(3).unwrap(), 10);
1098
1099 wrapped_rc.set_row_data(1, 0);
1101
1102 assert_eq!(observer.added_rows.borrow().len(), 1);
1103 assert!(observer.added_rows.borrow().first().unwrap().eq(&(0, 1)));
1104 assert!(observer.changed_rows.borrow().is_empty());
1105 assert_eq!(observer.removed_rows.borrow().len(), 1);
1106 assert!(observer.removed_rows.borrow().first().unwrap().eq(&(3, 1)));
1107 assert_eq!(*observer.reset.borrow(), 0);
1108 observer.clear();
1109
1110 assert_eq!(sorted_model.row_count(), 4);
1111 assert_eq!(sorted_model.row_data(0).unwrap(), 0);
1112 assert_eq!(sorted_model.row_data(1).unwrap(), 1);
1113 assert_eq!(sorted_model.row_data(2).unwrap(), 2);
1114 assert_eq!(sorted_model.row_data(3).unwrap(), 3);
1115 }
1116
1117 #[test]
1118 fn test_sorted_model_source_model() {
1119 let wrapped_rc = Rc::new(VecModel::from(vec![3, 4, 1, 2]));
1120 let model = Rc::new(SortModel::new(wrapped_rc.clone(), |lhs, rhs| lhs.cmp(rhs)));
1121 let _checker = ModelChecker::new(model.clone());
1122
1123 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1124 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1125
1126 model.source_model().push(6);
1127 model.source_model().push(5);
1128
1129 let expected = &[1, 2, 3, 4, 5, 6];
1130 assert_eq!(model.row_count(), expected.len());
1131 for (i, v) in expected.iter().enumerate() {
1132 assert_eq!(model.row_data(i), Some(*v), "Expected {v} at index {i}");
1133 }
1134 }
1135
1136 #[test]
1137 fn test_sorted_broken_model() {
1138 let wrapped_rc = BrokenModel::new(std::vec![
1139 Some("1"),
1140 Some("2"),
1141 None,
1142 Some("4"),
1143 None,
1144 Some("3"),
1145 Some("0"),
1146 Some("5")
1147 ]);
1148 let model = Rc::new(SortModel::new_ascending(wrapped_rc.clone()));
1149
1150 assert_eq!(model.row_count(), 8);
1151 assert_eq!(model.row_data(0), Some("0"));
1152 assert_eq!(model.row_data(1), Some("1"));
1153 assert_eq!(model.row_data(2), Some("2"));
1154 assert_eq!(model.row_data(3), Some("3"));
1155 assert_eq!(model.row_data(4), Some("4"));
1156 assert_eq!(model.row_data(5), Some("5"));
1157 assert_eq!(model.row_data(6), None);
1158 assert_eq!(model.row_data(7), None);
1159
1160 wrapped_rc.notify.row_removed(2, 2);
1161 wrapped_rc.notify.row_added(2, 2);
1162 wrapped_rc.data.borrow_mut()[1] = None;
1163 wrapped_rc.notify.row_changed(1);
1164 wrapped_rc.data.borrow_mut()[2] = Some("a");
1165 wrapped_rc.notify.row_changed(2);
1166
1167 assert_eq!(model.row_count(), 8);
1168 assert_eq!(model.row_data(0), Some("0"));
1169 assert_eq!(model.row_data(1), Some("1"));
1170 assert_eq!(model.row_data(2), Some("3"));
1171 assert_eq!(model.row_data(3), Some("4"));
1172 assert_eq!(model.row_data(4), Some("5"));
1173 assert_eq!(model.row_data(5), Some("a"));
1174 assert_eq!(model.row_data(6), None);
1175 assert_eq!(model.row_data(7), None);
1176 }
1177}
1178
1179pub struct ReverseModel<M>(Pin<Box<ModelChangeListenerContainer<ReverseModelInner<M>>>>)
1243where
1244 M: Model + 'static;
1245
1246struct ReverseModelInner<M>
1247where
1248 M: Model + 'static,
1249{
1250 wrapped_model: M,
1251 notify: ModelNotify,
1252}
1253
1254impl<M> ModelChangeListener for ReverseModelInner<M>
1255where
1256 M: Model + 'static,
1257{
1258 fn row_changed(self: Pin<&Self>, row: usize) {
1259 self.notify.row_changed(self.wrapped_model.row_count() - 1 - row);
1260 }
1261
1262 fn row_added(self: Pin<&Self>, index: usize, count: usize) {
1263 let row_count = self.wrapped_model.row_count();
1264 let old_row_count = row_count - count;
1265 let index = old_row_count - index;
1266 self.notify.row_added(index, count);
1267 }
1268
1269 fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
1270 let row_count = self.wrapped_model.row_count();
1271 self.notify.row_removed(row_count - index, count);
1272 }
1273
1274 fn reset(self: Pin<&Self>) {
1275 self.notify.reset()
1276 }
1277}
1278
1279impl<M> ReverseModel<M>
1280where
1281 M: Model + 'static,
1282{
1283 pub fn new(wrapped_model: M) -> Self {
1286 let inner = ReverseModelInner { wrapped_model, notify: Default::default() };
1287 let container = Box::pin(ModelChangeListenerContainer::new(inner));
1288 container.wrapped_model.model_tracker().attach_peer(container.as_ref().model_peer());
1289 Self(container)
1290 }
1291
1292 pub fn source_model(&self) -> &M {
1294 &self.0.as_ref().get().get_ref().wrapped_model
1295 }
1296}
1297
1298impl<M> Model for ReverseModel<M>
1299where
1300 M: Model + 'static,
1301{
1302 type Data = M::Data;
1303
1304 fn row_count(&self) -> usize {
1305 self.0.wrapped_model.row_count()
1306 }
1307
1308 fn row_data(&self, row: usize) -> Option<Self::Data> {
1309 let count = self.0.wrapped_model.row_count();
1310 self.0.wrapped_model.row_data(count.checked_sub(row + 1)?)
1311 }
1312 fn set_row_data(&self, row: usize, data: Self::Data) {
1313 let count = self.0.as_ref().wrapped_model.row_count();
1314 self.0.wrapped_model.set_row_data(count - row - 1, data);
1315 }
1316
1317 fn model_tracker(&self) -> &dyn ModelTracker {
1318 &self.0.notify
1319 }
1320
1321 fn as_any(&self) -> &dyn core::any::Any {
1322 self
1323 }
1324}
1325
1326#[cfg(test)]
1327mod reversed_tests {
1328 use super::*;
1329 use std::vec;
1330 use tests_helper::*;
1331
1332 #[track_caller]
1333 fn check_content(model: &ReverseModel<Rc<VecModel<i32>>>, expected: &[i32]) {
1334 assert_eq!(model.row_count(), expected.len());
1335 for (i, v) in expected.iter().enumerate() {
1336 assert_eq!(model.row_data(i), Some(*v), "Expected {v} at index {i}");
1337 }
1338 }
1339
1340 #[test]
1341 fn test_reversed_model() {
1342 let wrapped_rc = Rc::new(VecModel::from(vec![1, 2, 3, 4]));
1343 let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1344 let _checker = ModelChecker::new(model.clone());
1345
1346 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1347 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1348
1349 check_content(&model, &[4, 3, 2, 1]);
1350 }
1351
1352 #[test]
1353 fn test_reversed_model_insert() {
1354 for (idx, mapped_idx) in [(0, 4), (1, 3), (2, 2), (3, 1), (4, 0)] {
1355 std::println!("Inserting at {idx} expecting mapped to {mapped_idx}");
1356 let wrapped_rc = Rc::new(VecModel::from(vec![1, 2, 3, 4]));
1357 let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1358 let _checker = ModelChecker::new(model.clone());
1359
1360 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1361 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1362
1363 wrapped_rc.insert(idx, 10);
1364
1365 assert_eq!(observer.added_rows.borrow().len(), 1);
1366 assert!(
1367 observer.added_rows.borrow().eq(&[(mapped_idx, 1)]),
1368 "Added rows: {:?}",
1369 observer.added_rows.borrow()
1370 );
1371 assert!(observer.changed_rows.borrow().is_empty());
1372 assert!(observer.removed_rows.borrow().is_empty());
1373 assert_eq!(*observer.reset.borrow(), 0);
1374 assert_eq!(model.row_data(mapped_idx), Some(10));
1375 }
1376 }
1377
1378 #[test]
1379 fn test_reversed_model_remove() {
1380 for (idx, mapped_idx) in [(0, 3), (1, 2), (2, 1), (3, 0)] {
1381 std::println!("Removing at {idx} expecting mapped to {mapped_idx}");
1382 let wrapped_rc = Rc::new(VecModel::from(vec![1, 2, 3, 4]));
1383 let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1384 let _checker = ModelChecker::new(model.clone());
1385
1386 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1387 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1388
1389 wrapped_rc.remove(idx);
1390
1391 assert_eq!(observer.removed_rows.borrow().len(), 1);
1392 assert!(
1393 observer.removed_rows.borrow().eq(&[(mapped_idx, 1)]),
1394 "Remove rows: {:?}",
1395 observer.removed_rows.borrow()
1396 );
1397 assert!(observer.added_rows.borrow().is_empty());
1398 assert!(observer.changed_rows.borrow().is_empty());
1399 assert_eq!(*observer.reset.borrow(), 0);
1400 }
1401 }
1402
1403 #[test]
1404 fn test_reversed_model_changed() {
1405 for (idx, mapped_idx) in [(0, 3), (1, 2), (2, 1), (3, 0)] {
1406 std::println!("Changing at {idx} expecting mapped to {mapped_idx}");
1407 let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3, 4]));
1408 let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1409 let _checker = ModelChecker::new(model.clone());
1410
1411 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1412 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1413
1414 wrapped_rc.set_row_data(idx, 10);
1415
1416 assert_eq!(observer.changed_rows.borrow().len(), 1);
1417 assert!(
1418 observer.changed_rows.borrow().eq(&[mapped_idx]),
1419 "Changed rows: {:?}",
1420 observer.changed_rows.borrow()
1421 );
1422 assert!(observer.added_rows.borrow().is_empty());
1423 assert!(observer.removed_rows.borrow().is_empty());
1424 assert_eq!(*observer.reset.borrow(), 0);
1425 assert_eq!(model.row_data(mapped_idx), Some(10));
1426 }
1427 }
1428
1429 #[test]
1430 fn test_reversed_model_source_model() {
1431 let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3, 4]));
1432 let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1433 let _checker = ModelChecker::new(model.clone());
1434
1435 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1436 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1437
1438 model.source_model().push(5);
1439
1440 check_content(&model, &[5, 4, 3, 2, 1]);
1441 }
1442
1443 #[test]
1444 fn test_reversed_broken_model() {
1445 let wrapped_rc = BrokenModel::new(std::vec![Some("1"), Some("2"), None, Some("4")]);
1446 let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1447
1448 wrapped_rc.notify.row_added(1, 3);
1449
1450 assert_eq!(model.row_count(), 4);
1451 assert_eq!(model.row_data(0), Some("4"));
1452 assert_eq!(model.row_data(1), None);
1453 assert_eq!(model.row_data(2), Some("2"));
1454 assert_eq!(model.row_data(3), Some("1"));
1455 }
1456}
1457
1458#[test]
1459fn test_long_chain_integrity() {
1460 use alloc::string::ToString;
1461 use tests_helper::*;
1462 let origin_model = Rc::new(VecModel::from((0..100).collect::<Vec<_>>()));
1463 let checker1 = ModelChecker::new(origin_model.clone());
1464 let fizzbuzz = Rc::new(MapModel::new(origin_model.clone(), |number| {
1465 if (number % 3) == 0 && (number % 5) == 0 {
1466 "FizzBuzz".to_string()
1467 } else if (number % 3) == 0 {
1468 "Fizz".to_string()
1469 } else if (number % 5) == 0 {
1470 "Buzz".to_string()
1471 } else {
1472 number.to_string()
1473 }
1474 }));
1475 let checker2 = ModelChecker::new(fizzbuzz.clone());
1476 let filter = Rc::new(FilterModel::new(fizzbuzz, |s| s != "FizzBuzz"));
1477 let checker3 = ModelChecker::new(filter.clone());
1478 let reverse = Rc::new(ReverseModel::new(filter));
1479 let checker4 = ModelChecker::new(reverse.clone());
1480 let sorted = Rc::new(SortModel::new_ascending(reverse));
1481 let checker5 = ModelChecker::new(sorted.clone());
1482 let filter2 = Rc::new(FilterModel::new(sorted, |s| s != "Fizz"));
1483 let checker6 = ModelChecker::new(filter2.clone());
1484
1485 let check_all = || {
1486 checker1.check();
1487 checker2.check();
1488 checker3.check();
1489 checker4.check();
1490 checker5.check();
1491 checker6.check();
1492 };
1493
1494 origin_model.extend(50..150);
1495 check_all();
1496 origin_model.insert(8, 1000);
1497 check_all();
1498 origin_model.remove(9);
1499 check_all();
1500 origin_model.remove(10);
1501 origin_model.remove(11);
1502 origin_model.set_row_data(55, 10001);
1503 check_all();
1504 origin_model.set_row_data(58, 10002);
1505 origin_model.set_row_data(59, 10003);
1506 origin_model.remove(28);
1507 origin_model.remove(29);
1508 origin_model.insert(100, 8888);
1509 origin_model.remove(30);
1510 origin_model.set_row_data(60, 10004);
1511 origin_model.remove(130);
1512 origin_model.set_row_data(61, 10005);
1513 origin_model.remove(131);
1514 check_all();
1515 origin_model.remove(12);
1516 origin_model.remove(13);
1517 origin_model.remove(14);
1518 origin_model.set_row_data(62, 10006);
1519 origin_model.set_row_data(63, 10007);
1520 origin_model.set_row_data(64, 10008);
1521 origin_model.set_row_data(65, 10009);
1522 check_all();
1523
1524 trait RemoveRange {
1526 fn remove_range(&self, range: core::ops::Range<usize>);
1527 }
1528 impl<T> RemoveRange for VecModel<T> {
1529 fn remove_range(&self, range: core::ops::Range<usize>) {
1530 self.array.borrow_mut().drain(range.clone());
1531 self.notify.row_removed(range.start, range.len())
1532 }
1533 }
1534
1535 origin_model.remove_range(25..110);
1536 check_all();
1537
1538 origin_model.extend(900..910);
1539 origin_model.set_row_data(45, 44444);
1540 origin_model.remove_range(10..30);
1541 origin_model.insert(45, 3000);
1542 origin_model.insert(45, 3001);
1543 origin_model.insert(45, 3002);
1544 origin_model.insert(45, 3003);
1545 origin_model.insert(45, 3004);
1546 origin_model.insert(45, 3006);
1547 origin_model.insert(45, 3007);
1548 check_all();
1549}