use super::slice::RawJaggedSlice;
use crate::implementations::jagged_arrays::{
AsRawSlice, Slices, as_slice::AsSlice, index::JaggedIndex, indexer::JaggedIndexer,
};
use core::{cmp::Ordering, marker::PhantomData};
use orx_pseudo_default::PseudoDefault;
pub struct RawJaggedRef<'a, T, S, X>
where
T: 'a,
X: JaggedIndexer,
S: Slices<'a, T>,
{
arrays: S,
len: usize,
indexer: X,
phantom: PhantomData<&'a T>,
}
impl<'a, T, S, X> Default for RawJaggedRef<'a, T, S, X>
where
X: JaggedIndexer,
S: Slices<'a, T>,
{
fn default() -> Self {
Self {
arrays: S::empty(),
len: Default::default(),
indexer: PseudoDefault::pseudo_default(),
phantom: Default::default(),
}
}
}
impl<'a, T, S, X> Clone for RawJaggedRef<'a, T, S, X>
where
X: JaggedIndexer,
S: Slices<'a, T>,
{
fn clone(&self) -> Self {
Self {
arrays: self.arrays.clone(),
len: self.len,
indexer: self.indexer.clone(),
phantom: PhantomData,
}
}
}
impl<'a, T, S, X> RawJaggedRef<'a, T, S, X>
where
X: JaggedIndexer,
S: Slices<'a, T>,
{
pub fn new(arrays: S, indexer: X, total_len: Option<usize>) -> Self {
let len = total_len.unwrap_or_else(|| arrays.lengths().sum());
Self {
arrays,
len,
indexer,
phantom: PhantomData,
}
}
pub(super) fn len(&self) -> usize {
self.len
}
pub(super) fn num_slices(&self) -> usize {
self.arrays.num_slices()
}
pub(super) fn len_of(&self, f: usize) -> Option<usize> {
self.arrays.slice_at(f).map(|x| x.as_slice().len())
}
pub(super) fn jagged_index(&self, flat_index: usize) -> Option<JaggedIndex> {
match flat_index.cmp(&self.len) {
Ordering::Less => Some(unsafe {
self.indexer
.jagged_index_unchecked(&self.arrays, flat_index)
}),
Ordering::Equal => match self.arrays.num_slices() == 0 {
true => None,
false => {
let f = self.arrays.num_slices() - 1;
let i = unsafe { self.arrays.slice_at_unchecked(f) }.length();
Some(JaggedIndex::new(f, i))
}
},
Ordering::Greater => None,
}
}
pub(super) fn slice(&self, f: usize, begin_within_slice: usize, len: usize) -> Option<&'a [T]> {
self.arrays.slice_at(f).and_then(|array| {
let array = array.as_slice();
(begin_within_slice < array.len()).then(|| {
let ptr = unsafe { array.as_ptr().add(begin_within_slice) };
unsafe { core::slice::from_raw_parts(ptr, len) }
})
})
}
pub(super) fn jagged_slice(
&self,
flat_begin: usize,
flat_end: usize,
) -> RawJaggedSlice<'a, T, S, X> {
match flat_end.saturating_sub(flat_begin) {
0 => Default::default(),
len => {
let [begin, end] = [flat_begin, flat_end].map(|i| self.jagged_index(i));
match (begin, end) {
(Some(begin), Some(end)) => RawJaggedSlice::new(self.clone(), begin, end, len),
_ => Default::default(),
}
}
}
}
pub(super) fn get(&self, flat_index: usize) -> Option<&'a T> {
self.jagged_index(flat_index).map(|x| {
unsafe { self.arrays.slice_at_unchecked(x.f).get_unchecked(x.i) }
})
}
}