1use std::any::Any;
2use std::fmt::Debug;
3
4use anathema_store::slab::{Slab, SlabIndex};
5
6use crate::{Color, Hex, PendingValue, Type, Value};
7
8pub trait TypeId {
9 const TYPE: Type = Type::Composite;
10}
11
12impl TypeId for char {
13 const TYPE: Type = Type::Char;
14}
15
16impl TypeId for String {
17 const TYPE: Type = Type::String;
18}
19
20impl TypeId for bool {
21 const TYPE: Type = Type::Bool;
22}
23
24impl TypeId for Hex {
25 const TYPE: Type = Type::Hex;
26}
27
28impl<T> TypeId for crate::Map<T> {
29 const TYPE: Type = Type::Map;
30}
31
32impl<T> TypeId for crate::List<T> {
33 const TYPE: Type = Type::List;
34}
35
36impl TypeId for () {
37 const TYPE: Type = Type::Unit;
38}
39
40impl TypeId for Color {
41 const TYPE: Type = Type::Color;
42}
43
44#[derive(Debug, Copy, Clone, PartialEq)]
45pub struct StateId(usize);
46
47impl StateId {
48 pub const ZERO: Self = Self(0);
49}
50
51impl SlabIndex for StateId {
52 const MAX: usize = usize::MAX;
53
54 fn as_usize(&self) -> usize {
55 self.0
56 }
57
58 fn from_usize(index: usize) -> Self
59 where
60 Self: Sized,
61 {
62 Self(index)
63 }
64}
65
66pub trait State: Any + 'static {
67 fn type_info(&self) -> Type;
68
69 fn as_int(&self) -> Option<i64> {
70 None
71 }
72
73 fn as_float(&self) -> Option<f64> {
74 None
75 }
76
77 fn as_hex(&self) -> Option<Hex> {
78 None
79 }
80
81 fn as_color(&self) -> Option<Color> {
82 None
83 }
84
85 fn as_char(&self) -> Option<char> {
86 None
87 }
88
89 fn as_str(&self) -> Option<&str> {
90 None
91 }
92
93 fn as_bool(&self) -> Option<bool> {
94 None
95 }
96
97 fn as_any_map(&self) -> Option<&dyn AnyMap> {
98 None
99 }
100
101 fn as_any_list(&self) -> Option<&dyn AnyList> {
102 None
103 }
104
105 fn as_maybe(&self) -> Option<&dyn AnyMaybe> {
106 None
107 }
108}
109
110impl Debug for dyn State {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 write!(f, "<State ({:?})>", self.type_info())
113 }
114}
115
116impl State for Box<dyn State> {
117 fn type_info(&self) -> Type {
118 self.as_ref().type_info()
119 }
120
121 fn as_int(&self) -> Option<i64> {
122 self.as_ref().as_int()
123 }
124
125 fn as_float(&self) -> Option<f64> {
126 self.as_ref().as_float()
127 }
128
129 fn as_char(&self) -> Option<char> {
130 self.as_ref().as_char()
131 }
132
133 fn as_hex(&self) -> Option<Hex> {
134 self.as_ref().as_hex()
135 }
136
137 fn as_color(&self) -> Option<Color> {
138 self.as_ref().as_color()
139 }
140
141 fn as_str(&self) -> Option<&str> {
142 self.as_ref().as_str()
143 }
144
145 fn as_bool(&self) -> Option<bool> {
146 self.as_ref().as_bool()
147 }
148
149 fn as_any_map(&self) -> Option<&dyn AnyMap> {
150 self.as_ref().as_any_map()
151 }
152
153 fn as_any_list(&self) -> Option<&dyn AnyList> {
154 self.as_ref().as_any_list()
155 }
156
157 fn as_maybe(&self) -> Option<&dyn AnyMaybe> {
158 self.as_ref().as_maybe()
159 }
160}
161
162pub trait AnyMap: 'static {
163 fn lookup(&self, key: &str) -> Option<PendingValue>;
164
165 fn is_empty(&self) -> bool;
166}
167
168pub trait AnyList: 'static {
169 fn lookup(&self, index: usize) -> Option<PendingValue>;
170
171 fn len(&self) -> usize;
172
173 fn is_empty(&self) -> bool {
174 self.len() == 0
175 }
176}
177
178impl dyn AnyList {
179 pub fn iter(&self) -> impl Iterator<Item = PendingValue> {
180 let len = self.len();
181 (0..len).filter_map(|i| self.lookup(i))
182 }
183}
184
185pub trait AnyMaybe {
186 fn get(&self) -> Option<PendingValue>;
187}
188
189macro_rules! impl_num_state {
190 ($t:ty) => {
191 impl TypeId for $t {
192 const TYPE: Type = Type::Int;
193 }
194
195 impl State for $t {
196 fn type_info(&self) -> Type {
197 Type::Int
198 }
199
200 fn as_int(&self) -> Option<i64> {
201 Some(*self as i64)
202 }
203 }
204 };
205}
206
207macro_rules! impl_float_state {
208 ($t:ty) => {
209 impl TypeId for $t {
210 const TYPE: Type = Type::Float;
211 }
212
213 impl State for $t {
214 fn type_info(&self) -> Type {
215 Type::Float
216 }
217
218 fn as_float(&self) -> Option<f64> {
219 Some(*self as f64)
220 }
221 }
222 };
223}
224
225impl State for bool {
226 fn type_info(&self) -> Type {
227 Type::Bool
228 }
229
230 fn as_bool(&self) -> Option<bool> {
231 Some(*self)
232 }
233}
234
235impl State for String {
236 fn type_info(&self) -> Type {
237 Type::String
238 }
239
240 fn as_str(&self) -> Option<&str> {
241 Some(self)
242 }
243}
244
245impl State for &'static str {
246 fn type_info(&self) -> Type {
247 Type::String
248 }
249
250 fn as_str(&self) -> Option<&str> {
251 Some(*self)
252 }
253}
254
255impl State for char {
256 fn type_info(&self) -> Type {
257 Type::Char
258 }
259
260 fn as_char(&self) -> Option<char> {
261 Some(*self)
262 }
263}
264
265impl State for Hex {
266 fn type_info(&self) -> Type {
267 Type::Hex
268 }
269
270 fn as_hex(&self) -> Option<Hex> {
271 Some(*self)
272 }
273}
274
275impl State for Color {
276 fn type_info(&self) -> Type {
277 Type::Color
278 }
279
280 fn as_color(&self) -> Option<Color> {
281 Some(*self)
282 }
283}
284
285impl State for () {
286 fn type_info(&self) -> Type {
287 Type::Unit
288 }
289}
290
291impl_num_state!(u8);
292impl_num_state!(i8);
293impl_num_state!(u16);
294impl_num_state!(i16);
295impl_num_state!(u32);
296impl_num_state!(i32);
297impl_num_state!(u64);
298impl_num_state!(i64);
299impl_num_state!(usize);
300impl_num_state!(isize);
301impl_float_state!(f32);
302impl_float_state!(f64);
303
304#[derive(Debug)]
305pub struct States {
306 inner: Slab<StateId, Value<Box<dyn State>>>,
307}
308
309impl States {
310 pub fn new() -> Self {
311 Self { inner: Slab::empty() }
312 }
313
314 pub fn insert(&mut self, state: Box<dyn State>) -> StateId {
315 let state = Value::from_box(state);
316 self.inner.insert(state)
317 }
318
319 pub fn get(&self, state_id: impl Into<StateId>) -> Option<&Value<Box<dyn State>>> {
320 self.inner.get(state_id.into())
321 }
322
323 pub fn get_mut(&mut self, state_id: impl Into<StateId>) -> Option<&mut Value<Box<dyn State>>> {
324 self.inner.get_mut(state_id.into())
325 }
326
327 pub fn with_mut<F, U>(&mut self, index: impl Into<StateId>, f: F) -> U
328 where
329 F: FnOnce(&mut dyn State, &mut Self) -> U,
330 {
331 let mut ticket = self.inner.checkout(index.into());
332 let ret = f(&mut *ticket.to_mut(), self);
333 self.inner.restore(ticket);
334 ret
335 }
336
337 pub fn remove(&mut self, state_id: StateId) -> Value<Box<dyn State>> {
343 self.inner.remove(state_id)
344 }
345}