#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct VoxColor(pub u32);
impl VoxColor {
#[must_use]
pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
Self(0x8000_0000 | ((r as u32) << 16) | ((g as u32) << 8) | b as u32)
}
#[must_use]
pub const fn with_brightness(self, brightness: u8) -> Self {
Self((self.0 & 0x00ff_ffff) | ((brightness as u32) << 24))
}
#[must_use]
pub const fn rgb_part(self) -> Rgb {
Rgb(self.0 & 0x00ff_ffff)
}
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct Rgb(pub u32);
impl Rgb {
pub const WHITE: Self = Self(0x00ff_ffff);
#[must_use]
pub const fn new(r: u8, g: u8, b: u8) -> Self {
Self(((r as u32) << 16) | ((g as u32) << 8) | b as u32)
}
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct OverlayColor(pub u32);
impl OverlayColor {
#[must_use]
pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
Self(((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | b as u32)
}
#[must_use]
pub const fn opaque(r: u8, g: u8, b: u8) -> Self {
Self::rgba(r, g, b, 0xff)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn packings_match_their_wire_layouts() {
assert_eq!(VoxColor::rgb(0x4d, 0x8a, 0x3a).0, 0x804d_8a3a);
assert_eq!(
VoxColor::rgb(0x4d, 0x8a, 0x3a).with_brightness(0xff).0,
0xff4d_8a3a
);
assert_eq!(VoxColor(0x804d_8a3a).rgb_part(), Rgb(0x004d_8a3a));
assert_eq!(Rgb::new(0x8f, 0xbc, 0xd4).0, 0x008f_bcd4);
assert_eq!(OverlayColor::rgba(0xff, 0xd0, 0x40, 0xff).0, 0xffff_d040);
assert_eq!(
OverlayColor::opaque(1, 2, 3),
OverlayColor::rgba(1, 2, 3, 0xff)
);
}
}