Skip to main content

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::{AnyList, 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)]
48#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
49pub struct Hex {
50    pub r: u8,
51    pub g: u8,
52    pub b: u8,
53}
54
55impl Hex {
56    pub const BLACK: Self = Self { r: 0, g: 0, b: 0 };
57    pub const BLUE: Self = Self { r: 0, g: 0, b: 255 };
58    pub const GREEN: Self = Self { r: 0, g: 255, b: 0 };
59    pub const RED: Self = Self { r: 255, g: 0, b: 0 };
60    pub const WHITE: Self = Self { r: 255, g: 255, b: 255 };
61
62    pub const fn red_f32(&self) -> f32 {
63        self.r as f32 / u8::MAX as f32
64    }
65
66    pub const fn green_f32(&self) -> f32 {
67        self.g as f32 / u8::MAX as f32
68    }
69
70    pub const fn blue_f32(&self) -> f32 {
71        self.b as f32 / u8::MAX as f32
72    }
73
74    pub fn as_u32(&self) -> u32 {
75        ((self.r as u32) << 16) | ((self.g as u32) << 8) | (self.b as u32)
76    }
77}
78
79impl Display for Hex {
80    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81        write!(f, "#{:x}{:x}{:x}", self.r, self.g, self.b)
82    }
83}
84
85impl From<(u8, u8, u8)> for Hex {
86    fn from((r, g, b): (u8, u8, u8)) -> Self {
87        Self { r, g, b }
88    }
89}
90
91impl From<(f32, f32, f32)> for Hex {
92    fn from((r, g, b): (f32, f32, f32)) -> Self {
93        let r = (r * u8::MAX as f32) as u8;
94        let g = (g * u8::MAX as f32) as u8;
95        let b = (b * u8::MAX as f32) as u8;
96        Self { r, g, b }
97    }
98}
99
100impl TryFrom<&str> for Hex {
101    type Error = ();
102
103    fn try_from(hex: &str) -> Result<Self, Self::Error> {
104        if hex.is_empty() || !hex.starts_with("#") {
105            return Err(());
106        }
107
108        let hex = &hex[1..];
109        match hex.len() {
110            3 => {
111                let r = u8::from_str_radix(&hex[0..1], 16).map_err(|_| ())?;
112                let r = r << 4 | r;
113                let g = u8::from_str_radix(&hex[1..2], 16).map_err(|_| ())?;
114                let g = g << 4 | g;
115                let b = u8::from_str_radix(&hex[2..3], 16).map_err(|_| ())?;
116                let b = b << 4 | b;
117                Ok(Self::from((r, g, b)))
118            }
119            6 => {
120                let r = u8::from_str_radix(&hex[0..2], 16).map_err(|_| ())?;
121                let g = u8::from_str_radix(&hex[2..4], 16).map_err(|_| ())?;
122                let b = u8::from_str_radix(&hex[4..6], 16).map_err(|_| ())?;
123                Ok(Self::from((r, g, b)))
124            }
125            _ => Err(()),
126        }
127    }
128}
129
130#[cfg(test)]
131mod test {
132    use super::*;
133
134    #[test]
135    fn from_str_for_hex() {
136        let case1 = "#aabbcc";
137        let case2 = "#abc";
138
139        let result_1 = Hex::try_from(case1).unwrap();
140        let result_2 = Hex::try_from(case2).unwrap();
141        let expected = Hex::from((0xaa, 0xbb, 0xcc));
142
143        assert_eq!(result_1, expected);
144        assert_eq!(result_2, expected);
145    }
146}