1use super::*;
7
8#[cfg(test)]
9#[derive(Default)]
10struct TestView {
11 changed_rows: RefCell<Vec<usize>>,
15 added_rows: RefCell<Vec<(usize, usize)>>,
16 removed_rows: RefCell<Vec<(usize, usize)>>,
17 reset: RefCell<usize>,
18}
19
20#[cfg(test)]
21impl TestView {
22 fn clear(&self) {
23 self.changed_rows.borrow_mut().clear();
24 self.added_rows.borrow_mut().clear();
25 self.removed_rows.borrow_mut().clear();
26 }
27}
28
29#[cfg(test)]
30impl ModelChangeListener for TestView {
31 fn row_changed(self: Pin<&Self>, row: usize) {
32 self.changed_rows.borrow_mut().push(row);
33 }
34
35 fn row_added(self: Pin<&Self>, index: usize, count: usize) {
36 self.added_rows.borrow_mut().push((index, count));
37 }
38
39 fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
40 self.removed_rows.borrow_mut().push((index, count));
41 }
42 fn reset(self: Pin<&Self>) {
43 *self.reset.borrow_mut() += 1;
44 }
45}
46
47#[cfg(test)]
48struct ModelChecker<Data: PartialEq + core::fmt::Debug + 'static> {
49 model: Rc<dyn Model<Data = Data>>,
50 rows_copy: RefCell<Vec<Data>>,
51}
52
53#[cfg(test)]
54impl<Data: PartialEq + core::fmt::Debug + 'static> ModelChangeListener for ModelChecker<Data> {
55 fn row_changed(self: Pin<&Self>, row: usize) {
56 self.rows_copy.borrow_mut()[row] = self.model.row_data(row).unwrap();
57 }
58
59 fn row_added(self: Pin<&Self>, index: usize, count: usize) {
60 let mut copy = self.rows_copy.borrow_mut();
61 for row in index..index + count {
62 copy.insert(row, self.model.row_data(row).unwrap());
63 }
64 }
65
66 fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
67 self.rows_copy.borrow_mut().drain(index..index + count);
68 }
69 fn reset(self: Pin<&Self>) {
70 *self.rows_copy.borrow_mut() = ModelRc::from(self.model.clone()).iter().collect()
71 }
72}
73
74#[cfg(test)]
75impl<Data: PartialEq + core::fmt::Debug + 'static> ModelChecker<Data> {
76 pub fn new(
77 model: Rc<impl Model<Data = Data> + 'static>,
78 ) -> Pin<Box<ModelChangeListenerContainer<Self>>> {
79 let s = Self { rows_copy: RefCell::new(model.iter().collect()), model: model.clone() };
80 let s = Box::pin(ModelChangeListenerContainer::new(s));
81 model.model_tracker().attach_peer(s.as_ref().model_peer());
82 s
83 }
84
85 #[track_caller]
86 pub fn check(&self) {
87 assert_eq!(
88 *self.rows_copy.borrow(),
89 ModelRc::from(self.model.clone()).iter().collect::<Vec<_>>()
90 );
91 }
92}
93
94#[cfg(test)]
95impl<Data: PartialEq + core::fmt::Debug + 'static> Drop for ModelChecker<Data> {
96 fn drop(&mut self) {
97 self.check();
98 }
99}
100
101pub struct MapModel<M, F> {
184 wrapped_model: M,
185 map_function: F,
186}
187
188impl<M, F, T, U> Model for MapModel<M, F>
189where
190 M: 'static,
191 F: 'static,
192 F: Fn(T) -> U,
193 M: Model<Data = T>,
194{
195 type Data = U;
196
197 fn row_count(&self) -> usize {
198 self.wrapped_model.row_count()
199 }
200
201 fn row_data(&self, row: usize) -> Option<Self::Data> {
202 self.wrapped_model.row_data(row).map(|x| (self.map_function)(x))
203 }
204
205 fn model_tracker(&self) -> &dyn ModelTracker {
206 self.wrapped_model.model_tracker()
207 }
208
209 fn as_any(&self) -> &dyn core::any::Any {
210 self
211 }
212}
213
214impl<M, F, T, U> MapModel<M, F>
215where
216 M: 'static,
217 F: 'static,
218 F: Fn(T) -> U,
219 M: Model<Data = T>,
220{
221 pub fn new(wrapped_model: M, map_function: F) -> Self {
224 Self { wrapped_model, map_function }
225 }
226
227 pub fn source_model(&self) -> &M {
229 &self.wrapped_model
230 }
231}
232
233#[test]
234fn test_map_model() {
235 use alloc::string::ToString;
236 let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3]));
237 let map = MapModel::new(wrapped_rc.clone(), |x| x.to_string());
238
239 wrapped_rc.set_row_data(2, 42);
240 wrapped_rc.push(4);
241
242 assert_eq!(map.row_data(2).unwrap(), "42");
243 assert_eq!(map.row_data(3).unwrap(), "4");
244 assert_eq!(map.row_data(1).unwrap(), "2");
245}
246
247struct FilterModelInner<M, F>
248where
249 M: Model + 'static,
250 F: Fn(&M::Data) -> bool + 'static,
251{
252 wrapped_model: M,
253 filter_function: F,
254 mapping: RefCell<Vec<usize>>,
256 notify: ModelNotify,
257}
258
259impl<M, F> FilterModelInner<M, F>
260where
261 M: Model + 'static,
262 F: Fn(&M::Data) -> bool + 'static,
263{
264 fn build_mapping_vec(&self) {
265 let mut mapping = self.mapping.borrow_mut();
266 *mapping = self
267 .wrapped_model
268 .iter()
269 .enumerate()
270 .filter_map(|(i, e)| (self.filter_function)(&e).then_some(i))
271 .collect();
272 }
273}
274
275impl<M, F> ModelChangeListener for FilterModelInner<M, F>
276where
277 M: Model + 'static,
278 F: Fn(&M::Data) -> bool + 'static,
279{
280 fn row_changed(self: Pin<&Self>, row: usize) {
281 let mut mapping = self.mapping.borrow_mut();
282
283 let (index, is_contained) = match mapping.binary_search(&row) {
284 Ok(index) => (index, true),
285 Err(index) => (index, false),
286 };
287
288 let should_be_contained =
289 (self.filter_function)(&self.wrapped_model.row_data(row).unwrap());
290
291 if is_contained && should_be_contained {
292 drop(mapping);
293 self.notify.row_changed(index);
294 } else if !is_contained && should_be_contained {
295 mapping.insert(index, row);
296 drop(mapping);
297 self.notify.row_added(index, 1);
298 } else if is_contained && !should_be_contained {
299 mapping.remove(index);
300 drop(mapping);
301 self.notify.row_removed(index, 1);
302 }
303 }
304
305 fn row_added(self: Pin<&Self>, index: usize, count: usize) {
306 if count == 0 {
307 return;
308 }
309
310 let insertion: Vec<usize> = self
311 .wrapped_model
312 .iter()
313 .enumerate()
314 .skip(index)
315 .take(count)
316 .filter_map(|(i, e)| (self.filter_function)(&e).then_some(i))
317 .collect();
318
319 let mut mapping = self.mapping.borrow_mut();
320 let insertion_point = mapping.binary_search(&index).unwrap_or_else(|ip| ip);
321 mapping[insertion_point..].iter_mut().for_each(|i| *i += count);
322
323 if !insertion.is_empty() {
324 let insertion_len = insertion.len();
325 mapping.splice(insertion_point..insertion_point, insertion);
326
327 drop(mapping);
328 self.notify.row_added(insertion_point, insertion_len);
329 }
330 }
331
332 fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
333 if count == 0 {
334 return;
335 }
336 let mut mapping = self.mapping.borrow_mut();
337
338 let start = mapping.binary_search(&index).unwrap_or_else(|s| s);
339 let end = mapping.binary_search(&(index + count)).unwrap_or_else(|e| e);
340 let range = start..end;
341
342 mapping[end..].iter_mut().for_each(|i| *i -= count);
343
344 if !range.is_empty() {
345 mapping.drain(range.clone());
346 drop(mapping);
347 self.notify.row_removed(start, range.len());
348 }
349 }
350
351 fn reset(self: Pin<&Self>) {
352 self.build_mapping_vec();
353 self.notify.reset();
354 }
355}
356
357pub struct FilterModel<M, F>(Pin<Box<ModelChangeListenerContainer<FilterModelInner<M, F>>>>)
418where
419 M: Model + 'static,
420 F: Fn(&M::Data) -> bool + 'static;
421
422impl<M, F> FilterModel<M, F>
423where
424 M: Model + 'static,
425 F: Fn(&M::Data) -> bool + 'static,
426{
427 pub fn new(wrapped_model: M, filter_function: F) -> Self {
430 let filter_model_inner = FilterModelInner {
431 wrapped_model,
432 filter_function,
433 mapping: RefCell::new(Vec::new()),
434 notify: Default::default(),
435 };
436
437 filter_model_inner.build_mapping_vec();
438
439 let container = Box::pin(ModelChangeListenerContainer::new(filter_model_inner));
440
441 container.wrapped_model.model_tracker().attach_peer(container.as_ref().model_peer());
442
443 Self(container)
444 }
445
446 pub fn reset(&self) {
449 self.0.as_ref().get().reset();
450 }
451
452 pub fn unfiltered_row(&self, filtered_row: usize) -> usize {
454 self.0.mapping.borrow()[filtered_row]
455 }
456
457 pub fn source_model(&self) -> &M {
459 &self.0.as_ref().get().get_ref().wrapped_model
460 }
461}
462
463impl<M, F> Model for FilterModel<M, F>
464where
465 M: Model + 'static,
466 F: Fn(&M::Data) -> bool + 'static,
467{
468 type Data = M::Data;
469
470 fn row_count(&self) -> usize {
471 self.0.mapping.borrow().len()
472 }
473
474 fn row_data(&self, row: usize) -> Option<Self::Data> {
475 self.0
476 .mapping
477 .borrow()
478 .get(row)
479 .and_then(|&wrapped_row| self.0.wrapped_model.row_data(wrapped_row))
480 }
481
482 fn set_row_data(&self, row: usize, data: Self::Data) {
483 let wrapped_row = self.0.mapping.borrow()[row];
484 self.0.wrapped_model.set_row_data(wrapped_row, data);
485 }
486
487 fn model_tracker(&self) -> &dyn ModelTracker {
488 &self.0.notify
489 }
490
491 fn as_any(&self) -> &dyn core::any::Any {
492 self
493 }
494}
495
496#[test]
497fn test_filter_model() {
498 let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3, 4, 5, 6]));
499 let filter = Rc::new(FilterModel::new(wrapped_rc.clone(), |x| x % 2 == 0));
500
501 let _checker = ModelChecker::new(filter.clone());
502
503 assert_eq!(filter.row_data(0).unwrap(), 2);
504 assert_eq!(filter.row_data(1).unwrap(), 4);
505 assert_eq!(filter.row_data(2).unwrap(), 6);
506 assert_eq!(filter.row_count(), 3);
507
508 wrapped_rc.remove(1);
509 assert_eq!(filter.row_data(0).unwrap(), 4);
510 assert_eq!(filter.row_data(1).unwrap(), 6);
511 assert_eq!(filter.row_count(), 2);
512
513 wrapped_rc.push(8);
514 wrapped_rc.push(7);
515 assert_eq!(filter.row_data(0).unwrap(), 4);
516 assert_eq!(filter.row_data(1).unwrap(), 6);
517 assert_eq!(filter.row_data(2).unwrap(), 8);
518 assert_eq!(filter.row_count(), 3);
519
520 wrapped_rc.set_row_data(1, 2);
521 assert_eq!(filter.row_data(0).unwrap(), 2);
522 assert_eq!(filter.row_data(1).unwrap(), 4);
523 assert_eq!(filter.row_data(2).unwrap(), 6);
524 assert_eq!(filter.row_data(3).unwrap(), 8);
525 assert_eq!(filter.row_count(), 4);
526
527 wrapped_rc.insert(2, 12);
528 assert_eq!(filter.row_data(0).unwrap(), 2);
529 assert_eq!(filter.row_data(1).unwrap(), 12);
530 assert_eq!(filter.row_data(2).unwrap(), 4);
531 assert_eq!(filter.row_data(3).unwrap(), 6);
532 assert_eq!(filter.row_data(4).unwrap(), 8);
533 assert_eq!(filter.row_count(), 5);
534}
535
536#[test]
537fn test_filter_model_source_model() {
538 let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3, 4]));
539 let model = Rc::new(FilterModel::new(wrapped_rc.clone(), |x| x % 2 == 0));
540
541 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
542 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
543
544 let _checker = ModelChecker::new(model.clone());
545
546 model.source_model().push(5);
547 model.source_model().push(6);
548
549 let expected = &[2, 4, 6];
550 assert_eq!(model.row_count(), expected.len());
551 for (i, v) in expected.iter().enumerate() {
552 assert_eq!(model.row_data(i), Some(*v), "Expected {v} at index {i}");
553 }
554}
555
556pub trait SortHelper<D> {
557 fn cmp(&mut self, lhs: &D, rhs: &D) -> core::cmp::Ordering;
558}
559
560pub struct AscendingSortHelper;
561
562impl<D> SortHelper<D> for AscendingSortHelper
563where
564 D: core::cmp::Ord,
565{
566 fn cmp(&mut self, lhs: &D, rhs: &D) -> core::cmp::Ordering {
567 lhs.cmp(rhs)
568 }
569}
570
571impl<F, D> SortHelper<D> for F
572where
573 F: FnMut(&D, &D) -> core::cmp::Ordering + 'static,
574{
575 fn cmp(&mut self, lhs: &D, rhs: &D) -> core::cmp::Ordering {
576 (self)(lhs, rhs)
577 }
578}
579
580struct SortModelInner<M, S>
581where
582 M: Model + 'static,
583 S: SortHelper<M::Data> + 'static,
584{
585 wrapped_model: M,
586 sort_helper: RefCell<S>,
587 mapping: RefCell<Vec<usize>>,
589 notify: ModelNotify,
590 sorted_rows_dirty: Cell<bool>,
591}
592
593impl<M, S> SortModelInner<M, S>
594where
595 M: Model + 'static,
596 S: SortHelper<M::Data>,
597{
598 fn build_mapping_vec(&self) {
599 if !self.sorted_rows_dirty.get() {
600 return;
601 }
602
603 let mut mapping = self.mapping.borrow_mut();
604
605 mapping.clear();
606 mapping.extend(0..self.wrapped_model.row_count());
607 mapping.sort_by(|lhs, rhs| {
608 self.sort_helper.borrow_mut().cmp(
609 &self.wrapped_model.row_data(*lhs).unwrap(),
610 &self.wrapped_model.row_data(*rhs).unwrap(),
611 )
612 });
613
614 self.sorted_rows_dirty.set(false);
615 }
616}
617
618impl<M, S> ModelChangeListener for SortModelInner<M, S>
619where
620 M: Model + 'static,
621 S: SortHelper<M::Data> + 'static,
622{
623 fn row_changed(self: Pin<&Self>, row: usize) {
624 if self.sorted_rows_dirty.get() {
625 self.reset();
626 return;
627 }
628
629 let mut mapping = self.mapping.borrow_mut();
630 let removed_index = mapping.iter().position(|r| *r == row).unwrap();
631 mapping.remove(removed_index);
632
633 let changed_data = self.wrapped_model.row_data(row).unwrap();
634 let insertion_index = mapping.partition_point(|existing_row| {
635 self.sort_helper
636 .borrow_mut()
637 .cmp(&self.wrapped_model.row_data(*existing_row).unwrap(), &changed_data)
638 == core::cmp::Ordering::Less
639 });
640
641 mapping.insert(insertion_index, row);
642
643 drop(mapping);
644
645 if insertion_index == removed_index {
646 self.notify.row_changed(removed_index);
647 } else {
648 self.notify.row_removed(removed_index, 1);
649 self.notify.row_added(insertion_index, 1);
650 }
651 }
652
653 fn row_added(self: Pin<&Self>, index: usize, count: usize) {
654 if count == 0 {
655 return;
656 }
657
658 if self.sorted_rows_dirty.get() {
659 self.reset();
660 return;
661 }
662
663 for row in self.mapping.borrow_mut().iter_mut() {
665 if *row >= index {
666 *row += count;
667 }
668 }
669
670 for row in index..(index + count) {
671 let added_data = self.wrapped_model.row_data(row).unwrap();
672 let insertion_index = self.mapping.borrow().partition_point(|existing_row| {
673 self.sort_helper
674 .borrow_mut()
675 .cmp(&self.wrapped_model.row_data(*existing_row).unwrap(), &added_data)
676 == core::cmp::Ordering::Less
677 });
678
679 self.mapping.borrow_mut().insert(insertion_index, row);
680 self.notify.row_added(insertion_index, 1)
681 }
682 }
683
684 fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
685 if count == 0 {
686 return;
687 }
688
689 if self.sorted_rows_dirty.get() {
690 self.reset();
691 return;
692 }
693
694 let mut removed_rows = Vec::new();
695
696 let mut i = 0;
697
698 loop {
699 if i >= self.mapping.borrow().len() {
700 break;
701 }
702
703 let sort_index = self.mapping.borrow()[i];
704
705 if sort_index >= index {
706 if sort_index < index + count {
707 removed_rows.push(i);
708 self.mapping.borrow_mut().remove(i);
709 continue;
710 } else {
711 self.mapping.borrow_mut()[i] -= count;
712 }
713 }
714
715 i += 1;
716 }
717
718 for removed_row in removed_rows {
719 self.notify.row_removed(removed_row, 1);
720 }
721 }
722
723 fn reset(self: Pin<&Self>) {
724 self.sorted_rows_dirty.set(true);
725 self.notify.reset();
726 }
727}
728
729pub struct SortModel<M, F>(Pin<Box<ModelChangeListenerContainer<SortModelInner<M, F>>>>)
823where
824 M: Model + 'static,
825 F: SortHelper<M::Data> + 'static;
826
827impl<M, F> SortModel<M, F>
828where
829 M: Model + 'static,
830 F: FnMut(&M::Data, &M::Data) -> core::cmp::Ordering + 'static,
831{
832 pub fn new(wrapped_model: M, sort_function: F) -> Self
835 where
836 F: FnMut(&M::Data, &M::Data) -> core::cmp::Ordering + 'static,
837 {
838 let sorted_model_inner = SortModelInner {
839 wrapped_model,
840 sort_helper: RefCell::new(sort_function),
841 mapping: RefCell::new(Vec::new()),
842 notify: Default::default(),
843 sorted_rows_dirty: Cell::new(true),
844 };
845
846 let container = Box::pin(ModelChangeListenerContainer::new(sorted_model_inner));
847
848 container.wrapped_model.model_tracker().attach_peer(container.as_ref().model_peer());
849
850 Self(container)
851 }
852
853 pub fn source_model(&self) -> &M {
855 &self.0.as_ref().get().get_ref().wrapped_model
856 }
857}
858
859impl<M> SortModel<M, AscendingSortHelper>
860where
861 M: Model + 'static,
862 M::Data: core::cmp::Ord,
863{
864 pub fn new_ascending(wrapped_model: M) -> Self
867 where
868 M::Data: core::cmp::Ord,
869 {
870 let sorted_model_inner = SortModelInner {
871 wrapped_model,
872 sort_helper: RefCell::new(AscendingSortHelper),
873 mapping: RefCell::new(Vec::new()),
874 notify: Default::default(),
875 sorted_rows_dirty: Cell::new(true),
876 };
877
878 let container = Box::pin(ModelChangeListenerContainer::new(sorted_model_inner));
879
880 container.wrapped_model.model_tracker().attach_peer(container.as_ref().model_peer());
881
882 Self(container)
883 }
884
885 pub fn reset(&self) {
888 self.0.as_ref().get().reset();
889 }
890
891 pub fn unsorted_row(&self, sorted_row: usize) -> usize {
893 self.0.build_mapping_vec();
894 self.0.mapping.borrow()[sorted_row]
895 }
896}
897
898impl<M, S> Model for SortModel<M, S>
899where
900 M: Model + 'static,
901 S: SortHelper<M::Data>,
902{
903 type Data = M::Data;
904
905 fn row_count(&self) -> usize {
906 self.0.wrapped_model.row_count()
907 }
908
909 fn row_data(&self, row: usize) -> Option<Self::Data> {
910 self.0.build_mapping_vec();
911
912 self.0
913 .mapping
914 .borrow()
915 .get(row)
916 .and_then(|&wrapped_row| self.0.wrapped_model.row_data(wrapped_row))
917 }
918
919 fn set_row_data(&self, row: usize, data: Self::Data) {
920 let wrapped_row = self.0.mapping.borrow()[row];
921 self.0.wrapped_model.set_row_data(wrapped_row, data);
922 }
923
924 fn model_tracker(&self) -> &dyn ModelTracker {
925 &self.0.notify
926 }
927
928 fn as_any(&self) -> &dyn core::any::Any {
929 self
930 }
931}
932
933#[cfg(test)]
934mod sort_tests {
935 use super::*;
936 use std::vec;
937
938 #[test]
939 fn test_sorted_model_insert() {
940 let wrapped_rc = Rc::new(VecModel::from(std::vec![3, 4, 1, 2]));
941 let sorted_model = Rc::new(SortModel::new(wrapped_rc.clone(), |lhs, rhs| lhs.cmp(rhs)));
942
943 let _checker = ModelChecker::new(sorted_model.clone());
944
945 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
946 sorted_model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
947
948 assert_eq!(sorted_model.row_count(), 4);
949 assert_eq!(sorted_model.row_data(0).unwrap(), 1);
950 assert_eq!(sorted_model.row_data(1).unwrap(), 2);
951 assert_eq!(sorted_model.row_data(2).unwrap(), 3);
952 assert_eq!(sorted_model.row_data(3).unwrap(), 4);
953
954 wrapped_rc.insert(0, 10);
955
956 assert_eq!(observer.added_rows.borrow().len(), 1);
957 assert!(observer.added_rows.borrow().eq(&[(4, 1)]));
958 assert!(observer.changed_rows.borrow().is_empty());
959 assert!(observer.removed_rows.borrow().is_empty());
960 assert_eq!(*observer.reset.borrow(), 0);
961 observer.clear();
962
963 assert_eq!(sorted_model.row_count(), 5);
964 assert_eq!(sorted_model.row_data(0).unwrap(), 1);
965 assert_eq!(sorted_model.row_data(1).unwrap(), 2);
966 assert_eq!(sorted_model.row_data(2).unwrap(), 3);
967 assert_eq!(sorted_model.row_data(3).unwrap(), 4);
968 assert_eq!(sorted_model.row_data(4).unwrap(), 10);
969 }
970
971 #[test]
972 fn test_sorted_model_remove() {
973 let wrapped_rc = Rc::new(VecModel::from(vec![3, 4, 1, 2]));
974 let sorted_model = Rc::new(SortModel::new(wrapped_rc.clone(), |lhs, rhs| lhs.cmp(rhs)));
975
976 let _checker = ModelChecker::new(sorted_model.clone());
977
978 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
979 sorted_model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
980
981 assert_eq!(sorted_model.row_count(), 4);
982 assert_eq!(sorted_model.row_data(0).unwrap(), 1);
983 assert_eq!(sorted_model.row_data(1).unwrap(), 2);
984 assert_eq!(sorted_model.row_data(2).unwrap(), 3);
985 assert_eq!(sorted_model.row_data(3).unwrap(), 4);
986
987 wrapped_rc.remove(1);
989
990 assert!(observer.added_rows.borrow().is_empty());
991 assert!(observer.changed_rows.borrow().is_empty());
992 assert_eq!(observer.removed_rows.borrow().len(), 1);
993 assert!(observer.removed_rows.borrow().eq(&[(3, 1)]));
994 assert_eq!(*observer.reset.borrow(), 0);
995 observer.clear();
996
997 assert_eq!(sorted_model.row_count(), 3);
998 assert_eq!(sorted_model.row_data(0).unwrap(), 1);
999 assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1000 assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1001 }
1002
1003 #[test]
1004 fn test_sorted_model_changed() {
1005 let wrapped_rc = Rc::new(VecModel::from(vec![3, 4, 1, 2]));
1006 let sorted_model = Rc::new(SortModel::new(wrapped_rc.clone(), |lhs, rhs| lhs.cmp(rhs)));
1007
1008 let _checker = ModelChecker::new(sorted_model.clone());
1009
1010 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1011 sorted_model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1012
1013 assert_eq!(sorted_model.row_count(), 4);
1014 assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1015 assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1016 assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1017 assert_eq!(sorted_model.row_data(3).unwrap(), 4);
1018
1019 wrapped_rc.set_row_data(1, 10);
1021
1022 assert!(observer.added_rows.borrow().is_empty());
1023 assert_eq!(observer.changed_rows.borrow().len(), 1);
1024 assert_eq!(*observer.changed_rows.borrow().first().unwrap(), 3);
1025 assert!(observer.removed_rows.borrow().is_empty());
1026 assert_eq!(*observer.reset.borrow(), 0);
1027 observer.clear();
1028
1029 assert_eq!(sorted_model.row_count(), 4);
1030 assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1031 assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1032 assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1033 assert_eq!(sorted_model.row_data(3).unwrap(), 10);
1034
1035 wrapped_rc.set_row_data(1, 0);
1037
1038 assert_eq!(observer.added_rows.borrow().len(), 1);
1039 assert!(observer.added_rows.borrow().first().unwrap().eq(&(0, 1)));
1040 assert!(observer.changed_rows.borrow().is_empty());
1041 assert_eq!(observer.removed_rows.borrow().len(), 1);
1042 assert!(observer.removed_rows.borrow().first().unwrap().eq(&(3, 1)));
1043 assert_eq!(*observer.reset.borrow(), 0);
1044 observer.clear();
1045
1046 assert_eq!(sorted_model.row_count(), 4);
1047 assert_eq!(sorted_model.row_data(0).unwrap(), 0);
1048 assert_eq!(sorted_model.row_data(1).unwrap(), 1);
1049 assert_eq!(sorted_model.row_data(2).unwrap(), 2);
1050 assert_eq!(sorted_model.row_data(3).unwrap(), 3);
1051 }
1052
1053 #[test]
1054 fn test_sorted_model_source_model() {
1055 let wrapped_rc = Rc::new(VecModel::from(vec![3, 4, 1, 2]));
1056 let model = Rc::new(SortModel::new(wrapped_rc.clone(), |lhs, rhs| lhs.cmp(rhs)));
1057 let _checker = ModelChecker::new(model.clone());
1058
1059 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1060 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1061
1062 model.source_model().push(6);
1063 model.source_model().push(5);
1064
1065 let expected = &[1, 2, 3, 4, 5, 6];
1066 assert_eq!(model.row_count(), expected.len());
1067 for (i, v) in expected.iter().enumerate() {
1068 assert_eq!(model.row_data(i), Some(*v), "Expected {v} at index {i}");
1069 }
1070 }
1071}
1072
1073pub struct ReverseModel<M>(Pin<Box<ModelChangeListenerContainer<ReverseModelInner<M>>>>)
1137where
1138 M: Model + 'static;
1139
1140struct ReverseModelInner<M>
1141where
1142 M: Model + 'static,
1143{
1144 wrapped_model: M,
1145 notify: ModelNotify,
1146}
1147
1148impl<M> ModelChangeListener for ReverseModelInner<M>
1149where
1150 M: Model + 'static,
1151{
1152 fn row_changed(self: Pin<&Self>, row: usize) {
1153 self.notify.row_changed(self.wrapped_model.row_count() - 1 - row);
1154 }
1155
1156 fn row_added(self: Pin<&Self>, index: usize, count: usize) {
1157 let row_count = self.wrapped_model.row_count();
1158 let old_row_count = row_count - count;
1159 let index = old_row_count - index;
1160 self.notify.row_added(index, count);
1161 }
1162
1163 fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
1164 let row_count = self.wrapped_model.row_count();
1165 self.notify.row_removed(row_count - index, count);
1166 }
1167
1168 fn reset(self: Pin<&Self>) {
1169 self.notify.reset()
1170 }
1171}
1172
1173impl<M> ReverseModel<M>
1174where
1175 M: Model + 'static,
1176{
1177 pub fn new(wrapped_model: M) -> Self {
1180 let inner = ReverseModelInner { wrapped_model, notify: Default::default() };
1181 let container = Box::pin(ModelChangeListenerContainer::new(inner));
1182 container.wrapped_model.model_tracker().attach_peer(container.as_ref().model_peer());
1183 Self(container)
1184 }
1185
1186 pub fn source_model(&self) -> &M {
1188 &self.0.as_ref().get().get_ref().wrapped_model
1189 }
1190}
1191
1192impl<M> Model for ReverseModel<M>
1193where
1194 M: Model + 'static,
1195{
1196 type Data = M::Data;
1197
1198 fn row_count(&self) -> usize {
1199 self.0.wrapped_model.row_count()
1200 }
1201
1202 fn row_data(&self, row: usize) -> Option<Self::Data> {
1203 let count = self.0.wrapped_model.row_count();
1204 self.0.wrapped_model.row_data(count.checked_sub(row + 1)?)
1205 }
1206 fn set_row_data(&self, row: usize, data: Self::Data) {
1207 let count = self.0.as_ref().wrapped_model.row_count();
1208 self.0.wrapped_model.set_row_data(count - row - 1, data);
1209 }
1210
1211 fn model_tracker(&self) -> &dyn ModelTracker {
1212 &self.0.notify
1213 }
1214
1215 fn as_any(&self) -> &dyn core::any::Any {
1216 self
1217 }
1218}
1219
1220#[cfg(test)]
1221mod reversed_tests {
1222 use super::*;
1223 use std::vec;
1224
1225 #[track_caller]
1226 fn check_content(model: &ReverseModel<Rc<VecModel<i32>>>, expected: &[i32]) {
1227 assert_eq!(model.row_count(), expected.len());
1228 for (i, v) in expected.iter().enumerate() {
1229 assert_eq!(model.row_data(i), Some(*v), "Expected {v} at index {i}");
1230 }
1231 }
1232
1233 #[test]
1234 fn test_reversed_model() {
1235 let wrapped_rc = Rc::new(VecModel::from(vec![1, 2, 3, 4]));
1236 let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1237 let _checker = ModelChecker::new(model.clone());
1238
1239 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1240 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1241
1242 check_content(&model, &[4, 3, 2, 1]);
1243 }
1244
1245 #[test]
1246 fn test_reversed_model_insert() {
1247 for (idx, mapped_idx) in [(0, 4), (1, 3), (2, 2), (3, 1), (4, 0)] {
1248 std::println!("Inserting at {idx} expecting mapped to {mapped_idx}");
1249 let wrapped_rc = Rc::new(VecModel::from(vec![1, 2, 3, 4]));
1250 let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1251 let _checker = ModelChecker::new(model.clone());
1252
1253 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1254 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1255
1256 wrapped_rc.insert(idx, 10);
1257
1258 assert_eq!(observer.added_rows.borrow().len(), 1);
1259 assert!(
1260 observer.added_rows.borrow().eq(&[(mapped_idx, 1)]),
1261 "Added rows: {:?}",
1262 observer.added_rows.borrow()
1263 );
1264 assert!(observer.changed_rows.borrow().is_empty());
1265 assert!(observer.removed_rows.borrow().is_empty());
1266 assert_eq!(*observer.reset.borrow(), 0);
1267 assert_eq!(model.row_data(mapped_idx), Some(10));
1268 }
1269 }
1270
1271 #[test]
1272 fn test_reversed_model_remove() {
1273 for (idx, mapped_idx) in [(0, 3), (1, 2), (2, 1), (3, 0)] {
1274 std::println!("Removing at {idx} expecting mapped to {mapped_idx}");
1275 let wrapped_rc = Rc::new(VecModel::from(vec![1, 2, 3, 4]));
1276 let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1277 let _checker = ModelChecker::new(model.clone());
1278
1279 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1280 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1281
1282 wrapped_rc.remove(idx);
1283
1284 assert_eq!(observer.removed_rows.borrow().len(), 1);
1285 assert!(
1286 observer.removed_rows.borrow().eq(&[(mapped_idx, 1)]),
1287 "Remove rows: {:?}",
1288 observer.removed_rows.borrow()
1289 );
1290 assert!(observer.added_rows.borrow().is_empty());
1291 assert!(observer.changed_rows.borrow().is_empty());
1292 assert_eq!(*observer.reset.borrow(), 0);
1293 }
1294 }
1295
1296 #[test]
1297 fn test_reversed_model_changed() {
1298 for (idx, mapped_idx) in [(0, 3), (1, 2), (2, 1), (3, 0)] {
1299 std::println!("Changing at {idx} expecting mapped to {mapped_idx}");
1300 let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3, 4]));
1301 let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1302 let _checker = ModelChecker::new(model.clone());
1303
1304 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1305 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1306
1307 wrapped_rc.set_row_data(idx, 10);
1308
1309 assert_eq!(observer.changed_rows.borrow().len(), 1);
1310 assert!(
1311 observer.changed_rows.borrow().eq(&[mapped_idx]),
1312 "Changed rows: {:?}",
1313 observer.changed_rows.borrow()
1314 );
1315 assert!(observer.added_rows.borrow().is_empty());
1316 assert!(observer.removed_rows.borrow().is_empty());
1317 assert_eq!(*observer.reset.borrow(), 0);
1318 assert_eq!(model.row_data(mapped_idx), Some(10));
1319 }
1320 }
1321
1322 #[test]
1323 fn test_reversed_model_source_model() {
1324 let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3, 4]));
1325 let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1326 let _checker = ModelChecker::new(model.clone());
1327
1328 let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1329 model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1330
1331 model.source_model().push(5);
1332
1333 check_content(&model, &[5, 4, 3, 2, 1]);
1334 }
1335}
1336
1337#[test]
1338fn test_long_chain_integrity() {
1339 use alloc::string::ToString;
1340 let origin_model = Rc::new(VecModel::from((0..100).collect::<Vec<_>>()));
1341 let checker1 = ModelChecker::new(origin_model.clone());
1342 let fizzbuzz = Rc::new(MapModel::new(origin_model.clone(), |number| {
1343 if (number % 3) == 0 && (number % 5) == 0 {
1344 "FizzBuzz".to_string()
1345 } else if (number % 3) == 0 {
1346 "Fizz".to_string()
1347 } else if (number % 5) == 0 {
1348 "Buzz".to_string()
1349 } else {
1350 number.to_string()
1351 }
1352 }));
1353 let checker2 = ModelChecker::new(fizzbuzz.clone());
1354 let filter = Rc::new(FilterModel::new(fizzbuzz, |s| s != "FizzBuzz"));
1355 let checker3 = ModelChecker::new(filter.clone());
1356 let reverse = Rc::new(ReverseModel::new(filter));
1357 let checker4 = ModelChecker::new(reverse.clone());
1358 let sorted = Rc::new(SortModel::new_ascending(reverse));
1359 let checker5 = ModelChecker::new(sorted.clone());
1360 let filter2 = Rc::new(FilterModel::new(sorted, |s| s != "Fizz"));
1361 let checker6 = ModelChecker::new(filter2.clone());
1362
1363 let check_all = || {
1364 checker1.check();
1365 checker2.check();
1366 checker3.check();
1367 checker4.check();
1368 checker5.check();
1369 checker6.check();
1370 };
1371
1372 origin_model.extend(50..150);
1373 check_all();
1374 origin_model.insert(8, 1000);
1375 check_all();
1376 origin_model.remove(9);
1377 check_all();
1378 origin_model.remove(10);
1379 origin_model.remove(11);
1380 origin_model.set_row_data(55, 10001);
1381 check_all();
1382 origin_model.set_row_data(58, 10002);
1383 origin_model.set_row_data(59, 10003);
1384 origin_model.remove(28);
1385 origin_model.remove(29);
1386 origin_model.insert(100, 8888);
1387 origin_model.remove(30);
1388 origin_model.set_row_data(60, 10004);
1389 origin_model.remove(130);
1390 origin_model.set_row_data(61, 10005);
1391 origin_model.remove(131);
1392 check_all();
1393 origin_model.remove(12);
1394 origin_model.remove(13);
1395 origin_model.remove(14);
1396 origin_model.set_row_data(62, 10006);
1397 origin_model.set_row_data(63, 10007);
1398 origin_model.set_row_data(64, 10008);
1399 origin_model.set_row_data(65, 10009);
1400 check_all();
1401
1402 trait RemoveRange {
1404 fn remove_range(&self, range: core::ops::Range<usize>);
1405 }
1406 impl<T> RemoveRange for VecModel<T> {
1407 fn remove_range(&self, range: core::ops::Range<usize>) {
1408 self.array.borrow_mut().drain(range.clone());
1409 self.notify.row_removed(range.start, range.len())
1410 }
1411 }
1412
1413 origin_model.remove_range(25..110);
1414 check_all();
1415
1416 origin_model.extend(900..910);
1417 origin_model.set_row_data(45, 44444);
1418 origin_model.remove_range(10..30);
1419 origin_model.insert(45, 3000);
1420 origin_model.insert(45, 3001);
1421 origin_model.insert(45, 3002);
1422 origin_model.insert(45, 3003);
1423 origin_model.insert(45, 3004);
1424 origin_model.insert(45, 3006);
1425 origin_model.insert(45, 3007);
1426 check_all();
1427}