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#[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}