summary refs log tree commit diff
path: root/src/util/option_tracker.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/option_tracker.rs')
-rw-r--r--src/util/option_tracker.rs43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/util/option_tracker.rs b/src/util/option_tracker.rs
new file mode 100644
index 0000000..3c19ee5
--- /dev/null
+++ b/src/util/option_tracker.rs
@@ -0,0 +1,43 @@
+pub struct OptionTracker<T> {
+    inner: Option<T>,
+    dirty: bool,
+}
+
+/// Tracks changes to an inner Option<T>. Any change using `set` will cause the
+/// tracker to be marked as dirty, unless both the current and new value are
+/// `None`. This should be used when changes from `Some(something)` to
+/// `Some(something_different)` are rare, or when comparing inner values is more
+/// expensive than performing an update which will mark the tracker as clean.
+impl<T> OptionTracker<T> {
+    pub fn new(inner: Option<T>) -> Self {
+        Self { inner, dirty: true }
+    }
+
+    pub fn get(&self) -> &Option<T> {
+        &self.inner
+    }
+
+    pub fn set(&mut self, value: Option<T>) {
+        match (&self.inner, &value) {
+            (None, None) => {}
+            _ => self.dirty = true,
+        }
+
+        self.inner = value;
+    }
+
+    pub fn is_dirty(&self) -> bool {
+        self.dirty
+    }
+
+    /// Marks the tracker as clean.
+    pub fn reset(&mut self) {
+        self.dirty = false;
+    }
+}
+
+impl<T> Default for OptionTracker<T> {
+    fn default() -> Self {
+        Self::new(Option::default())
+    }
+}