mod clumped_offsets;
mod offsets;
#[cfg(feature = "rayon")]
mod par_iter;
#[cfg(feature = "sorted_chunks")]
mod sorted_chunks;
#[cfg(feature = "sparse")]
mod sparse;
mod uniform;
use super::*;
pub use clumped_offsets::*;
pub use offsets::*;
#[cfg(feature = "sorted_chunks")]
pub use sorted_chunks::*;
use std::convert::AsRef;
pub use uniform::*;
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Chunked<S, O = Offsets> {
pub chunks: O,
pub data: S,
}
pub type ChunkedView<'a, S> = Chunked<S, Offsets<&'a [usize]>>;
pub trait SplitOffsetsAt
where
Self: Sized,
{
fn split_offsets_with_intersection_at(self, mid: usize) -> (Self, Self, usize);
fn split_offsets_at(self, mid: usize) -> (Self, Self);
}
pub trait IndexRange {
unsafe fn index_range_unchecked(&self, range: std::ops::Range<usize>)
-> std::ops::Range<usize>;
fn index_range(&self, range: std::ops::Range<usize>) -> Option<std::ops::Range<usize>>;
}
pub trait IntoRanges {
type Iter: Iterator<Item = std::ops::Range<usize>>;
fn into_ranges(self) -> Self::Iter;
}
pub trait IntoSizes {
type Iter: Iterator<Item = usize>;
fn into_sizes(self) -> Self::Iter;
}
pub trait IntoOffsetValuesAndSizes {
type Iter: Iterator<Item = (usize, usize)>;
fn into_offset_values_and_sizes(self) -> Self::Iter;
}
#[cfg(feature = "rayon")]
pub trait IntoParOffsetValuesAndSizes {
type ParIter: rayon::iter::IndexedParallelIterator<Item = (usize, usize)>;
fn into_par_offset_values_and_sizes(self) -> Self::ParIter;
}
pub trait IntoValues {
type Iter: Iterator<Item = usize>;
fn into_values(self) -> Self::Iter;
}
pub unsafe trait GetOffset {
unsafe fn offset_value_unchecked(&self, index: usize) -> usize;
fn num_offsets(&self) -> usize;
#[inline]
fn chunk_len(&self, chunk_index: usize) -> usize {
assert!(
chunk_index + 1 < self.num_offsets(),
"Offset index out of bounds"
);
unsafe { self.chunk_len_unchecked(chunk_index) }
}
#[inline]
unsafe fn chunk_len_unchecked(&self, chunk_index: usize) -> usize {
self.offset_value_unchecked(chunk_index + 1) - self.offset_value_unchecked(chunk_index)
}
#[inline]
fn offset_value(&self, index: usize) -> usize {
assert!(index < self.num_offsets(), "Offset index out of bounds");
unsafe { self.offset_value_unchecked(index) }
}
#[inline]
fn offset(&self, index: usize) -> usize {
self.offset_value(index) - self.first_offset_value()
}
#[inline]
unsafe fn offset_unchecked(&self, index: usize) -> usize {
self.offset_value_unchecked(index) - self.first_offset_value()
}
#[inline]
fn last_offset(&self) -> usize {
unsafe { self.offset_unchecked(self.num_offsets() - 1) }
}
#[inline]
fn first_offset(&self) -> usize {
0
}
#[inline]
fn last_offset_value(&self) -> usize {
unsafe { self.offset_value_unchecked(self.num_offsets() - 1) }
}
#[inline]
fn first_offset_value(&self) -> usize {
unsafe { self.offset_value_unchecked(0) }
}
}
pub trait BinarySearch<T> {
fn binary_search(&self, x: &T) -> Result<usize, usize>;
}
pub type Clumped<S, O = Vec<usize>> = Chunked<S, ClumpedOffsets<O>>;
pub type ClumpedView<'a, S> = Clumped<S, &'a [usize]>;
impl<S, O> Chunked<S, O> {
pub fn data(&self) -> &S {
&self.data
}
pub fn data_mut(&mut self) -> &mut S {
&mut self.data
}
}
impl<S: Set> Chunked<S> {
pub fn from_sizes(sizes: impl AsRef<[usize]>, data: S) -> Self {
Self::from_sizes_impl(sizes.as_ref(), data)
}
#[inline]
fn from_sizes_impl(sizes: &[usize], data: S) -> Self {
assert_eq!(sizes.iter().sum::<usize>(), data.len());
let mut offsets = Vec::with_capacity(sizes.len() + 1);
offsets.push(0);
offsets.extend(sizes.iter().scan(0, |prev_off, &x| {
*prev_off += x;
Some(*prev_off)
}));
Chunked {
chunks: offsets.into(),
data,
}
}
}
impl<S: Set> Clumped<S> {
pub fn from_sizes_and_counts(
sizes: impl AsRef<[usize]>,
counts: impl AsRef<[usize]>,
data: S,
) -> Self {
Self::from_sizes_and_counts_impl(sizes.as_ref(), counts.as_ref(), data)
}
#[inline]
fn from_sizes_and_counts_impl(sizes: &[usize], counts: &[usize], data: S) -> Self {
assert_eq!(sizes.len(), counts.len());
assert_eq!(
sizes
.iter()
.zip(counts.iter())
.map(|(s, c)| s * c)
.sum::<usize>(),
data.len()
);
let mut clump_offsets = Vec::with_capacity(sizes.len() + 1);
let mut offsets = Vec::with_capacity(sizes.len() + 1);
clump_offsets.push(0);
offsets.push(0);
let mut prev_off = 0;
let mut prev_clump_off = 0;
for (s, c) in sizes.iter().zip(counts.iter()) {
prev_clump_off += c;
prev_off += s * c;
offsets.push(prev_off);
clump_offsets.push(prev_clump_off);
}
Chunked {
chunks: ClumpedOffsets::new(clump_offsets, offsets),
data,
}
}
}
impl<S: Set, O: AsRef<[usize]>> Chunked<S, Offsets<O>> {
#[inline]
pub fn from_offsets(offsets: O, data: S) -> Self {
let offsets_ref = offsets.as_ref();
let last = *offsets_ref.last().expect("offsets must be non empty");
let first = *offsets_ref.first().unwrap();
assert_eq!(
data.len(),
last - first,
"the length of data ({}) must equal the difference between first and last offsets ({})",
data.len(),
last - first
);
Chunked {
chunks: unsafe { Offsets::from_raw(offsets) },
data,
}
}
}
impl<S: Set, O: AsRef<[usize]>> Clumped<S, O> {
#[inline]
pub fn from_clumped_offsets(chunk_offsets: O, offsets: O, data: S) -> Self {
let offsets_ref = offsets.as_ref();
let last = *offsets_ref.last().expect("offsets must be non empty");
let first = *offsets_ref.first().unwrap();
assert_eq!(
data.len(),
last - first,
"the length of data ({}) must equal the difference between first and last offsets ({})",
data.len(),
last - first,
);
let chunk_offsets_ref = chunk_offsets.as_ref();
assert_eq!(
chunk_offsets_ref.len(),
offsets_ref.len(),
"there must be the same number of offsets as there are chunk offsets"
);
Chunked {
chunks: ClumpedOffsets {
chunk_offsets: Offsets::new(chunk_offsets),
offsets: Offsets::new(offsets),
},
data,
}
}
}
impl<S: Set, O> Chunked<S, O> {
#[inline]
pub fn into_inner(self) -> (O, S) {
let Chunked { chunks, data } = self;
(chunks, data)
}
#[inline]
pub fn as_inner_mut(&mut self) -> (&mut O, &mut S) {
let Chunked { chunks, data } = self;
(chunks, data)
}
}
impl<S, O> Chunked<S, O> {
#[inline]
pub fn offsets(&self) -> &O {
&self.chunks
}
}
impl<S, O> Chunked<S, O>
where
O: GetOffset,
{
#[inline]
pub fn offset(&self, index: usize) -> usize {
self.chunks.offset(index)
}
#[inline]
pub fn offset_value(&self, index: usize) -> usize {
self.chunks.offset_value(index)
}
#[inline]
pub fn chunk_len(&self, chunk_index: usize) -> usize {
self.chunks.chunk_len(chunk_index)
}
}
impl<S, O> Chunked<S, Offsets<O>>
where
O: AsRef<[usize]> + AsMut<[usize]>,
{
#[inline]
pub fn transfer_forward(&mut self, chunk_index: usize, num_elements: usize) {
self.chunks.move_back(chunk_index + 1, num_elements);
}
#[inline]
pub fn transfer_forward_all_but(&mut self, chunk_index: usize, num_elements_to_keep: usize) {
let num_elements_to_transfer = self.chunk_len(chunk_index) - num_elements_to_keep;
self.transfer_forward(chunk_index, num_elements_to_transfer);
}
}
impl<S, O> Chunked<S, Offsets<O>>
where
O: AsRef<[usize]> + AsMut<[usize]>,
S: RemovePrefix,
{
#[inline]
pub fn transfer_backward(&mut self, chunk_index: usize, num_elements: usize) {
self.chunks.move_forward(chunk_index, num_elements);
if chunk_index == 0 {
self.data.remove_prefix(num_elements);
}
}
}
impl<S: Default, O: Default> Chunked<S, O> {
#[inline]
pub fn new() -> Self {
Self::default()
}
}
impl<S> Chunked<S>
where
S: Set + Default + ExtendFromSlice<Item = <S as Set>::Elem>, {
#[inline]
pub fn from_nested_vec(nested_data: Vec<Vec<<S as Set>::Elem>>) -> Self {
nested_data.into_iter().collect()
}
}
impl<S, O> Set for Chunked<S, O>
where
S: Set,
O: GetOffset,
{
type Elem = Vec<S::Elem>;
type Atom = S::Atom;
#[inline]
fn len(&self) -> usize {
self.chunks.num_offsets() - 1
}
}
impl<S, O> Chunked<S, O>
where
S: Truncate + Set,
O: GetOffset,
{
#[inline]
pub fn trim_data(&mut self) -> usize {
debug_assert!(self.chunks.num_offsets() > 0);
let last_offset = self.chunks.last_offset();
let num_removed = self.data.len() - last_offset;
self.data.truncate(last_offset);
debug_assert_eq!(self.data.len(), last_offset);
num_removed
}
}
impl<S, O> Chunked<S, O>
where
S: Truncate + Set,
O: AsRef<[usize]> + GetOffset + Truncate,
{
pub fn trim(&mut self) -> usize {
let num_offsets = self.chunks.num_offsets();
debug_assert!(num_offsets > 0);
let last_offset = self.chunks.last_offset();
let num_empty = self
.chunks
.as_ref()
.iter()
.rev()
.skip(1) .take_while(|&&offset| offset == last_offset)
.count();
self.chunks.truncate(num_offsets - num_empty);
self.trim_data();
num_empty
}
}
impl<S: Truncate, O> Truncate for Chunked<S, O>
where
O: GetOffset,
{
fn truncate(&mut self, new_len: usize) {
self.data
.truncate(self.chunks.last_offset_value() - self.chunks.offset_value(new_len));
}
}
impl<S, O, L> Push<L> for Chunked<S, O>
where
S: Set + ExtendFromSlice<Item = <S as Set>::Elem>,
L: AsRef<[<S as Set>::Elem]>,
O: Push<usize>,
{
#[inline]
fn push(&mut self, element: L) {
self.data.extend_from_slice(element.as_ref());
self.chunks.push(self.data.len());
}
}
impl<S, O> Chunked<S, O>
where
S: Set + ExtendFromSlice<Item = <S as Set>::Elem>,
O: Push<usize>,
{
#[inline]
pub fn push_slice(&mut self, element: &[<S as Set>::Elem]) {
self.data.extend_from_slice(element);
self.chunks.push(self.data.len());
}
}
impl<S, O> Chunked<S, O>
where
S: Set,
O: Push<usize>,
{
#[inline]
pub fn push_iter<I: IntoIterator>(&mut self, iter: I)
where
S: Extend<I::Item>,
{
self.data.extend(iter);
self.chunks.push(self.data.len());
}
}
impl<S, O> Chunked<S, Offsets<O>>
where
S: Set + Extend<<S as Set>::Elem>,
O: AsMut<[usize]>,
{
#[inline]
pub fn extend_last<I: IntoIterator<Item = <S as Set>::Elem>>(&mut self, iter: I) {
let init_len = self.data.len();
self.data.extend(iter);
self.chunks.extend_last(self.data.len() - init_len);
}
}
impl<S, O> IntoOwned for Chunked<S, O>
where
S: IntoOwned,
O: IntoOwned,
{
type Owned = Chunked<S::Owned, O::Owned>;
#[inline]
fn into_owned(self) -> Self::Owned {
Chunked {
chunks: self.chunks.into_owned(),
data: self.data.into_owned(),
}
}
}
impl<S, O> IntoOwnedData for Chunked<S, O>
where
S: IntoOwnedData,
{
type OwnedData = Chunked<S::OwnedData, O>;
#[inline]
fn into_owned_data(self) -> Self::OwnedData {
let Chunked { chunks, data } = self;
Chunked {
chunks,
data: data.into_owned_data(),
}
}
}
impl<'a, S, O> std::iter::FromIterator<&'a [<S as Set>::Elem]> for Chunked<S, O>
where
S: Set + ExtendFromSlice<Item = <S as Set>::Elem> + Default,
<S as Set>::Elem: 'a,
O: Default + Push<usize>,
{
#[inline]
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = &'a [<S as Set>::Elem]>,
{
let mut s = Chunked::default();
for i in iter {
s.push_slice(i);
}
s
}
}
impl<S> std::iter::FromIterator<Vec<<S as Set>::Elem>> for Chunked<S>
where
S: Set + Default + ExtendFromSlice<Item = <S as Set>::Elem>, {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = Vec<<S as Set>::Elem>>,
{
let mut s = Chunked::default();
for i in iter {
s.push(i);
}
s
}
}
impl<'a, S, O> GetIndex<'a, Chunked<S, O>> for usize
where
S: Set + View<'a> + Get<'a, std::ops::Range<usize>, Output = <S as View<'a>>::Type>,
O: IndexRange,
{
type Output = S::Output;
#[inline]
fn get(self, chunked: &Chunked<S, O>) -> Option<Self::Output> {
let Chunked { ref chunks, data } = chunked;
chunks
.index_range(self..self + 1)
.and_then(|index_range| data.get(index_range))
}
}
impl<'a, S, O> GetIndex<'a, Chunked<S, O>> for &usize
where
S: Set + View<'a> + Get<'a, std::ops::Range<usize>, Output = <S as View<'a>>::Type>,
O: IndexRange,
{
type Output = S::Output;
#[inline]
fn get(self, chunked: &Chunked<S, O>) -> Option<Self::Output> {
GetIndex::get(*self, chunked)
}
}
impl<'a, S, O> GetIndex<'a, Chunked<S, O>> for std::ops::Range<usize>
where
S: Set + View<'a> + Get<'a, std::ops::Range<usize>, Output = <S as View<'a>>::Type>,
O: IndexRange + Get<'a, std::ops::Range<usize>>,
{
type Output = Chunked<S::Output, O::Output>;
#[inline]
fn get(self, chunked: &Chunked<S, O>) -> Option<Self::Output> {
assert!(self.start <= self.end);
let Chunked { data, ref chunks } = chunked;
chunks.index_range(self.clone()).and_then(|index_range| {
data.get(index_range).map(|data| Chunked {
chunks: chunks.get(self).unwrap(),
data,
})
})
}
}
impl<S, O> IsolateIndex<Chunked<S, O>> for usize
where
S: Set + Isolate<std::ops::Range<usize>>,
O: IndexRange,
{
type Output = S::Output;
#[inline]
unsafe fn isolate_unchecked(self, chunked: Chunked<S, O>) -> Self::Output {
let Chunked { chunks, data } = chunked;
data.isolate_unchecked(chunks.index_range_unchecked(self..self + 1))
}
#[inline]
fn try_isolate(self, chunked: Chunked<S, O>) -> Option<Self::Output> {
let Chunked { chunks, data } = chunked;
chunks
.index_range(self..self + 1)
.and_then(|index_range| data.try_isolate(index_range))
}
}
impl<S, O> IsolateIndex<Chunked<S, O>> for std::ops::Range<usize>
where
S: Set + Isolate<std::ops::Range<usize>>,
<S as Isolate<std::ops::Range<usize>>>::Output: Set,
O: IndexRange + Isolate<std::ops::Range<usize>>,
{
type Output = Chunked<S::Output, O::Output>;
#[inline]
unsafe fn isolate_unchecked(self, chunked: Chunked<S, O>) -> Self::Output {
debug_assert!(self.start <= self.end);
let Chunked { data, chunks } = chunked;
Chunked {
data: data.isolate_unchecked(chunks.index_range_unchecked(self.clone())),
chunks: chunks.isolate_unchecked(self),
}
}
#[inline]
fn try_isolate(self, chunked: Chunked<S, O>) -> Option<Self::Output> {
assert!(self.start <= self.end);
let Chunked { data, chunks } = chunked;
chunks
.index_range(self.clone())
.and_then(move |index_range| {
data.try_isolate(index_range).map(move |data| Chunked {
chunks: chunks.try_isolate(self).unwrap(),
data,
})
})
}
}
impl<T, O> std::ops::Index<usize> for Chunked<Vec<T>, O>
where
O: std::ops::Index<usize, Output = usize>,
{
type Output = <[T] as std::ops::Index<std::ops::Range<usize>>>::Output;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
&self.data[self.chunks[idx]..self.chunks[idx + 1]]
}
}
impl<T, O> std::ops::Index<usize> for Chunked<&[T], O>
where
O: std::ops::Index<usize, Output = usize>,
{
type Output = <[T] as std::ops::Index<std::ops::Range<usize>>>::Output;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
&self.data[self.chunks[idx]..self.chunks[idx + 1]]
}
}
impl<T, O> std::ops::Index<usize> for Chunked<&mut [T], O>
where
O: std::ops::Index<usize, Output = usize>,
{
type Output = <[T] as std::ops::Index<std::ops::Range<usize>>>::Output;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
&self.data[self.chunks[idx]..self.chunks[idx + 1]]
}
}
impl<T, O> std::ops::IndexMut<usize> for Chunked<Vec<T>, O>
where
O: std::ops::Index<usize, Output = usize>,
{
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
&mut self.data[self.chunks[idx]..self.chunks[idx + 1]]
}
}
impl<T, O> std::ops::IndexMut<usize> for Chunked<&mut [T], O>
where
O: std::ops::Index<usize, Output = usize>,
{
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
&mut self.data[self.chunks[idx]..self.chunks[idx + 1]]
}
}
impl<'a, S, O> IntoIterator for Chunked<S, O>
where
O: IntoOffsetValuesAndSizes + GetOffset,
S: SplitAt + Set + Dummy,
O::Iter: ExactSizeIterator,
{
type Item = S;
type IntoIter = ChunkedIter<O::Iter, S>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
ChunkedIter {
first_offset_value: self.chunks.first_offset_value(),
offset_values_and_sizes: self.chunks.into_offset_values_and_sizes(),
data: self.data,
}
}
}
impl<'a, S, O> ViewIterator<'a> for Chunked<S, O>
where
S: View<'a>,
O: View<'a, Type = Offsets<&'a [usize]>>,
<S as View<'a>>::Type: SplitAt + Set + Dummy,
{
type Item = <S as View<'a>>::Type;
type Iter = ChunkedIter<OffsetValuesAndSizes<'a>, <S as View<'a>>::Type>;
#[inline]
fn view_iter(&'a self) -> Self::Iter {
self.iter()
}
}
impl<'a, S, O> ViewMutIterator<'a> for Chunked<S, O>
where
S: ViewMut<'a>,
O: View<'a, Type = Offsets<&'a [usize]>>,
<S as ViewMut<'a>>::Type: SplitAt + Set + Dummy,
{
type Item = <S as ViewMut<'a>>::Type;
type Iter = ChunkedIter<OffsetValuesAndSizes<'a>, <S as ViewMut<'a>>::Type>;
#[inline]
fn view_mut_iter(&'a mut self) -> Self::Iter {
self.iter_mut()
}
}
impl_atom_iterators_recursive!(impl<S, O> for Chunked<S, O> { data });
impl<'a, S, O> Chunked<S, O>
where
S: View<'a>,
O: View<'a>,
O::Type: IntoOffsetValuesAndSizes + GetOffset,
{
#[inline]
pub fn iter(
&'a self,
) -> ChunkedIter<<<O as View<'a>>::Type as IntoOffsetValuesAndSizes>::Iter, <S as View<'a>>::Type>
{
ChunkedIter {
first_offset_value: self.chunks.view().first_offset_value(),
offset_values_and_sizes: self.chunks.view().into_offset_values_and_sizes(),
data: self.data.view(),
}
}
}
impl<'a, S, O> Chunked<S, O>
where
S: ViewMut<'a>,
O: View<'a>,
O::Type: IntoOffsetValuesAndSizes + GetOffset,
{
#[inline]
pub fn iter_mut(
&'a mut self,
) -> ChunkedIter<
<<O as View<'a>>::Type as IntoOffsetValuesAndSizes>::Iter,
<S as ViewMut<'a>>::Type,
> {
ChunkedIter {
first_offset_value: self.chunks.view().first_offset_value(),
offset_values_and_sizes: self.chunks.view().into_offset_values_and_sizes(),
data: self.data.view_mut(),
}
}
}
impl<S, O> SplitAt for Chunked<S, O>
where
S: SplitAt + Set,
O: SplitOffsetsAt,
{
#[inline]
fn split_at(self, mid: usize) -> (Self, Self) {
let (offsets_l, offsets_r, off) = self.chunks.split_offsets_with_intersection_at(mid);
let (data_l, data_r) = self.data.split_at(off);
(
Chunked {
chunks: offsets_l,
data: data_l,
},
Chunked {
chunks: offsets_r,
data: data_r,
},
)
}
}
pub struct ChunkedIter<I, S> {
first_offset_value: usize,
offset_values_and_sizes: I,
data: S,
}
impl<I, V> Iterator for ChunkedIter<I, V>
where
V: SplitAt + Set + Dummy,
I: ExactSizeIterator<Item = (usize, usize)>,
{
type Item = V;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
unsafe {
let data_slice = std::mem::replace(&mut self.data, Dummy::dummy());
self.offset_values_and_sizes.next().map(move |(_, n)| {
let (l, r) = data_slice.split_at(n);
self.data = r;
self.first_offset_value += n;
l
})
}
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
unsafe {
let data_slice = std::mem::replace(&mut self.data, Dummy::dummy());
self.offset_values_and_sizes.nth(n).map(move |(off, size)| {
let (_, r) = data_slice.split_at(off - self.first_offset_value);
let (l, r) = r.split_at(size);
self.data = r;
self.first_offset_value = off;
l
})
}
}
}
impl<I, V> DoubleEndedIterator for ChunkedIter<I, V>
where
V: SplitAt + Set + Dummy,
I: ExactSizeIterator + DoubleEndedIterator<Item = (usize, usize)>,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
unsafe {
let data_slice = std::mem::replace(&mut self.data, Dummy::dummy());
self.offset_values_and_sizes
.next_back()
.map(move |(off, _)| {
let (l, r) = data_slice.split_at(off - self.first_offset_value);
self.data = l;
self.first_offset_value = off;
r
})
}
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
unsafe {
let data_slice = std::mem::replace(&mut self.data, Dummy::dummy());
self.offset_values_and_sizes
.nth_back(n)
.map(move |(off, size)| {
let (l, r) = data_slice.split_at(off - self.first_offset_value);
let (v, _) = r.split_at(size);
self.data = l;
self.first_offset_value = off;
v
})
}
}
}
impl<I, V> ExactSizeIterator for ChunkedIter<I, V> where Self: Iterator {}
impl<I, V> std::iter::FusedIterator for ChunkedIter<I, V> where Self: Iterator {}
pub struct VarIntoIter<S> {
offsets: std::iter::Peekable<std::vec::IntoIter<usize>>,
data: S,
}
impl<S> Iterator for VarIntoIter<S>
where
S: SplitOff + Set,
{
type Item = S;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let begin = self
.offsets
.next()
.expect("Chunked is corrupted and cannot be iterated.");
if self.offsets.len() <= 1 {
return None; }
let end = *self.offsets.peek().unwrap();
let n = end - begin;
let mut l = self.data.split_off(n);
std::mem::swap(&mut l, &mut self.data);
Some(l) }
}
impl<S: SplitOff + Set> SplitOff for Chunked<S> {
#[inline]
fn split_off(&mut self, mid: usize) -> Self {
assert!(self.chunks.num_offsets() > 0);
assert!(mid < self.chunks.num_offsets());
let off = self.chunks[mid] - self.chunks[0];
let offsets_l = self.chunks[..=mid].to_vec();
let offsets_r = self.chunks[mid..].to_vec();
self.chunks = offsets_l.into();
let data_r = self.data.split_off(off);
Chunked::from_offsets(offsets_r, data_r)
}
}
impl<S> IntoIterator for Chunked<S>
where
S: SplitOff + Set,
{
type Item = S;
type IntoIter = VarIntoIter<S>;
fn into_iter(self) -> Self::IntoIter {
let Chunked { chunks, data } = self;
VarIntoIter {
offsets: chunks.into_inner().into_iter().peekable(),
data,
}
}
}
impl<'a, S, O> View<'a> for Chunked<S, O>
where
S: View<'a>,
O: View<'a>,
{
type Type = Chunked<S::Type, O::Type>;
#[inline]
fn view(&'a self) -> Self::Type {
Chunked {
chunks: self.chunks.view(),
data: self.data.view(),
}
}
}
impl<'a, S, O> ViewMut<'a> for Chunked<S, O>
where
S: ViewMut<'a>,
O: View<'a>,
{
type Type = Chunked<S::Type, O::Type>;
#[inline]
fn view_mut(&'a mut self) -> Self::Type {
Chunked {
chunks: self.chunks.view(),
data: self.data.view_mut(),
}
}
}
impl<S: IntoStorage, O> IntoStorage for Chunked<S, O> {
type StorageType = S::StorageType;
#[inline]
fn into_storage(self) -> Self::StorageType {
self.data.into_storage()
}
}
impl<'a, S: StorageView<'a>, O> StorageView<'a> for Chunked<S, O> {
type StorageView = S::StorageView;
#[inline]
fn storage_view(&'a self) -> Self::StorageView {
self.data.storage_view()
}
}
impl<S: Storage, O> Storage for Chunked<S, O> {
type Storage = S::Storage;
#[inline]
fn storage(&self) -> &Self::Storage {
self.data.storage()
}
}
impl<S: StorageMut, O> StorageMut for Chunked<S, O> {
#[inline]
fn storage_mut(&mut self) -> &mut Self::Storage {
self.data.storage_mut()
}
}
impl<T, S: CloneWithStorage<T>, O: Clone> CloneWithStorage<T> for Chunked<S, O> {
type CloneType = Chunked<S::CloneType, O>;
#[inline]
fn clone_with_storage(&self, storage: T) -> Self::CloneType {
Chunked {
chunks: self.chunks.clone(),
data: self.data.clone_with_storage(storage),
}
}
}
impl<S: Default, O: Default> Default for Chunked<S, O> {
#[inline]
fn default() -> Self {
Chunked {
data: Default::default(),
chunks: Default::default(),
}
}
}
impl<S: Dummy, O: Dummy> Dummy for Chunked<S, O> {
#[inline]
unsafe fn dummy() -> Self {
Chunked {
data: Dummy::dummy(),
chunks: Dummy::dummy(),
}
}
}
impl<S: RemovePrefix, O: RemovePrefix + AsRef<[usize]>> RemovePrefix for Chunked<S, O> {
#[inline]
fn remove_prefix(&mut self, n: usize) {
let chunks = self.chunks.as_ref();
assert!(n < chunks.len());
let offset = *chunks.first().unwrap();
self.chunks.remove_prefix(n);
let data_offset = *self.chunks.as_ref().first().unwrap() - offset;
self.data.remove_prefix(data_offset);
}
}
impl<S: Clear> Clear for Chunked<S> {
#[inline]
fn clear(&mut self) {
self.chunks.clear();
self.chunks.push(0);
self.data.clear();
}
}
impl<S, O, N> SplitPrefix<N> for Chunked<S, O>
where
S: Viewed + Set + SplitAt,
N: Unsigned,
O: GetOffset + SplitOffsetsAt,
{
type Prefix = Chunked<S, O>;
#[inline]
fn split_prefix(self) -> Option<(Self::Prefix, Self)> {
if N::to_usize() > self.len() {
return None;
}
Some(self.split_at(N::to_usize()))
}
}
impl<S, O> SplitFirst for Chunked<S, O>
where
S: Viewed + Set + SplitAt,
O: GetOffset + SplitOffsetsAt,
{
type First = S;
#[inline]
fn split_first(self) -> Option<(Self::First, Self)> {
if self.is_empty() {
return None;
}
let (_, rest_chunks, off) = self.chunks.split_offsets_with_intersection_at(1);
let (first, rest) = self.data.split_at(off);
Some((
first,
Chunked {
data: rest,
chunks: rest_chunks,
},
))
}
}
impl<S, I, N> UniChunkable<N> for Chunked<S, I> {
type Chunk = Chunked<S, I>;
}
impl<S, N> IntoStaticChunkIterator<N> for ChunkedView<'_, S>
where
Self: Set + SplitPrefix<N> + Dummy,
N: Unsigned,
{
type Item = <Self as SplitPrefix<N>>::Prefix;
type IterType = UniChunkedIter<Self, N>;
#[inline]
fn into_static_chunk_iter(self) -> Self::IterType {
self.into_generic_static_chunk_iter()
}
}
impl<S: StorageInto<T>, O, T> StorageInto<T> for Chunked<S, O> {
type Output = Chunked<S::Output, O>;
#[inline]
fn storage_into(self) -> Self::Output {
Chunked {
data: self.data.storage_into(),
chunks: self.chunks,
}
}
}
impl<S: MapStorage<Out>, O, Out> MapStorage<Out> for Chunked<S, O> {
type Input = S::Input;
type Output = Chunked<S::Output, O>;
#[inline]
fn map_storage<F: FnOnce(Self::Input) -> Out>(self, f: F) -> Self::Output {
Chunked {
data: self.data.map_storage(f),
chunks: self.chunks,
}
}
}
impl<S: Reserve, O: Reserve> Reserve for Chunked<S, O> {
#[inline]
fn reserve_with_storage(&mut self, n: usize, storage_n: usize) {
self.chunks.reserve(n);
self.data.reserve_with_storage(n, storage_n);
}
}
impl<S, O: AsRef<[usize]> + Set> From<Chunked<S, Offsets<O>>> for Clumped<S> {
fn from(chunked: Chunked<S, Offsets<O>>) -> Clumped<S> {
let Chunked { chunks, data } = chunked;
Clumped {
chunks: ClumpedOffsets::from(chunks),
data,
}
}
}
impl<S, O: AsRef<[usize]> + Set> From<Clumped<S, O>> for Chunked<S> {
fn from(clumped: Clumped<S, O>) -> Chunked<S> {
let Clumped { chunks, data } = clumped;
Chunked {
chunks: Offsets::from(chunks),
data,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chunked_iter() {
let s = Chunked::from_offsets(vec![0, 3, 5, 6], vec![0, 1, 2, 3, 4, 5]);
let mut iter = s.iter();
assert_eq!(iter.next().unwrap(), &[0, 1, 2]);
assert_eq!(iter.next_back().unwrap(), &[5]);
assert_eq!(iter.next().unwrap(), &[3, 4]);
assert_eq!(iter.next(), None);
assert_eq!(s.len(), 3);
assert_eq!(s.iter().nth(0).unwrap(), &[0, 1, 2]);
assert_eq!(s.iter().nth(1).unwrap(), &[3, 4]);
assert_eq!(s.iter().nth(2).unwrap(), &[5]);
assert_eq!(s.iter().nth(3), None);
assert_eq!(s.iter().nth_back(0).unwrap(), &[5]);
assert_eq!(s.iter().nth_back(1).unwrap(), &[3, 4]);
assert_eq!(s.iter().nth_back(2).unwrap(), &[0, 1, 2]);
assert_eq!(s.iter().nth_back(3), None);
}
#[test]
fn sizes_constructor() {
let empty: Vec<u32> = vec![];
let s = Chunked::from_sizes(vec![], Vec::<u32>::new());
assert_eq!(s.len(), 0);
let s = Chunked::from_sizes(vec![0], Vec::<u32>::new());
assert_eq!(s.len(), 1);
assert_eq!(empty.as_slice(), s.view().at(0));
let s = Chunked::from_sizes(vec![0, 0, 0], vec![]);
assert_eq!(s.len(), 3);
for chunk in s.iter() {
assert_eq!(empty.as_slice(), chunk);
}
}
#[test]
fn zero_length_chunk() {
let empty: Vec<usize> = vec![];
let s = Chunked::from_offsets(vec![0, 0, 3, 4, 6], vec![1, 2, 3, 4, 5, 6]);
let mut iter = s.iter();
assert_eq!(empty.clone(), iter.next().unwrap().to_vec());
assert_eq!(vec![1, 2, 3], iter.next().unwrap().to_vec());
assert_eq!(vec![4], iter.next().unwrap().to_vec());
assert_eq!(vec![5, 6], iter.next().unwrap().to_vec());
assert_eq!(None, iter.next());
let s = Chunked::from_offsets(vec![0, 3, 3, 4, 6], vec![1, 2, 3, 4, 5, 6]);
let mut iter = s.iter();
assert_eq!(vec![1, 2, 3], iter.next().unwrap().to_vec());
assert_eq!(empty.clone(), iter.next().unwrap().to_vec());
assert_eq!(vec![4], iter.next().unwrap().to_vec());
assert_eq!(vec![5, 6], iter.next().unwrap().to_vec());
assert_eq!(None, iter.next());
let s = Chunked::from_offsets(vec![0, 3, 4, 6, 6], vec![1, 2, 3, 4, 5, 6]);
let mut iter = s.iter();
assert_eq!(vec![1, 2, 3], iter.next().unwrap().to_vec());
assert_eq!(vec![4], iter.next().unwrap().to_vec());
assert_eq!(vec![5, 6], iter.next().unwrap().to_vec());
assert_eq!(empty.clone(), iter.next().unwrap().to_vec());
assert_eq!(None, iter.next());
}
#[test]
fn chunked_range() {
let c = Chunked::from_sizes(vec![0, 4, 2, 0, 1], 0..7);
assert_eq!(c.at(0), 0..0);
assert_eq!(c.at(1), 0..4);
assert_eq!(c.at(2), 4..6);
assert_eq!(c.at(3), 6..6);
assert_eq!(c.at(4), 6..7);
assert_eq!(c.into_storage(), 0..7);
}
#[test]
fn chunked_viewable() {
let mut s = Chunked::<Vec<usize>>::from_offsets(vec![0, 1, 4, 6], vec![0, 1, 2, 3, 4, 5]);
let v1 = s.into_view();
let v2 = v1.clone();
let mut view1_iter = v1.clone().into_iter();
assert_eq!(Some(&[0][..]), view1_iter.next());
assert_eq!(Some(&[1, 2, 3][..]), view1_iter.next());
assert_eq!(Some(&[4, 5][..]), view1_iter.next());
assert_eq!(None, view1_iter.next());
for (a, b) in v1.into_iter().zip(v2.into_iter()) {
assert_eq!(a, b);
}
let v_mut = (&mut s).into_view();
v_mut.isolate(0)[0] = 100;
assert_eq!(&[100][..], s.into_view().at(0));
}
#[test]
fn trim() {
let mut s = Chunked::from_offsets(vec![2, 3, 6, 8], vec![1, 2, 3, 4, 5, 6]);
assert_eq!(3, s.len());
s.transfer_forward(2, 2);
assert_eq!(6, s.data().len());
assert_eq!(3, s.len());
let mut trimmed = s.clone();
trimmed.trim_data(); assert_eq!(4, trimmed.data().len());
let mut trimmed = s;
trimmed.trim(); assert_eq!(4, trimmed.data().len());
}
#[test]
fn convert_between_clumped_and_chunked() {
let chunked = Chunked::from_offsets(vec![2, 3, 4, 8], vec![1, 2, 3, 4, 5, 6]);
let clumped = Clumped::from(chunked.clone());
assert_eq!(clumped.chunks.chunk_offsets, Offsets::new(vec![0, 2, 3]));
assert_eq!(clumped.chunks.offsets, Offsets::new(vec![2, 4, 8]));
assert_eq!(clumped.data, chunked.data);
let chunked_again = Chunked::<Vec<usize>>::from(clumped);
assert_eq!(chunked_again.chunks, chunked.chunks);
assert_eq!(chunked_again.data, chunked.data);
}
}