use crate::render::low_memory_pipeline::render_group::ChannelVec;
#[cfg(feature = "allow-unsafe")]
#[inline]
#[allow(unsafe_code)]
pub(super) fn get_distinct_indices<'a, T>(
vals: &'a mut [impl AsMut<[T]>],
idx: &[(usize, usize, usize)],
) -> ChannelVec<&'a mut T> {
let mut answer_buffer: ChannelVec<Option<&'a mut T>> = ChannelVec::new();
for _ in 0..idx.len() {
answer_buffer.push(None);
}
let mut prev_outer = usize::MAX;
let mut prev_inner = usize::MAX;
for &(outer, inner, pos) in idx {
assert!(
prev_outer == usize::MAX
|| outer > prev_outer
|| (outer == prev_outer && inner > prev_inner),
"indices must be sorted and distinct"
);
prev_outer = outer;
prev_inner = inner;
let buf = vals[outer].as_mut();
assert!(inner < buf.len(), "inner index out of bounds");
let ptr = unsafe { buf.as_mut_ptr().add(inner) };
answer_buffer[pos] = Some(unsafe { &mut *ptr });
}
answer_buffer
.into_iter()
.map(|x| x.expect("Not all elements were found"))
.collect()
}
#[cfg(not(feature = "allow-unsafe"))]
#[inline]
pub(super) fn get_distinct_indices<'a, T>(
vals: &'a mut [impl AsMut<[T]>],
idx: &[(usize, usize, usize)],
) -> ChannelVec<&'a mut T> {
let mut answer: ChannelVec<Option<&'a mut T>> = ChannelVec::new();
for _ in 0..idx.len() {
answer.push(None);
}
for (outer_idx, outer_val) in vals.iter_mut().enumerate() {
let mut remaining = outer_val.as_mut();
let mut base = 0usize;
for &(outer, inner, pos) in idx {
if outer != outer_idx {
continue;
}
debug_assert!(inner >= base, "indices must be sorted within each outer");
let (_, rest) = remaining.split_at_mut(inner - base);
let (element, after) = rest.split_first_mut().unwrap();
answer[pos] = Some(element);
remaining = after;
base = inner + 1;
}
}
answer
.into_iter()
.map(|x| x.expect("Not all elements were found"))
.collect()
}