Skip to main content

anathema_state/
states.rs

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    /// Remove and return a given state.
338    ///
339    /// # Panics
340    ///
341    /// Will panic if the state does not exist.
342    pub fn remove(&mut self, state_id: StateId) -> Value<Box<dyn State>> {
343        self.inner.remove(state_id)
344    }
345}