use crate::error::OutOfBounds;
use crate::index::{IndexList, UniqueIndexList};
use crate::{BoundedParAccess, Bounds, LinearParAccess, RecordIndex};
use paradis_core::ParAccess;
use std::any::type_name;
#[derive(Debug)]
pub struct NarrowedAccess<'a, Indices, Access> {
indices: &'a Indices,
access: Access,
verified_in_bounds: bool,
}
impl<'a, Indices, Access> NarrowedAccess<'a, Indices, Access>
where
Indices: IndexList,
Indices::Index: RecordIndex,
Access: BoundedParAccess<Indices::Index>,
{
pub(crate) fn try_new(indices: &'a Indices, access: Access) -> Result<Self, OutOfBounds> {
if let Some(index_bounds) = indices.bounds() {
if access.bounds().contains_bounds(&index_bounds) {
Ok(Self {
indices,
access,
verified_in_bounds: true,
})
} else {
Err(OutOfBounds)
}
} else {
assert!(
!Indices::ALWAYS_BOUNDED,
"IndexList {} claims that it is ALWAYS_BOUNDED, but no bounds were returned",
type_name::<Indices>()
);
Ok(Self {
indices,
access,
verified_in_bounds: false,
})
}
}
}
unsafe impl<'a, Indices, Access> ParAccess<usize> for NarrowedAccess<'a, Indices, Access>
where
Indices: UniqueIndexList,
Indices::Index: RecordIndex,
Access: BoundedParAccess<Indices::Index>,
{
type Record = Access::Record;
#[inline(always)]
unsafe fn clone_access(&self) -> Self {
Self {
indices: self.indices,
access: unsafe { self.access.clone_access() },
verified_in_bounds: self.verified_in_bounds,
}
}
#[inline(always)]
unsafe fn get_unsync_unchecked(&self, loc: usize) -> Self::Record {
let index = unsafe { self.indices.get_index_unchecked(loc) };
if Indices::ALWAYS_BOUNDED {
debug_assert!(self.verified_in_bounds);
unsafe { self.access.get_unsync_unchecked(index) }
} else if self.verified_in_bounds {
unsafe { self.access.get_unsync_unchecked(index) }
} else {
unsafe { self.access.get_unsync(index) }
}
}
}
unsafe impl<'a, Indices, Access> BoundedParAccess<usize> for NarrowedAccess<'a, Indices, Access>
where
Indices: UniqueIndexList,
Indices::Index: RecordIndex,
Access: BoundedParAccess<Indices::Index>,
{
fn bounds(&self) -> Bounds<usize> {
Bounds {
offset: 0,
extent: self.indices.num_indices(),
}
}
}
unsafe impl<'a, Indices, Access> LinearParAccess for NarrowedAccess<'a, Indices, Access>
where
Indices: UniqueIndexList,
Indices::Index: RecordIndex,
Access: BoundedParAccess<Indices::Index>,
{
#[inline(always)]
fn collection_len(&self) -> usize {
self.indices.num_indices()
}
}