use std::fmt;
use zerocopy::{FromBytes, Immutable, KnownLayout, LittleEndian, U32};
#[derive(Clone, Copy, Default, Eq, PartialEq, FromBytes, Immutable, KnownLayout)]
#[repr(transparent)]
pub struct Color(U32<LittleEndian>);
impl Color {
#[must_use]
#[inline]
pub const fn new(rgba: u32) -> Self {
Self(U32::new(rgba))
}
#[must_use]
pub const fn new_rgba(red: u8, green: u8, blue: u8, alpha: u8) -> Self {
Self(U32::from_bytes([alpha, blue, green, red]))
}
#[must_use]
pub const fn to_rgba(self) -> (u8, u8, u8, u8) {
let [alpha, blue, green, red] = self.0.to_bytes();
(red, green, blue, alpha)
}
#[must_use]
pub const fn to_bytes(self) -> [u8; size_of::<u32>()] {
let [alpha, blue, green, red] = self.0.to_bytes();
[red, green, blue, alpha]
}
#[must_use]
#[inline]
pub const fn get(self) -> u32 {
self.0.get()
}
#[must_use]
pub const fn red(self) -> u8 {
self.0.to_bytes()[3]
}
#[must_use]
pub const fn green(self) -> u8 {
self.0.to_bytes()[2]
}
#[must_use]
pub const fn blue(self) -> u8 {
self.0.to_bytes()[1]
}
#[must_use]
pub const fn alpha(self) -> u8 {
self.0.to_bytes()[0]
}
}
impl fmt::Debug for Color {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (red, green, blue, alpha) = self.to_rgba();
write!(
f,
"Color(red={red}, green={green}, blue={blue}, alpha={alpha}, {self}",
)
}
}
impl fmt::Display for Color {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "#{:08X}", self.0)
}
}
impl From<U32<LittleEndian>> for Color {
fn from(rgba: U32<LittleEndian>) -> Self {
Self(rgba)
}
}
impl From<u32> for Color {
fn from(rgba: u32) -> Self {
Self::new(rgba)
}
}
impl From<(u8, u8, u8, u8)> for Color {
fn from((red, green, blue, alpha): (u8, u8, u8, u8)) -> Self {
Self::new_rgba(red, green, blue, alpha)
}
}
impl From<[u8; size_of::<u32>()]> for Color {
fn from([red, green, blue, alpha]: [u8; size_of::<u32>()]) -> Self {
Self::new_rgba(red, green, blue, alpha)
}
}