use substrate_data::schema::NamedType;
use substrate_data::typed::{Spelled, classify};
use substrate_data::{Kind, Value};
use crate::{Res, kinds};
const RGB_DIGITS: usize = 6;
const ARGB_DIGITS: usize = 8;
const OPAQUE: u32 = 0xFF00_0000;
#[derive(Debug, Clone, PartialEq)]
pub enum Color {
Argb(u32),
Res(Res),
}
impl Color {
pub fn parse(s: &str) -> Option<u32> {
let hex = s.strip_prefix(yog_ids::sep::TAG)?;
let value = u32::from_str_radix(hex, 16).ok()?;
match hex.len() {
RGB_DIGITS => Some(OPAQUE | value),
ARGB_DIGITS => Some(value),
_ => None,
}
}
pub fn format(argb: u32) -> String {
format!("{}{argb:08X}", yog_ids::sep::TAG)
}
}
impl NamedType for Color {
const NAME: &'static str = yog_ids::typed::COLOR;
type Stored = Value;
fn to_stored(&self) -> Value {
match self {
Color::Argb(c) => Value::Int(i64::from(*c)),
Color::Res(r) => substrate_data::Schema::write(r),
}
}
fn from_stored(stored: Value) -> Option<Self> {
match stored {
Value::Int(c) => u32::try_from(c).ok().map(Color::Argb),
Value::Str(s) if s.starts_with(yog_ids::sep::TAG) => Color::parse(&s).map(Color::Argb),
Value::Str(s) => match classify(&s).ok()? {
Spelled::Ref(r) if r.kind.as_str() == kinds::Res::NAME => {
Res::parse(r.id.as_str()).map(Color::Res)
}
_ => None,
},
Value::Ref(r) if r.kind.as_str() == kinds::Res::NAME => {
Res::parse(r.id.as_str()).map(Color::Res)
}
_ => None,
}
}
}
substrate_data::named_schema!(Color);