Skip to main content

chromashift/
hex.rs

1use crate::{Srgb, ToAlpha};
2use core::fmt;
3
4/// An Hex representation of the sRGB colour space.
5#[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 [red, green, blue, _] = self.0.to_be_bytes();
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 [red, green, blue, alpha] = self.0.to_be_bytes();
24		is_shorthand_byte(red) && is_shorthand_byte(green) && is_shorthand_byte(blue) && is_shorthand_byte(alpha)
25	}
26
27	pub const fn has_alpha(&self) -> bool {
28		self.0 & 0xFF != 0xFF
29	}
30}
31
32impl ToAlpha for Hex {
33	fn to_alpha(&self) -> f32 {
34		((self.0 & 0xFF) as f32 / 255.0) * 100.0
35	}
36}
37
38impl fmt::Display for Hex {
39	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40		let [red, green, blue, alpha] = self.0.to_be_bytes();
41		if self.can_use_3_digit() {
42			write!(f, "#{:x}{:x}{:x}", red & 0xF, green & 0xF, blue & 0xF)
43		} else if self.can_use_4_digit() {
44			write!(f, "#{:x}{:x}{:x}{:x}", red & 0xF, green & 0xF, blue & 0xF, alpha & 0xF)
45		} else if self.has_alpha() {
46			write!(f, "#{red:02x}{green:02x}{blue:02x}{alpha:02x}")
47		} else {
48			write!(f, "#{red:02x}{green:02x}{blue:02x}")
49		}
50	}
51}
52
53impl From<Hex> for Srgb {
54	fn from(value: Hex) -> Self {
55		let [red, green, blue, alpha] = value.0.to_be_bytes();
56		Srgb::from_u8(red, green, blue, alpha as f32 * 100.0 / 255.0)
57	}
58}
59
60impl From<Srgb> for Hex {
61	fn from(value: Srgb) -> Self {
62		let [red, green, blue] = value.to_u8();
63		let alpha = value.alpha;
64		Hex::new(
65			((red as u32) << 24)
66				| ((green as u32) << 16)
67				| ((blue as u32) << 8)
68				| ((alpha * 255.0 / 100.0).round() as u32),
69		)
70	}
71}