Add a change tracker type

This commit is contained in:
SeanOMik 2023-09-16 11:52:20 -04:00
parent cc1cfdbc68
commit 461b41695b
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
2 changed files with 104 additions and 0 deletions

103
src/change_tracker.rs Normal file
View File

@ -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<T> {
data: T,
changed: bool,
}
impl<T> Ct<T> {
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<T> Deref for Ct<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<T> DerefMut for Ct<T> {
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
}
}

View File

@ -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;