1use std::fmt::{self, Debug, Formatter};
2use std::marker::PhantomData;
3use std::ops::DerefMut;
4
5use generational_box::GenerationalBox;
6
7use crate::{ComposeNode, Composer, Loc, NodeKey};
8
9pub struct State<T, N>
10where
11 N: ComposeNode,
12{
13 pub id: StateId,
14 composer: GenerationalBox<Composer<N>>,
15 ty: PhantomData<T>,
16}
17
18impl<T, N> State<T, N>
19where
20 T: 'static,
21 N: ComposeNode,
22{
23 #[inline(always)]
24 pub(crate) fn new(id: StateId, composer: GenerationalBox<Composer<N>>) -> Self {
25 Self {
26 id,
27 composer,
28 ty: PhantomData,
29 }
30 }
31
32 pub fn with<F, U>(&self, func: F) -> U
33 where
34 F: Fn(&T) -> U,
35 {
36 let mut c = self.composer.write();
37 let c = c.deref_mut();
38 let current_node_key = c.current_node_key;
39 let used_by = c.used_by.entry(self.id).or_default();
40 used_by.insert(current_node_key);
41 let uses = c.uses.entry(current_node_key).or_default();
42 uses.insert(self.id);
43 let scope_states = c.states.get(&self.id.node_key).unwrap();
44 let any_state = scope_states.get(&self.id).unwrap();
45 let state = any_state.downcast_ref::<T>().unwrap();
46 func(state)
47 }
48
49 pub fn with_untracked<F, U>(&self, func: F) -> U
50 where
51 F: Fn(&T) -> U,
52 {
53 let mut c = self.composer.write();
54 let c = c.deref_mut();
55 let scope_states = c.states.get(&self.id.node_key).unwrap();
56 let any_state = scope_states.get(&self.id).unwrap();
57 let state = any_state.downcast_ref::<T>().unwrap();
58 func(state)
59 }
60
61 pub fn with_mut<F, U>(&self, func: F) -> U
62 where
63 F: Fn(&mut T) -> U,
64 {
65 let mut c = self.composer.write();
66 let c = c.deref_mut();
67 let current_node_key = c.current_node_key;
68 let used_by = c.used_by.entry(self.id).or_default();
69 used_by.insert(current_node_key);
70 let uses = c.uses.entry(current_node_key).or_default();
71 uses.insert(self.id);
72 let scope_states = c.states.get_mut(&self.id.node_key).unwrap();
73 let any_state = scope_states.get_mut(&self.id).unwrap();
74 let state = any_state.downcast_mut::<T>().unwrap();
75 c.dirty_states.insert(self.id);
76 func(state)
77 }
78
79 pub fn with_mut_untracked<F, U>(&self, func: F) -> U
80 where
81 F: Fn(&mut T) -> U,
82 {
83 let mut c = self.composer.write();
84 let c = c.deref_mut();
85 let scope_states = c.states.get_mut(&self.id.node_key).unwrap();
86 let any_state = scope_states.get_mut(&self.id).unwrap();
87 let state = any_state.downcast_mut::<T>().unwrap();
88 c.dirty_states.insert(self.id);
89 func(state)
90 }
91
92 pub fn get(&self) -> T
93 where
94 T: Clone,
95 {
96 let mut c = self.composer.write();
97 let c = c.deref_mut();
98 let current_node_key = c.current_node_key;
99 let used_by = c.used_by.entry(self.id).or_default();
100 used_by.insert(current_node_key);
101 let uses = c.uses.entry(current_node_key).or_default();
102 uses.insert(self.id);
103 let scope_states = c.states.get(&self.id.node_key).unwrap();
104 let any_state = scope_states.get(&self.id).unwrap();
105 let state = any_state.downcast_ref::<T>().unwrap();
106 state.clone()
107 }
108
109 pub fn get_untracked(&self) -> T
110 where
111 T: Clone,
112 {
113 let mut c = self.composer.write();
114 let c = c.deref_mut();
115 let scope_states = c.states.get(&self.id.node_key).unwrap();
116 let any_state = scope_states.get(&self.id).unwrap();
117 let state = any_state.downcast_ref::<T>().unwrap();
118 state.clone()
119 }
120
121 pub fn set(&self, value: T) {
122 let mut c = self.composer.write();
123 let c = c.deref_mut();
124 c.dirty_states.insert(self.id);
125 let scope_states = c.states.entry(self.id.node_key).or_default();
126 let val = scope_states.get_mut(&self.id).unwrap();
127 *val = Box::new(value);
128 }
129}
130
131impl<T, N> Debug for State<T, N>
132where
133 N: ComposeNode,
134{
135 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
136 f.debug_struct("State")
137 .field("id", &self.id)
138 .field("ty", &self.ty)
139 .finish()
140 }
141}
142
143impl<T, N> Clone for State<T, N>
144where
145 N: ComposeNode,
146{
147 fn clone(&self) -> Self {
148 *self
149 }
150}
151
152impl<T, N> Copy for State<T, N> where N: ComposeNode {}
153
154#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
155pub struct StateId {
156 pub(crate) node_key: NodeKey,
157 loc: Loc,
158}
159
160impl StateId {
161 #[track_caller]
162 #[inline(always)]
163 pub fn new(node_key: NodeKey) -> Self {
164 Self {
165 node_key,
166 loc: Loc::new(),
167 }
168 }
169}
170
171impl Debug for StateId {
172 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
173 write!(f, "StateId({:?},{:?})", self.node_key, self.loc)
174 }
175}