use crate::{BalancedColour, Colour, Component, DefinedGamut};
#[cfg(feature = "bytemuck")]
use bytemuck::{Pod, Zeroable};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "zerocopy")]
use zerocopy::{FromZeros, Immutable, IntoBytes};
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "zerocopy", derive(FromZeros, Immutable, IntoBytes))]
pub struct OkLab<T>([T; 0x3]);
impl<T: Component> OkLab<T> {
#[inline(always)]
#[must_use]
pub const fn new(luminance: T, a_star: T, b_star: T) -> Self {
let data = [luminance, a_star, b_star];
Self(data)
}
#[inline]
#[must_use]
pub fn map<U, F>(self, mut op: F) -> OkLab<U>
where
U: Component,
F: FnMut(T) -> U,
{
let (luminance, a_star, b_star) = self.get();
let luminance = op(luminance);
let a_star = op(a_star);
let b_star = op(b_star);
OkLab::new(luminance, a_star, b_star)
}
#[inline(always)]
#[must_use]
pub const fn get(self) -> (T, T, T) {
let [luminance, a_star, b_star] = self.0;
(luminance, a_star, b_star)
}
}
unsafe impl<T: Component> BalancedColour for OkLab<T> {
type Component = T;
}
impl<T: Component> Colour for OkLab<T> { }
impl<T: Component> DefinedGamut for OkLab<T> { }