use std::ops::{Index, IndexMut, RangeFrom};
pub(crate) trait BidirectionalStore<T>:
Index<usize, Output = T> + IndexMut<usize, Output = T> + Sized
{
#[allow(unused)]
fn slice_from(&self, range: RangeFrom<usize>) -> &[T];
#[allow(unused)]
fn slice_from_mut(&mut self, range: RangeFrom<usize>) -> &mut [T];
}
pub(crate) struct InPlaceStore<'a, T> {
data: &'a mut [T],
}
impl<T> Index<usize> for InPlaceStore<'_, T> {
type Output = T;
#[inline(always)]
fn index(&self, index: usize) -> &Self::Output {
unsafe { self.data.get_unchecked(index) }
}
}
impl<T> IndexMut<usize> for InPlaceStore<'_, T> {
#[inline(always)]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
unsafe { self.data.get_unchecked_mut(index) }
}
}
impl<T> BidirectionalStore<T> for InPlaceStore<'_, T> {
#[inline(always)]
fn slice_from(&self, range: RangeFrom<usize>) -> &[T] {
unsafe { self.data.get_unchecked(range.start..) }
}
#[inline(always)]
fn slice_from_mut(&mut self, range: RangeFrom<usize>) -> &mut [T] {
unsafe { self.data.get_unchecked_mut(range.start..) }
}
}
impl<'a, T> InPlaceStore<'a, T> {
pub(crate) fn new(data: &'a mut [T]) -> Self {
Self { data }
}
}
pub(crate) struct BiStore<'a, T> {
read: &'a [T],
write: &'a mut [T],
}
impl<T> Index<usize> for BiStore<'_, T> {
type Output = T;
#[inline(always)]
fn index(&self, index: usize) -> &Self::Output {
unsafe { self.read.get_unchecked(index) }
}
}
impl<T> IndexMut<usize> for BiStore<'_, T> {
#[inline(always)]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
unsafe { self.write.get_unchecked_mut(index) }
}
}
impl<T> BidirectionalStore<T> for BiStore<'_, T> {
#[inline(always)]
fn slice_from(&self, range: RangeFrom<usize>) -> &[T] {
unsafe { self.read.get_unchecked(range.start..) }
}
#[inline(always)]
fn slice_from_mut(&mut self, range: RangeFrom<usize>) -> &mut [T] {
unsafe { self.write.get_unchecked_mut(range.start..) }
}
}
impl<'a, T> BiStore<'a, T> {
pub(crate) fn new(read: &'a [T], write: &'a mut [T]) -> Self {
Self { read, write }
}
}