use crate::{BalancedColour, Colour, DefinedGamut};
use core::mem::{ManuallyDrop, offset_of};
#[cfg(feature = "bytemuck")]
use bytemuck::{Pod, Zeroable};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "zerocopy")]
use zerocopy::{FromZeros, Immutable, IntoBytes};
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "zerocopy", derive(FromZeros, Immutable))]
pub struct Alpha<T: BalancedColour> {
colour: T,
alpha: T::Component,
}
impl<T: BalancedColour> Alpha<T> {
#[inline(always)]
#[must_use]
pub const fn attach(colour: T, alpha: T::Component) -> Self {
Self { colour, alpha }
}
#[inline]
#[must_use]
pub const fn as_colour(&self) -> &T {
&self.colour
}
#[inline]
#[must_use]
pub const fn as_mut_colour(&mut self) -> &mut T {
&mut self.colour
}
#[inline]
#[must_use]
pub const fn detach(self) -> (T, T::Component) {
let alpha = self.alpha;
let this = ManuallyDrop::new(self);
let ptr = &raw const this as *const Self;
let colour = {
let off = offset_of!(Self, colour);
let ptr = unsafe { ptr.byte_add(off) } as *const T;
unsafe { ptr.read() }
};
(colour, alpha)
}
}
impl<T: BalancedColour> Colour for Alpha<T> { }
unsafe impl<T: BalancedColour> BalancedColour for Alpha<T> {
type Component = T::Component;
}
impl<T: BalancedColour + DefinedGamut> DefinedGamut for Alpha<T> { }
#[cfg(feature = "zerocopy")]
unsafe impl<T> IntoBytes for Alpha<T>
where
T: BalancedColour + IntoBytes,
T::Component: IntoBytes,
{
fn only_derive_is_allowed_to_implement_this_trait() { }
}
#[cfg(feature = "bytemuck")]
unsafe impl<T> Pod for Alpha<T>
where
T: BalancedColour + Pod,
T::Component: Pod,
{ }
#[cfg(feature = "bytemuck")]
unsafe impl<T> Zeroable for Alpha<T>
where
T: BalancedColour + Zeroable,
T::Component: Zeroable,
{ }