stratus/eth/primitives/
execution_value_change.rs

1// -----------------------------------------------------------------------------
2// Value Change
3// -----------------------------------------------------------------------------
4
5use std::fmt::Debug;
6
7use display_json::DebugAsJson;
8
9use crate::ext::to_json_string;
10
11/// Changes that happened to an account value during a transaction.
12#[derive(Clone, PartialEq, Eq, fake::Dummy, serde::Serialize, serde::Deserialize, Default)]
13pub struct ExecutionValueChange<T>
14where
15    T: PartialEq + serde::Serialize,
16{
17    original: ValueState<T>,
18    modified: ValueState<T>,
19}
20
21impl<T> Copy for ExecutionValueChange<T> where T: Copy + PartialEq + serde::Serialize {}
22
23impl<T> From<T> for ExecutionValueChange<T>
24where
25    T: PartialEq + serde::Serialize,
26{
27    fn from(value: T) -> Self {
28        Self::from_modified(value)
29    }
30}
31
32impl<T> Debug for ExecutionValueChange<T>
33where
34    T: PartialEq + serde::Serialize,
35{
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        f.write_str(&to_json_string(self))
38    }
39}
40
41impl<T> ExecutionValueChange<T>
42where
43    T: PartialEq + serde::Serialize,
44{
45    /// Creates a new [`ExecutionValueChange`] only with original value.
46    pub fn from_original(value: T) -> Self {
47        Self {
48            original: ValueState::Set(value),
49            modified: ValueState::NotSet,
50        }
51    }
52
53    /// Creates a new [`ExecutionValueChange`] only with modified value.
54    pub fn from_modified(value: T) -> Self {
55        Self {
56            original: ValueState::NotSet,
57            modified: ValueState::Set(value),
58        }
59    }
60
61    /// Sets the modified value of an original value.
62    pub fn set_modified(&mut self, value: T) {
63        self.modified = ValueState::Set(value);
64    }
65
66    pub fn set_original(&mut self, value: T) {
67        self.original = ValueState::Set(value);
68    }
69
70    /// Takes the original value as reference if it is set.
71    pub fn take_original_ref(&self) -> Option<&T> {
72        self.original.take_ref()
73    }
74
75    /// Takes the modified value if it is set.
76    pub fn take_modified(self) -> Option<T> {
77        self.modified.take()
78    }
79
80    /// Takes the modified value as reference if it is set.
81    pub fn take_modified_ref(&self) -> Option<&T> {
82        self.modified.take_ref()
83    }
84
85    /// Takes any value that is set, giving preference to the modified value, but using the original value as fallback.
86    pub fn take(self) -> Option<T> {
87        self.modified.take().or_else(|| self.original.take())
88    }
89
90    /// Takes any value that is set as reference, giving preference to the modified value, but using the original value as fallback.
91    pub fn take_ref(&self) -> Option<&T> {
92        self.modified.take_ref().or_else(|| self.original.take_ref())
93    }
94
95    /// Check if the value was modified.
96    pub fn is_modified(&self) -> bool {
97        self.modified.is_set() && (self.original != self.modified)
98    }
99
100    pub fn is_empty(&self) -> bool {
101        !self.modified.is_set() && !self.original.is_set()
102    }
103}
104
105impl<T> From<Option<T>> for ExecutionValueChange<T>
106where
107    T: PartialEq + serde::Serialize,
108{
109    fn from(value: Option<T>) -> Self {
110        let modified = match value {
111            None => ValueState::NotSet,
112            Some(value) => ValueState::Set(value),
113        };
114        ExecutionValueChange {
115            original: ValueState::NotSet,
116            modified,
117        }
118    }
119}
120
121// -----------------------------------------------------------------------------
122// Value State
123// -----------------------------------------------------------------------------
124
125#[derive(DebugAsJson, Clone, PartialEq, Eq, fake::Dummy, serde::Serialize, serde::Deserialize, Default)]
126#[serde(rename_all = "snake_case")]
127pub enum ValueState<T> {
128    Set(T),
129    #[default]
130    NotSet,
131}
132
133impl<T> Copy for ValueState<T> where T: Copy {}
134
135impl<T> ValueState<T> {
136    pub fn is_set(&self) -> bool {
137        matches!(self, Self::Set(_))
138    }
139
140    pub fn take(self) -> Option<T> {
141        if let Self::Set(value) = self { Some(value) } else { None }
142    }
143
144    pub fn take_ref(&self) -> Option<&T> {
145        if let Self::Set(value) = self { Some(value) } else { None }
146    }
147}