From 461b41695b106265a40111940f2ae158c216d4ea Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Sat, 16 Sep 2023 11:52:20 -0400 Subject: [PATCH] Add a change tracker type --- src/change_tracker.rs | 103 ++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 104 insertions(+) create mode 100644 src/change_tracker.rs diff --git a/src/change_tracker.rs b/src/change_tracker.rs new file mode 100644 index 0000000..211ad77 --- /dev/null +++ b/src/change_tracker.rs @@ -0,0 +1,103 @@ +use std::ops::{DerefMut, Deref}; + +/// A change tracker. This tracks changes of the data it owns. +/// Tracking changes can cause false positives since it actually tracks calls to `deref_mut()` +/// If you mutably dereference this, make sure its only when you change the data. +pub struct Ct { + data: T, + changed: bool, +} + +impl Ct { + pub fn new(data: T) -> Self { + Self { + data, + changed: false, + } + } + + /// Create a new change tracker with data + pub fn new_true(data: T) -> Self { + Self { + data, + changed: true, + } + } + + /// Returns true if there was a change. Will reset back to false after this is called. + pub fn changed(&mut self) -> bool { + let before = self.changed; + self.reset(); + before + } + + /// Resets the changed tracker to be false + pub fn reset(&mut self) { + self.changed = false; + } + + /// Silently mutate the inner data, this wont be tracked + pub fn silent_mutate(&mut self) -> &mut T { + &mut self.data + } + + /// Consumes self and returns the data stored inside. + pub fn take(self) -> T { + self.data + } +} + +impl Deref for Ct { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.data + } +} + +impl DerefMut for Ct { + fn deref_mut(&mut self) -> &mut Self::Target { + self.changed = true; + &mut self.data + } +} + +#[cfg(test)] +mod tests { + use super::Ct; + + #[test] + fn new() { + let mut c = Ct::new(100); + assert!(!c.changed()); + + let mut c = Ct::new_true(100); + assert!(c.changed()); + } + + #[test] + fn change_tracking() { + let mut c = Ct::new(100); + assert!(!c.changed()); + + *c = 10; + assert!(c.changed()); + assert!(!c.changed()); // should now be not changed + } + + #[test] + fn silent_mutate() { + let mut c = Ct::new(100); + let a = c.silent_mutate(); + *a = 10; + assert!(!c.changed()); + } + + #[test] + fn reset() { + let mut c = Ct::new(100); + *c = 10; + c.reset(); + assert!(!c.changed()); // should not be changed because of reset + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index d599eed..4c01741 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ pub mod math; pub mod input; pub mod castable_any; pub mod plugin; +pub mod change_tracker; pub use lyra_resource as assets;