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)]
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 new(r: u8, g: u8, b: u8, a: u8) -> Self {
37        Self(ColorU::new(r, g, b, a))
38    }
39
40    pub fn from_u32(rgba: u32) -> Self {
41        Self(ColorU::from_u32(rgba))
42    }
43}
44
45impl<'de> Deserialize<'de> for Color {
46    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
47    where
48        D: Deserializer<'de>,
49    {
50        let literal: Cow<str> = Deserialize::deserialize(deserializer)?;
51        if let Some(digits) = literal.strip_prefix('#') {
52            if let Ok(value) = u32::from_str_radix(digits, 16) {
53                if digits.len() == 6 {
54                    return Ok(Color::from_u32((value << 8) | 0xFF));
55                } else if digits.len() == 8 {
56                    return Ok(Color::from_u32(value));
57                }
58            }
59        }
60        Err(de::Error::invalid_value(
61            Unexpected::Str(literal.as_ref()),
62            &"#RRGGBB[AA]",
63        ))
64    }
65}
66
67impl ToJson for Color {
68    fn to_json(&self) -> serde_json::Value {
69        json!(format!(
70            "0x{:x}{:x}{:x}{:x}",
71            self.0.r, self.0.g, self.0.b, self.0.a
72        ))
73    }
74}
75
76impl Deref for Color {
77    type Target = ColorU;
78    fn deref(&self) -> &Self::Target {
79        &self.0
80    }
81}
82
83impl DerefMut for Color {
84    fn deref_mut(&mut self) -> &mut Self::Target {
85        &mut self.0
86    }
87}
88
89impl fmt::Debug for Color {
90    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        self.0.fmt(f)
92    }
93}