use core::marker::PhantomData;
use crate::{
Field,
type_lists::{
ConsSet,
GetPtr,
SculptPtr,
TupleSet,
},
};
pub struct Lens<'a, T>
where
T: TupleSet,
{
storage: T::ConsPtr,
_phantom: PhantomData<&'a ()>,
}
impl<T> Clone for Lens<'_, T>
where
T: TupleSet,
T::ConsPtr: Clone,
{
#[inline]
fn clone(&self) -> Self {
Self {
storage: self.storage.clone(),
_phantom: PhantomData,
}
}
}
impl<T> Copy for Lens<'_, T>
where
T: TupleSet,
T::ConsPtr: Copy,
{
}
impl<'a, T> Lens<'a, T>
where
T: TupleSet,
{
#[inline]
pub(crate) const fn new(storage: T::ConsPtr) -> Self {
Self {
storage,
_phantom: PhantomData,
}
}
#[expect(clippy::type_complexity, reason = "necessary type inference")]
#[inline]
pub fn split<Lhs, Indices>(
self,
) -> (
Lens<'a, Lhs>,
Lens<'a, <<T::ConsPtr as SculptPtr<Lhs::ConsPtr, Indices>>::Remainder as ConsSet>::Tuple>,
)
where
Lhs: TupleSet,
T::ConsPtr: SculptPtr<Lhs::ConsPtr, Indices>,
<T::ConsPtr as SculptPtr<Lhs::ConsPtr, Indices>>::Remainder: ConsSet<
Tuple: TupleSet<ConsPtr = <T::ConsPtr as SculptPtr<Lhs::ConsPtr, Indices>>::Remainder>,
>,
{
let (lhs_storage, rem_storage) = self.storage.sculpt_ptr();
(
Lens {
storage: lhs_storage,
_phantom: PhantomData,
},
Lens {
storage: rem_storage,
_phantom: PhantomData,
},
)
}
#[inline]
pub fn as_ptr<Elt, Index>(&self) -> *const Elt::Type
where
Elt: Field + 'static,
T::ConsPtr: GetPtr<Elt, Index>,
{
self.storage.get_ptr().as_ptr()
}
#[expect(
clippy::should_implement_trait,
reason = "signature is generic over the field type, not interchangeable with `AsRef`"
)]
#[inline]
#[must_use]
pub fn as_ref<Elt, Index>(&self) -> &'a Elt::Type
where
Elt: Field + 'static,
T::ConsPtr: GetPtr<Elt, Index>,
{
unsafe { &*self.storage.get_ptr().as_ptr() }
}
}