dirtytype/
lib.rs

1#![doc = include_str!("../README.md")]
2use std::ops::{Deref, DerefMut};
3
4/// A struct that stores a `T` and marks if the data inside has been modified.
5#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
6pub struct Dirty<T> {
7    /// The data stored in the type. Typically accessed by dereferencing, but can be modified here to avoid being marked as dirty.
8    pub data: T,
9    /// Whether the data is dirty or not.
10    pub dirty: bool,
11}
12
13impl<T> Dirty<T> {
14    /// Create a new `Clean` value of `t`.
15    pub fn new(data: T) -> Self {
16        Self { data, dirty: false }
17    }
18
19    /// Calls the closure if the data is dirty, and then marks the data as clean.
20    pub fn clean(&mut self, mut f: impl FnMut(&mut T)) {
21        if self.dirty {
22            self.dirty = false;
23            f(&mut self.data);
24        }
25    }
26
27    /// Returns a reference to the held value if it is dirty and `None` otherwise.
28    pub fn as_dirty(&self) -> Option<&T> {
29        self.dirty.then_some(&self.data)
30    }
31
32    /// Returns a reference to the held value if it is clean and `None` otherwise.
33    pub fn as_clean(&self) -> Option<&T> {
34        (!self.dirty).then_some(&self.data)
35    }
36
37    /// Returns a mutable reference to the held value if it is dirty and `None` otherwise.
38    pub fn as_dirty_mut(&mut self) -> Option<&mut T> {
39        if self.dirty {
40            Some(&mut self.data)
41        } else {
42            None
43        }
44    }
45
46    /// Returns a mutable reference to the held value if it is clean and `None` otherwise.
47    pub fn as_clean_mut(&mut self) -> Option<&mut T> {
48        if self.dirty {
49            None
50        } else {
51            Some(&mut self.data)
52        }
53    }
54}
55
56impl<T> AsRef<T> for Dirty<T> {
57    fn as_ref(&self) -> &T {
58        self
59    }
60}
61
62impl<T> AsMut<T> for Dirty<T> {
63    fn as_mut(&mut self) -> &mut T {
64        self
65    }
66}
67
68impl<T: Default> Default for Dirty<T> {
69    fn default() -> Self {
70        Self::new(T::default())
71    }
72}
73
74impl<T> Deref for Dirty<T> {
75    type Target = T;
76    fn deref(&self) -> &Self::Target {
77        &self.data
78    }
79}
80
81impl<T> DerefMut for Dirty<T> {
82    fn deref_mut(&mut self) -> &mut Self::Target {
83        self.dirty = true;
84        &mut self.data
85    }
86}
87
88impl<T> From<T> for Dirty<T> {
89    fn from(value: T) -> Self {
90        Self::new(value)
91    }
92}