1use std::cell::RefCell;
2use std::fmt;
3use std::rc::Rc;
4
5pub struct State<T> {
10 inner: Rc<StateInner<T>>,
11}
12
13struct StateInner<T> {
14 value: RefCell<T>,
15 dirty: RefCell<bool>,
17}
18
19impl<T> Clone for State<T> {
20 fn clone(&self) -> Self {
21 Self {
22 inner: Rc::clone(&self.inner),
23 }
24 }
25}
26
27impl<T> State<T> {
31 pub fn new(value: T) -> Self {
33 Self {
34 inner: Rc::new(StateInner {
35 value: RefCell::new(value),
36 dirty: RefCell::new(false),
37 }),
38 }
39 }
40
41 pub fn get(&self) -> T
43 where
44 T: Clone,
45 {
46 self.inner.value.borrow().clone()
47 }
48
49 pub fn set(&self, value: T) {
51 *self.inner.value.borrow_mut() = value;
52 *self.inner.dirty.borrow_mut() = true;
53 }
54
55 pub fn update(&self, f: impl FnOnce(&mut T)) {
57 f(&mut self.inner.value.borrow_mut());
58 *self.inner.dirty.borrow_mut() = true;
59 }
60
61 pub fn is_dirty(&self) -> bool {
63 *self.inner.dirty.borrow()
64 }
65
66 pub fn clear_dirty(&self) {
68 *self.inner.dirty.borrow_mut() = false;
69 }
70
71 pub fn with<R>(&self, f: impl FnOnce(&T) -> R) -> R {
73 f(&self.inner.value.borrow())
74 }
75}
76
77impl<T: fmt::Display> fmt::Display for State<T> {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 self.inner.value.borrow().fmt(f)
80 }
81}
82
83impl<T: fmt::Debug> fmt::Debug for State<T> {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 f.debug_tuple("State")
86 .field(&*self.inner.value.borrow())
87 .finish()
88 }
89}