1#![doc = include_str!("../README.md")]
2use std::ops::{Deref, DerefMut};
3
4#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
6pub struct Dirty<T> {
7 pub data: T,
9 pub dirty: bool,
11}
12
13impl<T> Dirty<T> {
14 pub fn new(data: T) -> Self {
16 Self { data, dirty: false }
17 }
18
19 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 pub fn as_dirty(&self) -> Option<&T> {
29 self.dirty.then_some(&self.data)
30 }
31
32 pub fn as_clean(&self) -> Option<&T> {
34 (!self.dirty).then_some(&self.data)
35 }
36
37 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 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}