use super::Rgb;
use crate::error::{CubeError, Result};
macro_rules! generate_lut1d_variants {
($(
$variant:ident, $size:expr, $bits:expr
),* $(,)?) => {
#[derive(Clone)]
pub enum Lut1D {
$(
#[doc = concat!($bits, "-bit (", stringify!($size), " points) - heap-allocated array for optimal performance")]
$variant { data: Box<[Rgb; $size]> },
)*
Other { size: usize, data: Vec<Rgb> },
}
impl std::fmt::Debug for Lut1D {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
$(
Lut1D::$variant { .. } => write!(f, concat!("Lut1D::", stringify!($variant), " (", $bits, "-bit)")),
)*
Lut1D::Other { size, .. } => write!(f, "Lut1D::Other (size: {})", size),
}
}
}
impl Lut1D {
pub fn new(size: usize) -> Result<Self> {
if !(2..=65536).contains(&size) {
return Err(CubeError::LutSizeOutOfRange {
size,
min: 2,
max: 65536,
});
}
Ok(match size {
$(
$size => {
let data: Box<[Rgb; $size]> = Box::new([[0.0, 0.0, 0.0]; $size]);
Lut1D::$variant { data }
}
)*
_ => {
let data = vec![[0.0, 0.0, 0.0]; size];
Lut1D::Other { size, data }
}
})
}
pub fn size(&self) -> usize {
match self {
$(
Lut1D::$variant { .. } => $size,
)*
Lut1D::Other { size, .. } => *size,
}
}
#[inline]
pub fn as_slice(&self) -> &[Rgb] {
match self {
$(
Lut1D::$variant { data } => &**data,
)*
Lut1D::Other { data, .. } => data.as_slice(),
}
}
#[inline]
pub fn as_slice_mut(&mut self) -> &mut [Rgb] {
match self {
$(
Lut1D::$variant { data } => &mut **data,
)*
Lut1D::Other { data, .. } => data.as_mut_slice(),
}
}
pub fn get(&self, index: usize, channel: usize) -> Result<f32> {
if channel > 2 {
return Err(CubeError::IndexOutOfBounds {
index: channel,
len: 3,
});
}
let size = self.size();
if index >= size {
return Err(CubeError::IndexOutOfBounds { index, len: size });
}
Ok(self.as_slice()[index][channel])
}
#[inline]
pub unsafe fn get_unchecked(&self, index: usize, channel: usize) -> f32 {
let data = self.as_slice();
(*data.get_unchecked(index))[channel]
}
pub fn set(&mut self, index: usize, channel: usize, value: f32) -> Result<()> {
if channel > 2 {
return Err(CubeError::IndexOutOfBounds {
index: channel,
len: 3,
});
}
let size = self.size();
if index >= size {
return Err(CubeError::IndexOutOfBounds { index, len: size });
}
let data = self.as_slice_mut();
data[index][channel] = value;
Ok(())
}
pub fn get_rgb(&self, index: usize) -> Result<Rgb> {
let size = self.size();
if index >= size {
return Err(CubeError::IndexOutOfBounds { index, len: size });
}
Ok(self.as_slice()[index])
}
#[inline]
pub unsafe fn get_rgb_unchecked(&self, index: usize) -> Rgb {
let data = self.as_slice();
*data.get_unchecked(index)
}
pub fn set_rgb(&mut self, index: usize, rgb: Rgb) -> Result<()> {
let size = self.size();
if index >= size {
return Err(CubeError::IndexOutOfBounds { index, len: size });
}
let data = self.as_slice_mut();
data[index] = rgb;
Ok(())
}
}
};
}
generate_lut1d_variants!(
Bit10, 1024, "10-bit", Bit12, 4096, "12-bit", Bit14, 16384, "14-bit", Bit16, 65536, "16-bit"
);