1use crate::props::{Props, PropsData, PropsError};
4use std::{any::TypeId, sync::mpsc::Sender};
5
6#[derive(Debug, Clone)]
7pub enum StateError {
8 Props(PropsError),
9 CouldNotWriteChange,
10}
11
12#[derive(Debug, Clone)]
13pub enum StateChange {
14 Set(Props),
15 Include(Props),
16 Exclude(TypeId),
17}
18
19#[derive(Clone)]
20pub struct StateUpdate(Sender<StateChange>);
21
22impl StateUpdate {
23 pub fn new(sender: Sender<StateChange>) -> Self {
24 Self(sender)
25 }
26
27 pub fn set<T>(&self, data: T) -> Result<(), StateError>
28 where
29 T: Into<Props>,
30 {
31 if self.0.send(StateChange::Set(data.into())).is_err() {
32 Err(StateError::CouldNotWriteChange)
33 } else {
34 Ok(())
35 }
36 }
37
38 pub fn include<T>(&self, data: T) -> Result<(), StateError>
39 where
40 T: Into<Props>,
41 {
42 let data = data.into();
43 if self.0.send(StateChange::Include(data)).is_err() {
44 Err(StateError::CouldNotWriteChange)
45 } else {
46 Ok(())
47 }
48 }
49
50 pub fn exclude<T>(&self) -> Result<(), StateError>
51 where
52 T: 'static + PropsData,
53 {
54 if self
55 .0
56 .send(StateChange::Exclude(TypeId::of::<T>()))
57 .is_err()
58 {
59 Err(StateError::CouldNotWriteChange)
60 } else {
61 Ok(())
62 }
63 }
64}
65
66pub struct State<'a> {
67 data: &'a Props,
68 update: StateUpdate,
69}
70
71impl<'a> State<'a> {
72 pub fn new(data: &'a Props, update: StateUpdate) -> Self {
73 Self { data, update }
74 }
75
76 #[inline]
77 pub fn data(&self) -> &Props {
78 self.data
79 }
80
81 pub fn has<T>(&self) -> bool
82 where
83 T: 'static + PropsData,
84 {
85 self.data.has::<T>()
86 }
87
88 pub fn read<T>(&self) -> Result<&'a T, StateError>
89 where
90 T: 'static + PropsData,
91 {
92 match self.data.read() {
93 Ok(v) => Ok(v),
94 Err(e) => Err(StateError::Props(e)),
95 }
96 }
97
98 pub fn map_or_default<T, R, F>(&self, f: F) -> R
99 where
100 T: 'static + PropsData,
101 R: Default,
102 F: FnMut(&T) -> R,
103 {
104 self.data.map_or_default(f)
105 }
106
107 pub fn map_or_else<T, R, F, E>(&self, f: F, e: E) -> R
108 where
109 T: 'static + PropsData,
110 F: FnMut(&T) -> R,
111 E: FnMut() -> R,
112 {
113 self.data.map_or_else(f, e)
114 }
115
116 pub fn read_cloned<T>(&self) -> Result<T, StateError>
117 where
118 T: 'static + PropsData + Clone,
119 {
120 match self.data.read_cloned() {
121 Ok(v) => Ok(v),
122 Err(e) => Err(StateError::Props(e)),
123 }
124 }
125
126 pub fn read_cloned_or_default<T>(&self) -> T
127 where
128 T: 'static + PropsData + Clone + Default,
129 {
130 self.data.read_cloned_or_default()
131 }
132
133 pub fn read_cloned_or_else<T, F>(&self, f: F) -> T
134 where
135 T: 'static + PropsData + Clone + Default,
136 F: FnMut() -> T,
137 {
138 self.data.read_cloned_or_else(f)
139 }
140
141 pub fn write<T>(&self, data: T) -> Result<(), StateError>
142 where
143 T: 'static + PropsData + Send + Sync,
144 {
145 self.update.set(data)
146 }
147
148 pub fn write_with<T>(&self, data: T) -> Result<(), StateError>
149 where
150 T: 'static + PropsData + Send + Sync,
151 {
152 self.update.include(data)
153 }
154
155 pub fn write_without<T>(&self) -> Result<(), StateError>
156 where
157 T: 'static + PropsData + Send + Sync,
158 {
159 self.update.exclude::<T>()
160 }
161
162 pub fn mutate<T, F>(&self, mut f: F) -> Result<(), StateError>
163 where
164 T: 'static + PropsData + Send + Sync,
165 F: FnMut(&T) -> T,
166 {
167 match self.read() {
168 Ok(data) => {
169 let data = f(data);
170 self.write(data)
171 }
172 Err(error) => Err(error),
173 }
174 }
175
176 pub fn mutate_cloned<T, F>(&self, mut f: F) -> Result<(), StateError>
177 where
178 T: 'static + PropsData + Send + Sync + Clone,
179 F: FnMut(&mut T),
180 {
181 match self.read::<T>() {
182 Ok(data) => {
183 let mut data = data.clone();
184 f(&mut data);
185 self.write(data)
186 }
187 Err(error) => Err(error),
188 }
189 }
190
191 pub fn update(&self) -> &StateUpdate {
192 &self.update
193 }
194}