use core::iter::FusedIterator;
use core::marker::PhantomData;
use core::ptr::NonNull;
use crate::access::Access;
use crate::bounds;
use crate::integers::Integer;
use crate::iter;
use crate::reg::{Reg, RegMapPtr};
#[cfg(doc)]
use crate::RegMap;
pub struct RegArray<'a, P: ArrayElem<'a>, const N: usize> {
ptr: NonNull<[P::Target; N]>,
_ref: PhantomData<&'a [P::Target; N]>,
}
impl<'a, P: ArrayElem<'a>, const N: usize> RegArray<'a, P, N> {
#[doc(hidden)]
#[allow(non_snake_case)]
#[inline]
pub const unsafe fn __MACRO_ONLY__from_ptr(ptr: *mut [P::Target; N]) -> Self {
Self::from_nonnull(NonNull::new_unchecked(ptr))
}
#[inline]
const unsafe fn from_nonnull(ptr: NonNull<[P::Target; N]>) -> Self {
Self {
ptr,
_ref: PhantomData,
}
}
#[inline]
pub const fn as_ptr(&self) -> *mut [P::Target; N] {
self.ptr.as_ptr()
}
#[allow(clippy::len_without_is_empty)]
#[inline]
pub const fn len(&self) -> usize {
N
}
#[inline]
pub fn idx(&self, index: usize) -> P {
bounds::check_index::<N>(index);
unsafe { self.idx_unchecked(index) }
}
#[inline]
pub unsafe fn idx_unchecked(&self, index: usize) -> P {
let base: NonNull<P::Target> = self.ptr.cast();
unsafe { P::from_nonnull(base.add(index)) }
}
pub fn iter(
&self,
) -> impl 'a + ExactSizeIterator<Item = P> + DoubleEndedIterator + FusedIterator + Clone {
iter::RegArrayIter::new(self.ptr)
}
pub fn iter_slice(
&self,
start: usize,
end: usize,
) -> impl 'a + ExactSizeIterator<Item = P> + DoubleEndedIterator + FusedIterator + Clone {
bounds::check_slice::<N>(start, end);
let base: NonNull<P::Target> = self.ptr.cast();
unsafe {
let slice = NonNull::slice_from_raw_parts(base.add(start), end - start);
iter::RegArrayIter::new(slice)
}
}
}
pub trait ArrayElem<'a>: 'a + private::Sealed {
type Target;
unsafe fn from_nonnull(ptr: NonNull<Self::Target>) -> Self;
}
impl<'a, T: Integer, A: Access> ArrayElem<'a> for Reg<'a, T, A> {
type Target = T;
unsafe fn from_nonnull(ptr: NonNull<Self::Target>) -> Self {
Reg::from_nonnull(ptr)
}
}
impl<'a, T: RegMapPtr<'a>> ArrayElem<'a> for T {
type Target = T::RegMap;
unsafe fn from_nonnull(ptr: NonNull<Self::Target>) -> Self {
T::from_nonnull(ptr)
}
}
impl<'a, T: ArrayElem<'a>, const N: usize> ArrayElem<'a> for RegArray<'a, T, N> {
type Target = [T::Target; N];
unsafe fn from_nonnull(ptr: NonNull<Self::Target>) -> Self {
RegArray::from_nonnull(ptr)
}
}
mod private {
use crate::access::Access;
use crate::arr::{ArrayElem, RegArray};
use crate::integers::Integer;
use crate::reg::{Reg, RegMapPtr};
pub trait Sealed {}
impl<'a, T: Integer, A: Access> Sealed for Reg<'a, T, A> {}
impl<'a, T: RegMapPtr<'a>> Sealed for T {}
impl<'a, T: ArrayElem<'a>, const N: usize> Sealed for RegArray<'a, T, N> {}
}