anathema_state/
lib.rs

1use std::fmt::Display;
2
3pub use anathema_state_derive::State;
4use anathema_store::slab::Key;
5
6pub use crate::colors::{Color, FromColor};
7pub use crate::numbers::Number;
8pub use crate::states::{AnyMap, State, StateId, States, TypeId};
9pub use crate::store::watchers::Watcher;
10pub use crate::store::{
11    Change, Changes, SubTo, Subscriber, Watched, clear_all_changes, clear_all_subs, drain_changes, drain_watchers,
12};
13pub use crate::value::{List, Map, Maybe, Nullable, PendingValue, SharedState, Type, Value, ValueRef};
14
15mod colors;
16mod numbers;
17mod states;
18mod store;
19mod value;
20
21// -----------------------------------------------------------------------------
22//   - Macro requirements -
23// -----------------------------------------------------------------------------
24#[allow(unused_extern_crates)]
25extern crate self as anathema;
26#[allow(unused_imports)]
27pub use crate as state;
28
29#[derive(Debug, Copy, Clone, PartialEq)]
30pub enum Path<'e> {
31    Key(&'e str),
32    Index(usize),
33}
34
35impl From<usize> for Path<'_> {
36    fn from(value: usize) -> Self {
37        Self::Index(value)
38    }
39}
40
41impl<'a> From<&'a str> for Path<'a> {
42    fn from(value: &'a str) -> Self {
43        Self::Key(value)
44    }
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
48pub struct Hex {
49    pub r: u8,
50    pub g: u8,
51    pub b: u8,
52}
53
54impl Hex {
55    pub const BLACK: Self = Self { r: 0, g: 0, b: 0 };
56    pub const BLUE: Self = Self { r: 0, g: 0, b: 255 };
57    pub const GREEN: Self = Self { r: 0, g: 255, b: 0 };
58    pub const RED: Self = Self { r: 255, g: 0, b: 0 };
59    pub const WHITE: Self = Self { r: 255, g: 255, b: 255 };
60
61    pub const fn red_f32(&self) -> f32 {
62        self.r as f32 / u8::MAX as f32
63    }
64
65    pub const fn green_f32(&self) -> f32 {
66        self.g as f32 / u8::MAX as f32
67    }
68
69    pub const fn blue_f32(&self) -> f32 {
70        self.b as f32 / u8::MAX as f32
71    }
72}
73
74impl Display for Hex {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        write!(f, "#{:x}{:x}{:x}", self.r, self.g, self.b)
77    }
78}
79
80impl From<(u8, u8, u8)> for Hex {
81    fn from((r, g, b): (u8, u8, u8)) -> Self {
82        Self { r, g, b }
83    }
84}
85
86impl From<(f32, f32, f32)> for Hex {
87    fn from((r, g, b): (f32, f32, f32)) -> Self {
88        let r = (r * u8::MAX as f32) as u8;
89        let g = (g * u8::MAX as f32) as u8;
90        let b = (b * u8::MAX as f32) as u8;
91        Self { r, g, b }
92    }
93}
94
95impl TryFrom<&str> for Hex {
96    type Error = ();
97
98    fn try_from(hex: &str) -> Result<Self, Self::Error> {
99        if hex.is_empty() || !hex.starts_with("#") {
100            return Err(());
101        }
102
103        let hex = &hex[1..];
104        match hex.len() {
105            3 => {
106                let r = u8::from_str_radix(&hex[0..1], 16).map_err(|_| ())?;
107                let r = r << 4 | r;
108                let g = u8::from_str_radix(&hex[1..2], 16).map_err(|_| ())?;
109                let g = g << 4 | g;
110                let b = u8::from_str_radix(&hex[2..3], 16).map_err(|_| ())?;
111                let b = b << 4 | b;
112                Ok(Self::from((r, g, b)))
113            }
114            6 => {
115                let r = u8::from_str_radix(&hex[0..2], 16).map_err(|_| ())?;
116                let g = u8::from_str_radix(&hex[2..4], 16).map_err(|_| ())?;
117                let b = u8::from_str_radix(&hex[4..6], 16).map_err(|_| ())?;
118                Ok(Self::from((r, g, b)))
119            }
120            _ => Err(()),
121        }
122    }
123}
124
125#[cfg(test)]
126mod test {
127    use super::*;
128
129    #[test]
130    fn from_str_for_hex() {
131        let case1 = "#aabbcc";
132        let case2 = "#abc";
133
134        let result_1 = Hex::try_from(case1).unwrap();
135        let result_2 = Hex::try_from(case2).unwrap();
136        let expected = Hex::from((0xaa, 0xbb, 0xcc));
137
138        assert_eq!(result_1, expected);
139        assert_eq!(result_2, expected);
140    }
141}