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}