1use crate::{Srgb, ToAlpha};
2use core::fmt;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
6pub struct Hex(u32);
7
8const fn is_shorthand_byte(byte: u8) -> bool {
9 (byte >> 4) == (byte & 0xF)
10}
11
12impl Hex {
13 pub const fn new(hex: u32) -> Self {
14 Self(hex)
15 }
16
17 pub fn can_use_3_digit(self) -> bool {
18 let Srgb { red, green, blue, .. } = self.into();
19 !self.has_alpha() && is_shorthand_byte(red) && is_shorthand_byte(green) && is_shorthand_byte(blue)
20 }
21
22 pub fn can_use_4_digit(self) -> bool {
23 let Srgb { red, green, blue, alpha } = self.into();
24 is_shorthand_byte(red)
25 && is_shorthand_byte(green)
26 && is_shorthand_byte(blue)
27 && is_shorthand_byte(((alpha as u32 * 255) / 100) as u8)
28 }
29
30 pub const fn has_alpha(&self) -> bool {
31 self.0 & 0xFF != 0xFF
32 }
33}
34
35impl ToAlpha for Hex {
36 fn to_alpha(&self) -> f32 {
37 ((self.0 & 0xFF) as f32 / 255.0) * 100.0
38 }
39}
40
41impl fmt::Display for Hex {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 let Srgb { red, green, blue, alpha } = (*self).into();
44 let alpha = (alpha as u32 * 255) / 100;
45 if self.can_use_3_digit() {
46 write!(f, "#{:x}{:x}{:x}", red & 0xF, green & 0xF, blue & 0xF)
47 } else if self.can_use_4_digit() {
48 write!(f, "#{:x}{:x}{:x}{:x}", red & 0xF, green & 0xF, blue & 0xF, alpha & 0xF)
49 } else if self.has_alpha() {
50 write!(f, "#{red:02x}{green:02x}{blue:02x}{alpha:02x}")
51 } else {
52 write!(f, "#{red:02x}{green:02x}{blue:02x}")
53 }
54 }
55}
56
57impl From<Hex> for Srgb {
58 fn from(value: Hex) -> Self {
59 let hex = value.0;
60 let r = ((hex >> 24) & 0xFF) as u8;
61 let g = ((hex >> 16) & 0xFF) as u8;
62 let b = ((hex >> 8) & 0xFF) as u8;
63 let alpha = (((hex & 0xFF) * 100) / 255) as f32;
64 Srgb::new(r, g, b, alpha)
65 }
66}
67
68impl From<Srgb> for Hex {
69 fn from(value: Srgb) -> Self {
70 let Srgb { red, green, blue, alpha } = value;
71 Hex::new(((red as u32) << 24) | ((green as u32) << 16) | ((blue as u32) << 8) | ((alpha as u32 * 255) / 100))
72 }
73}