use crate::follow::Follow;
use crate::vector::VectorIter;
use crate::EndianScalar;
use core::fmt::{Debug, Formatter, Result};
use core::marker::PhantomData;
use core::mem::size_of;
#[derive(Copy, Clone)]
pub struct Array<'a, T: 'a, const N: usize>(&'a [u8], PhantomData<T>);
impl<'a, T: 'a, const N: usize> Debug for Array<'a, T, N>
where
T: 'a + Follow<'a>,
<T as Follow<'a>>::Inner: Debug,
{
fn fmt(&self, f: &mut Formatter) -> Result {
f.debug_list().entries(self.iter()).finish()
}
}
#[allow(clippy::len_without_is_empty)]
#[allow(clippy::from_over_into)] impl<'a, T: 'a, const N: usize> Array<'a, T, N> {
#[inline(always)]
pub unsafe fn new(buf: &'a [u8]) -> Self {
assert_eq!(size_of::<T>() * N, buf.len());
Array(buf, PhantomData)
}
#[inline(always)]
pub const fn len(&self) -> usize {
N
}
pub fn as_ptr(&self) -> *const u8 {
self.0.as_ptr()
}
}
impl<'a, T: Follow<'a> + 'a, const N: usize> Array<'a, T, N> {
#[inline(always)]
pub fn get(&self, idx: usize) -> T::Inner {
assert!(idx < N);
let sz = size_of::<T>();
unsafe { T::follow(self.0, sz * idx) }
}
#[inline(always)]
pub fn iter(&self) -> VectorIter<'a, T> {
unsafe { VectorIter::from_slice(self.0, self.len()) }
}
}
impl<'a, T: Follow<'a> + Debug, const N: usize> From<Array<'a, T, N>> for [T::Inner; N] {
fn from(array: Array<'a, T, N>) -> Self {
array_init(|i| array.get(i))
}
}
impl<'a, T: Follow<'a> + 'a, const N: usize> Follow<'a> for Array<'a, T, N> {
type Inner = Array<'a, T, N>;
#[inline(always)]
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Array::new(&buf[loc..loc + N * size_of::<T>()])
}
}
pub unsafe fn emplace_scalar_array<T: EndianScalar, const N: usize>(
buf: &mut [u8],
loc: usize,
src: &[T; N],
) {
let mut buf_ptr = buf[loc..].as_mut_ptr();
for item in src.iter() {
let item_le = item.to_little_endian();
core::ptr::copy_nonoverlapping(
&item_le as *const T::Scalar as *const u8,
buf_ptr,
size_of::<T::Scalar>(),
);
buf_ptr = buf_ptr.add(size_of::<T::Scalar>());
}
}
impl<'a, T: Follow<'a> + 'a, const N: usize> IntoIterator for Array<'a, T, N> {
type Item = T::Inner;
type IntoIter = VectorIter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[inline]
pub fn array_init<F, T, const N: usize>(mut initializer: F) -> [T; N]
where
F: FnMut(usize) -> T,
{
let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit();
let mut ptr_i = array.as_mut_ptr() as *mut T;
unsafe {
for i in 0..N {
let value_i = initializer(i);
ptr_i.write(value_i);
ptr_i = ptr_i.add(1);
}
array.assume_init()
}
}
#[cfg(feature = "serialize")]
impl<'a, T: 'a, const N: usize> serde::ser::Serialize for Array<'a, T, N>
where
T: 'a + Follow<'a>,
<T as Follow<'a>>::Inner: serde::ser::Serialize,
{
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
use serde::ser::SerializeSeq;
let mut seq = serializer.serialize_seq(Some(self.len()))?;
for element in self.iter() {
seq.serialize_element(&element)?;
}
seq.end()
}
}