use core::marker::PhantomData;
use crate::{
Field,
lens::Lens,
lenses::LensesSlice,
type_lists::{
Concat,
ConsSet,
ConsSliceToConsPtr,
GetPtr,
GetStride,
SculptSlice,
TupleSet,
},
};
#[derive(Debug)]
pub struct LensSlice<'a, T>
where
T: TupleSet,
{
storage: T::ConsSlice,
len: usize,
_phantom: PhantomData<&'a ()>,
}
impl<'a, T> LensesSlice<'a, T> for LensSlice<'a, T>
where
T: TupleSet,
{
#[inline]
fn lens_slice(self) -> Self {
self
}
}
impl<T> Clone for LensSlice<'_, T>
where
T: TupleSet,
T::ConsSlice: Clone,
{
#[inline]
fn clone(&self) -> Self {
Self {
storage: self.storage.clone(),
len: self.len,
_phantom: PhantomData,
}
}
}
impl<T> Copy for LensSlice<'_, T>
where
T: TupleSet,
T::ConsSlice: Copy,
{
}
impl<'a, T> LensSlice<'a, T>
where
T: TupleSet,
{
#[inline]
#[must_use]
pub(crate) const fn new(storage: T::ConsSlice, len: usize) -> Self {
Self {
storage,
len,
_phantom: PhantomData,
}
}
#[expect(clippy::type_complexity, reason = "necessary type inference")]
#[inline]
#[must_use]
pub fn split<Lhs, Indices>(
self,
) -> (
LensSlice<'a, Lhs>,
LensSlice<
'a,
<<T::ConsSlice as SculptSlice<Lhs::ConsSlice, Indices>>::Remainder as ConsSet>::Tuple,
>,
)
where
Lhs: TupleSet,
T::ConsSlice: SculptSlice<Lhs::ConsSlice, Indices>,
<T::ConsSlice as SculptSlice<Lhs::ConsSlice, Indices>>::Remainder: ConsSet<
Tuple: TupleSet<
ConsSlice = <T::ConsSlice as SculptSlice<Lhs::ConsSlice, Indices>>::Remainder,
>,
>,
{
let (lhs_storage, rem_storage) = self.storage.sculpt_slice();
(
LensSlice {
storage: lhs_storage,
len: self.len,
_phantom: PhantomData,
},
LensSlice {
storage: rem_storage,
len: self.len,
_phantom: PhantomData,
},
)
}
#[expect(clippy::type_complexity, reason = "necessary type inference")]
#[inline]
#[must_use]
pub fn join<Rhs>(
self,
other: LensSlice<'a, Rhs>,
) -> Option<
LensSlice<
'a,
<<T::ConsSlice as Concat<T::ConsSlice, Rhs::ConsSlice>>::Result as ConsSet>::Tuple,
>,
>
where
Rhs: TupleSet,
T::ConsSlice: Concat<T::ConsSlice, Rhs::ConsSlice>,
<T::ConsSlice as Concat<T::ConsSlice, Rhs::ConsSlice>>::Result: ConsSet<
Tuple: TupleSet<
ConsSlice = <T::ConsSlice as Concat<T::ConsSlice, Rhs::ConsSlice>>::Result,
>,
>,
{
if other.len >= self.len {
Some(unsafe { self.join_unchecked(other) })
} else {
None
}
}
#[expect(clippy::type_complexity, reason = "necessary type inference")]
#[inline]
#[must_use]
pub unsafe fn join_unchecked<Rhs>(
self,
other: LensSlice<'a, Rhs>,
) -> LensSlice<
'a,
<<T::ConsSlice as Concat<T::ConsSlice, Rhs::ConsSlice>>::Result as ConsSet>::Tuple,
>
where
Rhs: TupleSet,
T::ConsSlice: Concat<T::ConsSlice, Rhs::ConsSlice>,
<T::ConsSlice as Concat<T::ConsSlice, Rhs::ConsSlice>>::Result: ConsSet<
Tuple: TupleSet<
ConsSlice = <T::ConsSlice as Concat<T::ConsSlice, Rhs::ConsSlice>>::Result,
>,
>,
{
LensSlice {
storage: self.storage.concat(other.storage),
len: self.len,
_phantom: PhantomData,
}
}
#[inline]
#[must_use]
pub fn as_ptr<Elt, Index>(&self) -> *const Elt::Type
where
Elt: Field,
T::ConsSlice: GetPtr<Elt, Index>,
{
self.storage.get_ptr().as_ptr()
}
#[inline]
#[must_use]
pub fn get<Elt, Index>(&self, i: usize) -> Option<&'a Elt::Type>
where
Elt: Field,
T::ConsSlice: GetPtr<Elt, Index> + GetStride<Elt, Index>,
{
if i < self.len {
Some(unsafe { self.get_unchecked(i) })
} else {
None
}
}
#[inline]
#[must_use]
pub unsafe fn get_unchecked<Elt, Index>(&self, i: usize) -> &'a Elt::Type
where
Elt: Field,
T::ConsSlice: GetPtr<Elt, Index> + GetStride<Elt, Index>,
{
let base: *const Elt::Type = self.storage.get_ptr().as_ptr();
let stride = self.storage.get_stride();
unsafe { &*base.byte_add(stride * i) }
}
#[inline]
#[must_use]
pub fn get_all(&self, i: usize) -> Option<Lens<'a, T>>
where
T::ConsSlice: ConsSliceToConsPtr<Result = T::ConsPtr>,
{
if i < self.len {
Some(unsafe { self.get_all_unchecked(i) })
} else {
None
}
}
#[inline]
#[must_use]
pub unsafe fn get_all_unchecked(&self, i: usize) -> Lens<'a, T>
where
T::ConsSlice: ConsSliceToConsPtr<Result = T::ConsPtr>,
{
Lens::new(unsafe { self.storage.to_cons_ptr(i) })
}
#[inline]
#[must_use]
pub const fn len(&self) -> usize {
self.len
}
#[inline]
#[must_use]
pub fn stride<Elt, Index>(&self) -> usize
where
Elt: Field,
T::ConsSlice: GetStride<Elt, Index>,
{
self.storage.get_stride()
}
#[inline]
#[must_use]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
}
impl<'a, T> IntoIterator for LensSlice<'a, T>
where
T: TupleSet,
T::ConsSlice: ConsSliceToConsPtr<Result = T::ConsPtr>,
{
type Item = <LensSliceIter<'a, T> as Iterator>::Item;
type IntoIter = LensSliceIter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
LensSliceIter {
lens_slice: self,
offset: 0,
}
}
}
pub struct LensSliceIter<'a, T>
where
T: TupleSet,
{
lens_slice: LensSlice<'a, T>,
offset: usize,
}
impl<'a, T> Iterator for LensSliceIter<'a, T>
where
T: TupleSet,
T::ConsSlice: ConsSliceToConsPtr<Result = T::ConsPtr>,
{
type Item = Lens<'a, T>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let offset = self.offset;
self.offset += 1;
self.lens_slice.get_all(offset)
}
}