color.rs

  1use std::{
  2    borrow::Cow,
  3    fmt,
  4    ops::{Deref, DerefMut},
  5};
  6
  7use crate::json::ToJson;
  8use pathfinder_color::ColorU;
  9use serde::{
 10    de::{self, Unexpected},
 11    Deserialize, Deserializer,
 12};
 13use serde_json::json;
 14
 15#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
 16#[repr(transparent)]
 17pub struct Color(ColorU);
 18
 19impl Color {
 20    pub fn transparent_black() -> Self {
 21        Self(ColorU::transparent_black())
 22    }
 23
 24    pub fn black() -> Self {
 25        Self(ColorU::black())
 26    }
 27
 28    pub fn white() -> Self {
 29        Self(ColorU::white())
 30    }
 31
 32    pub fn red() -> Self {
 33        Self(ColorU::from_u32(0xff0000ff))
 34    }
 35
 36    pub fn green() -> Self {
 37        Self(ColorU::from_u32(0x00ff00ff))
 38    }
 39
 40    pub fn blue() -> Self {
 41        Self(ColorU::from_u32(0x0000ffff))
 42    }
 43
 44    pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
 45        Self(ColorU::new(r, g, b, a))
 46    }
 47
 48    pub fn from_u32(rgba: u32) -> Self {
 49        Self(ColorU::from_u32(rgba))
 50    }
 51}
 52
 53impl<'de> Deserialize<'de> for Color {
 54    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
 55    where
 56        D: Deserializer<'de>,
 57    {
 58        let literal: Cow<str> = Deserialize::deserialize(deserializer)?;
 59        if let Some(digits) = literal.strip_prefix('#') {
 60            if let Ok(value) = u32::from_str_radix(digits, 16) {
 61                if digits.len() == 6 {
 62                    return Ok(Color::from_u32((value << 8) | 0xFF));
 63                } else if digits.len() == 8 {
 64                    return Ok(Color::from_u32(value));
 65                }
 66            }
 67        }
 68        Err(de::Error::invalid_value(
 69            Unexpected::Str(literal.as_ref()),
 70            &"#RRGGBB[AA]",
 71        ))
 72    }
 73}
 74
 75impl ToJson for Color {
 76    fn to_json(&self) -> serde_json::Value {
 77        json!(format!(
 78            "0x{:x}{:x}{:x}{:x}",
 79            self.0.r, self.0.g, self.0.b, self.0.a
 80        ))
 81    }
 82}
 83
 84impl Deref for Color {
 85    type Target = ColorU;
 86    fn deref(&self) -> &Self::Target {
 87        &self.0
 88    }
 89}
 90
 91impl DerefMut for Color {
 92    fn deref_mut(&mut self) -> &mut Self::Target {
 93        &mut self.0
 94    }
 95}
 96
 97impl fmt::Debug for Color {
 98    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 99        self.0.fmt(f)
100    }
101}