Skip to main content

ferroui_dynamic_data/cache/
change.rs

1//! `Change<TObject, TKey>` (`Cache/Change.cs`).
2
3use super::ChangeReason;
4use std::fmt;
5
6/// A change of one item of a cache (`Change<TObject, TKey>`): its reason, its key, the item and,
7/// for an update, the item it replaced; the indexes for a sorted collection.
8///
9/// Deviation (DEVIATIONS.md, DynamicData): the indexes are `Option<usize>`, where upstream writes
10/// `-1` for no index.
11#[derive(Clone, PartialEq, Eq, Hash)]
12pub struct Change<T, K> {
13    reason: ChangeReason,
14    key: K,
15    current: T,
16    previous: Option<T>,
17    current_index: Option<usize>,
18    previous_index: Option<usize>,
19}
20
21impl<T, K> Change<T, K> {
22    /// A change without a previous item (`Change(ChangeReason, TKey, TObject, int index = -1)`).
23    ///
24    /// # Panics
25    /// For `ChangeReason::Update`, which needs the previous item (`ArgumentException`).
26    pub fn new(reason: ChangeReason, key: K, current: T) -> Self {
27        Self::with_previous(reason, key, current, None, None, None)
28    }
29
30    /// A change with the index of the item (`Change(ChangeReason, TKey, TObject, int index)`).
31    pub fn with_index(reason: ChangeReason, key: K, current: T, index: Option<usize>) -> Self {
32        Self::with_previous(reason, key, current, None, index, None)
33    }
34
35    /// A change with every part (`Change(ChangeReason, TKey, TObject, in Optional<TObject>, int,
36    /// int)`).
37    ///
38    /// # Panics
39    /// For `ChangeReason::Add` with a previous item, and for `ChangeReason::Update` without one
40    /// (`ArgumentException`).
41    pub fn with_previous(
42        reason: ChangeReason,
43        key: K,
44        current: T,
45        previous: Option<T>,
46        current_index: Option<usize>,
47        previous_index: Option<usize>,
48    ) -> Self {
49        assert!(!(reason == ChangeReason::Add && previous.is_some()), "For ChangeReason.Add, a previous value cannot be specified");
50        assert!(!(reason == ChangeReason::Update && previous.is_none()), "For ChangeReason.Update, must supply previous value");
51        Self { reason, key, current, previous, current_index, previous_index }
52    }
53
54    /// An update of `key` from `previous` to `current` (`Change(ChangeReason.Update, key, current,
55    /// previous)`).
56    pub fn update(key: K, current: T, previous: T) -> Self {
57        Self::with_previous(ChangeReason::Update, key, current, Some(previous), None, None)
58    }
59
60    /// A move within a sorted collection (`Change(TKey, TObject, int currentIndex, int
61    /// previousIndex)`).
62    pub fn moved(key: K, current: T, current_index: usize, previous_index: usize) -> Self {
63        Self {
64            reason: ChangeReason::Moved,
65            key,
66            current,
67            previous: None,
68            current_index: Some(current_index),
69            previous_index: Some(previous_index),
70        }
71    }
72
73    /// The key of the item (`Key`).
74    pub fn key(&self) -> &K {
75        &self.key
76    }
77
78    /// The reason of the change (`Reason`).
79    pub fn reason(&self) -> ChangeReason {
80        self.reason
81    }
82
83    /// The item (`Current`).
84    pub fn current(&self) -> &T {
85        &self.current
86    }
87
88    /// The item that an update replaced (`Previous`).
89    pub fn previous(&self) -> Option<&T> {
90        self.previous.as_ref()
91    }
92
93    /// The index of the item in a sorted collection (`CurrentIndex`; `-1` upstream when none).
94    pub fn current_index(&self) -> Option<usize> {
95        self.current_index
96    }
97
98    /// The previous index of the item (`PreviousIndex`).
99    pub fn previous_index(&self) -> Option<usize> {
100        self.previous_index
101    }
102
103    /// The parts of the change, taken apart.
104    pub fn into_parts(self) -> (ChangeReason, K, T, Option<T>) {
105        (self.reason, self.key, self.current, self.previous)
106    }
107}
108
109impl<T: fmt::Debug, K: fmt::Debug> fmt::Debug for Change<T, K> {
110    /// `ToString`: the reason, the key, the item and the previous item.
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        write!(f, "{:?}, Key: {:?}, Current: {:?}, Previous: {:?}", self.reason, self.key, self.current, self.previous)
113    }
114}