use crate::{extensions::U2, graphics::switch_red_and_blue, prelude::Buffer};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "c_compatible", repr(C))]
pub struct CopyableList<T, const N: usize>
where
T: Copy,
{
pub data: [T; N],
}
impl<T, const N: usize> Default for CopyableList<T, N>
where
T: Copy + Default,
{
fn default() -> Self {
Self::new()
}
}
impl<T, const N: usize> CopyableList<T, N>
where
T: Copy + Default,
{
#[must_use]
pub fn new() -> Self {
Self {
data: [T::default(); N],
}
}
#[must_use]
pub const fn from_array(data: [T; N]) -> Self {
Self {
data,
}
}
#[must_use]
pub fn get(&self, index: usize) -> Option<&T> {
self.data.get(index)
}
pub const fn set(
&mut self,
index: usize,
value: T,
) -> Result<(), &'static str> {
if core::intrinsics::likely(index < N) {
self.data[index] = value;
Ok(())
} else {
Err("Index out of bounds")
}
}
pub const fn len(&self) -> usize {
N
}
pub const fn is_empty(&self) -> bool {
N == 0
}
pub const fn as_slice(&self) -> &[T] {
&self.data
}
}
#[allow(type_alias_bounds)]
pub type List1K<T: Copy> = CopyableList<T, 1024>;
#[allow(type_alias_bounds)]
pub type List4K<T: Copy> = CopyableList<T, 4096>;
#[allow(type_alias_bounds)]
pub type List16K<T: Copy> = CopyableList<T, 16384>;
#[allow(type_alias_bounds)]
pub type List64K<T: Copy> = CopyableList<T, 65536>;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "c_compatible", repr(C))]
pub enum VariableSizeList<T>
where
T: Copy,
{
Image32(List1K<T>),
Image64(List4K<T>),
Image128(List16K<T>),
Image256(List64K<T>),
}
#[must_use]
pub fn u2_to_size_list<T: Copy + core::default::Default>(
size: U2,
) -> VariableSizeList<T> {
match size {
U2 {
b0: false,
b1: false,
} => VariableSizeList::Image32(List1K::new()),
U2 {
b0: true,
b1: false,
} => VariableSizeList::Image64(List4K::new()),
U2 {
b0: false,
b1: true,
} => VariableSizeList::Image128(List16K::new()),
U2 {
b0: true,
b1: true,
} => VariableSizeList::Image256(List64K::new()),
}
}
impl<T> VariableSizeList<T>
where
T: Copy + Default,
{
#[must_use]
pub fn new_32() -> Self {
Self::Image32(List1K::new())
}
#[must_use]
pub fn new_64() -> Self {
Self::Image64(List4K::new())
}
#[must_use]
pub fn new_128() -> Self {
Self::Image128(List16K::new())
}
#[must_use]
pub fn new_256() -> Self {
Self::Image256(List64K::new())
}
#[must_use]
pub const fn len(&self) -> usize {
match self {
Self::Image32(list) => list.len(),
Self::Image64(list) => list.len(),
Self::Image128(list) => list.len(),
Self::Image256(list) => list.len(),
}
}
#[must_use]
pub const fn is_empty(&self) -> bool {
match self {
Self::Image32(list) => list.is_empty(),
Self::Image64(list) => list.is_empty(),
Self::Image128(list) => list.is_empty(),
Self::Image256(list) => list.is_empty(),
}
}
#[must_use]
pub fn get(&self, index: usize) -> Option<&T> {
match self {
Self::Image32(list) => list.get(index),
Self::Image64(list) => list.get(index),
Self::Image128(list) => list.get(index),
Self::Image256(list) => list.get(index),
}
}
pub const fn set(
&mut self,
index: usize,
value: T,
) -> Result<(), &'static str> {
match self {
Self::Image32(list) => list.set(index, value),
Self::Image64(list) => list.set(index, value),
Self::Image128(list) => list.set(index, value),
Self::Image256(list) => list.set(index, value),
}
}
}
fn copy_list_to_buffer<const N: usize>(
list: &CopyableList<u32, N>,
width: usize,
height: usize,
) -> Buffer {
let mut buffer = Buffer::new_empty((width, height));
buffer.data = list.data.to_vec();
buffer
}
pub fn fill(
from: &Buffer,
to: Box<VariableSizeList<u32>>,
) -> Result<Box<VariableSizeList<u32>>, &'static str> {
let mut list = to;
for idx in 0..from.total_size {
list.set(idx, from.data[idx])?;
}
Ok(list)
}
impl<const N: usize> From<CopyableList<u32, N>> for Buffer {
fn from(list: CopyableList<u32, N>) -> Self {
let size = list.len().isqrt();
copy_list_to_buffer(&list, size, size)
}
}
impl<const N: usize> CopyableList<u32, N> {
#[must_use]
pub const fn swap_red_blue(&self) -> Self {
let mut result = *self;
let mut i = 0;
while i < N {
result.data[i] = switch_red_and_blue(result.data[i]);
i += 1;
}
result
}
}