Skip to main content

telex/
state.rs

1use std::cell::RefCell;
2use std::fmt;
3use std::rc::Rc;
4
5/// A reactive state handle that can be copied and shared.
6///
7/// State<T> is Copy, allowing closures to capture it without explicit cloning.
8/// Internally it wraps Rc<RefCell<T>> for shared mutable state.
9pub struct State<T> {
10    inner: Rc<StateInner<T>>,
11}
12
13struct StateInner<T> {
14    value: RefCell<T>,
15    /// Flag to track if state changed since last render
16    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
27// Note: State is cheap to clone (just Rc pointer copy).
28// Use .clone() in closures or move semantics.
29
30impl<T> State<T> {
31    /// Create a new state with the given initial value.
32    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    /// Get a clone of the current value.
42    pub fn get(&self) -> T
43    where
44        T: Clone,
45    {
46        self.inner.value.borrow().clone()
47    }
48
49    /// Set a new value.
50    pub fn set(&self, value: T) {
51        *self.inner.value.borrow_mut() = value;
52        *self.inner.dirty.borrow_mut() = true;
53    }
54
55    /// Update the value using a function.
56    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    /// Check if state has changed since last clear_dirty call.
62    pub fn is_dirty(&self) -> bool {
63        *self.inner.dirty.borrow()
64    }
65
66    /// Clear the dirty flag.
67    pub fn clear_dirty(&self) {
68        *self.inner.dirty.borrow_mut() = false;
69    }
70
71    /// Borrow the value immutably.
72    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}