use std::cmp::min;
use std::mem;
pub struct ArbitraryChunkMut<'a, 'b, T: 'a> {
data: &'a mut [T],
counts: &'b [usize],
cursor: usize,
}
impl<'a, 'b, T> Iterator for ArbitraryChunkMut<'a, 'b, T> {
type Item = &'a mut [T];
fn next(&mut self) -> Option<Self::Item> {
if self.cursor > self.counts.len() - 1 {
return None;
}
let c = self.counts[self.cursor];
self.cursor += 1;
if c == 0 {
return Some(&mut []);
}
if self.data.is_empty() {
return None;
}
let point = min(c, self.data.len());
let slice = mem::take(&mut self.data);
let (l, r) = slice.split_at_mut(point);
self.data = r;
Some(l)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.counts.len() - self.cursor;
(remaining, Some(remaining))
}
}
pub struct ArbitraryChunk<'a, 'b, T: 'a> {
data: &'a [T],
counts: &'b [usize],
cursor: usize,
}
impl<'a, 'b, T> Iterator for ArbitraryChunk<'a, 'b, T> {
type Item = &'a [T];
fn next(&mut self) -> Option<Self::Item> {
if self.cursor > self.counts.len() - 1 {
return None;
}
let c = self.counts[self.cursor];
self.cursor += 1;
if c == 0 {
return Some(&[]);
}
if self.data.is_empty() {
return None;
}
let point = min(c, self.data.len());
let slice = mem::take(&mut self.data);
let (l, r) = slice.split_at(point);
self.data = r;
Some(l)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.counts.len() - self.cursor;
(remaining, Some(remaining))
}
}
pub struct ArbitraryChunkExactMut<'a, 'b, T: 'a> {
data: &'a mut [T],
counts: &'b [usize],
cursor: usize,
}
impl<'a, 'b, T> Iterator for ArbitraryChunkExactMut<'a, 'b, T> {
type Item = &'a mut [T];
fn next(&mut self) -> Option<Self::Item> {
if self.cursor > self.counts.len() - 1 {
return None;
}
let c = self.counts[self.cursor];
self.cursor += 1;
if c == 0 {
return Some(&mut []);
}
if self.data.is_empty() || c > self.data.len() {
return None;
}
let slice = mem::take(&mut self.data);
let (l, r) = slice.split_at_mut(c);
self.data = r;
Some(l)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.counts.len() - self.cursor;
(remaining, Some(remaining))
}
}
impl<'a, 'b, T> ArbitraryChunkExactMut<'a, 'b, T> {
pub fn remainder(&'a mut self) -> &'a mut [T] {
self.data
}
}
pub struct ArbitraryChunkExact<'a, 'b, T: 'a> {
data: &'a [T],
counts: &'b [usize],
cursor: usize,
}
impl<'a, 'b, T> Iterator for ArbitraryChunkExact<'a, 'b, T> {
type Item = &'a [T];
fn next(&mut self) -> Option<Self::Item> {
if self.cursor > self.counts.len() - 1 {
return None;
}
let c = self.counts[self.cursor];
self.cursor += 1;
if c == 0 {
return Some(&[]);
}
if self.data.is_empty() || c > self.data.len() {
return None;
}
let slice = mem::take(&mut self.data);
let (l, r) = slice.split_at(c);
self.data = r;
Some(l)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.counts.len() - self.cursor;
(remaining, Some(remaining))
}
}
impl<'a, 'b, T> ArbitraryChunkExact<'a, 'b, T> {
pub fn remainder(&'a self) -> &'a [T] {
self.data
}
}
pub trait ArbitraryChunks<'a, 'b, T> {
fn arbitrary_chunks(&'a self, counts: &'b [usize]) -> ArbitraryChunk<'a, 'b, T>;
fn arbitrary_chunks_mut(&'a mut self, counts: &'b [usize]) -> ArbitraryChunkMut<'a, 'b, T>;
fn arbitrary_chunks_exact(&'a self, counts: &'b [usize]) -> ArbitraryChunkExact<'a, 'b, T>;
fn arbitrary_chunks_exact_mut(&'a mut self, counts: &'b [usize]) -> ArbitraryChunkExactMut<'a, 'b, T>;
}
impl<'a, 'b, T> ArbitraryChunks<'a, 'b, T> for [T] {
fn arbitrary_chunks(&'a self, counts: &'b [usize]) -> ArbitraryChunk<'a, 'b, T> {
ArbitraryChunk {
data: self,
counts,
cursor: 0,
}
}
fn arbitrary_chunks_mut(&'a mut self, counts: &'b [usize]) -> ArbitraryChunkMut<'a, 'b, T> {
ArbitraryChunkMut {
data: self,
counts,
cursor: 0,
}
}
fn arbitrary_chunks_exact(&'a self, counts: &'b [usize]) -> ArbitraryChunkExact<'a, 'b, T> {
ArbitraryChunkExact {
data: self,
counts,
cursor: 0,
}
}
fn arbitrary_chunks_exact_mut(&'a mut self, counts: &'b [usize]) -> ArbitraryChunkExactMut<'a, 'b, T> {
ArbitraryChunkExactMut {
data: self,
counts,
cursor: 0,
}
}
}
#[cfg(test)]
mod tests {
use crate::ArbitraryChunks;
#[test]
fn it_stops_when_chunks_run_out() {
let chunks: Vec<usize> = vec![0, 1, 2, 3];
let data = vec![8, 7, 6, 5, 4, 3, 2, 1];
let chunk_data: Vec<Vec<i32>> = data
.arbitrary_chunks(&chunks)
.map(|chunk| chunk.to_vec())
.collect();
assert_eq!(Vec::<i32>::new(), chunk_data[0]);
assert_eq!(vec![8], chunk_data[1]);
assert_eq!(vec![7, 6], chunk_data[2]);
assert_eq!(vec![5, 4, 3], chunk_data[3]);
assert_eq!(None, chunk_data.get(4));
}
#[test]
fn mut_stops_when_chunks_run_out() {
let chunks: Vec<usize> = vec![0, 1, 2, 3];
let mut data = vec![8, 7, 6, 5, 4, 3, 2, 1];
let chunk_data: Vec<Vec<i32>> = data
.arbitrary_chunks_mut(&chunks)
.map(|chunk| chunk.to_vec())
.collect();
assert_eq!(Vec::<i32>::new(), chunk_data[0]);
assert_eq!(vec![8], chunk_data[1]);
assert_eq!(vec![7, 6], chunk_data[2]);
assert_eq!(vec![5, 4, 3], chunk_data[3]);
assert_eq!(None, chunk_data.get(4));
}
#[test]
fn exact_stops_when_chunks_run_out() {
let chunks: Vec<usize> = vec![0, 1, 2, 3];
let data = vec![8, 7, 6, 5, 4, 3, 2, 1];
let mut iter = data.arbitrary_chunks_exact(&chunks);
assert_eq!(&[0i32; 0], iter.next().unwrap());
assert_eq!(&[8i32], iter.next().unwrap());
assert_eq!(&[7i32, 6], iter.next().unwrap());
assert_eq!(&[5i32, 4, 3], iter.next().unwrap());
assert_eq!(None, iter.next());
assert_eq!(&[2i32, 1], iter.remainder());
}
#[test]
fn exact_mut_stops_when_chunks_run_out() {
let chunks: Vec<usize> = vec![0, 1, 2, 3];
let mut data = vec![8, 7, 6, 5, 4, 3, 2, 1];
let mut iter = data.arbitrary_chunks_exact_mut(&chunks);
assert_eq!(&mut [0i32; 0], iter.next().unwrap());
assert_eq!(&mut [8i32], iter.next().unwrap());
assert_eq!(&mut [7i32, 6], iter.next().unwrap());
assert_eq!(&mut [5i32, 4, 3], iter.next().unwrap());
assert_eq!(None, iter.next());
assert_eq!(&mut [2i32, 1], iter.remainder());
}
#[test]
fn it_accounts_for_trailing_zeros() {
let chunks: Vec<usize> = vec![0, 1, 2, 3, 0, 0];
let data = vec![8, 7, 6, 5, 4, 3, 2, 1];
let chunk_data: Vec<Vec<i32>> = data
.arbitrary_chunks(&chunks)
.map(|chunk| chunk.to_vec())
.collect();
assert_eq!(Vec::<i32>::new(), chunk_data[0]);
assert_eq!(vec![8], chunk_data[1]);
assert_eq!(vec![7, 6], chunk_data[2]);
assert_eq!(vec![5, 4, 3], chunk_data[3]);
assert_eq!(Vec::<i32>::new(), chunk_data[4]);
assert_eq!(Vec::<i32>::new(), chunk_data[5]);
assert_eq!(None, chunk_data.get(6));
}
#[test]
fn mut_accounts_for_trailing_zeros() {
let chunks: Vec<usize> = vec![0, 1, 2, 3, 0, 0];
let mut data = vec![8, 7, 6, 5, 4, 3, 2, 1];
let chunk_data: Vec<Vec<i32>> = data
.arbitrary_chunks_mut(&chunks)
.map(|chunk| chunk.to_vec())
.collect();
assert_eq!(Vec::<i32>::new(), chunk_data[0]);
assert_eq!(vec![8], chunk_data[1]);
assert_eq!(vec![7, 6], chunk_data[2]);
assert_eq!(vec![5, 4, 3], chunk_data[3]);
assert_eq!(Vec::<i32>::new(), chunk_data[4]);
assert_eq!(Vec::<i32>::new(), chunk_data[5]);
assert_eq!(None, chunk_data.get(6));
}
#[test]
fn exact_accounts_for_trailing_zeros() {
let chunks: Vec<usize> = vec![0, 1, 2, 3, 0, 0];
let data = vec![8, 7, 6, 5, 4, 3, 2, 1];
let mut iter = data.arbitrary_chunks_exact(&chunks);
assert_eq!(&[0i32; 0], iter.next().unwrap());
assert_eq!(&[8i32], iter.next().unwrap());
assert_eq!(&[7i32, 6], iter.next().unwrap());
assert_eq!(&[5i32, 4, 3], iter.next().unwrap());
assert_eq!(&[0i32; 0], iter.next().unwrap());
assert_eq!(&[0i32; 0], iter.next().unwrap());
assert_eq!(None, iter.next());
assert_eq!(&[2i32, 1], iter.remainder());
}
#[test]
fn exact_mut_accounts_for_trailing_zeros() {
let chunks: Vec<usize> = vec![0, 1, 2, 3, 0, 0];
let mut data = vec![8, 7, 6, 5, 4, 3, 2, 1];
let mut iter = data.arbitrary_chunks_exact_mut(&chunks);
assert_eq!(&mut [0i32; 0], iter.next().unwrap());
assert_eq!(&mut [8i32], iter.next().unwrap());
assert_eq!(&mut [7i32, 6], iter.next().unwrap());
assert_eq!(&mut [5i32, 4, 3], iter.next().unwrap());
assert_eq!(&[0i32; 0], iter.next().unwrap());
assert_eq!(&[0i32; 0], iter.next().unwrap());
assert_eq!(None, iter.next());
assert_eq!(&mut [2i32, 1], iter.remainder());
}
#[test]
fn it_stops_when_data_runs_out() {
let chunks: Vec<usize> = vec![0, 1, 2, 3];
let data = vec![8, 7, 6, 5, 4];
let chunk_data: Vec<Vec<i32>> = data
.arbitrary_chunks(&chunks)
.map(|chunk| chunk.to_vec())
.collect();
assert_eq!(Vec::<i32>::new(), chunk_data[0]);
assert_eq!(vec![8], chunk_data[1]);
assert_eq!(vec![7, 6], chunk_data[2]);
assert_eq!(vec![5, 4], chunk_data[3]);
assert_eq!(None, chunk_data.get(4));
}
#[test]
fn mut_stops_when_data_runs_out() {
let chunks: Vec<usize> = vec![0, 1, 2, 3];
let mut data = vec![8, 7, 6, 5, 4];
let chunk_data: Vec<Vec<i32>> = data
.arbitrary_chunks_mut(&chunks)
.map(|chunk| chunk.to_vec())
.collect();
assert_eq!(Vec::<i32>::new(), chunk_data[0]);
assert_eq!(vec![8], chunk_data[1]);
assert_eq!(vec![7, 6], chunk_data[2]);
assert_eq!(vec![5, 4], chunk_data[3]);
assert_eq!(None, chunk_data.get(4));
}
#[test]
fn exact_stops_when_data_runs_out() {
let chunks: Vec<usize> = vec![0, 1, 2, 3];
let data = vec![8, 7, 6, 5, 4];
let mut iter = data.arbitrary_chunks_exact(&chunks);
assert_eq!(&[0i32; 0], iter.next().unwrap());
assert_eq!(&[8i32], iter.next().unwrap());
assert_eq!(&[7i32, 6], iter.next().unwrap());
assert_eq!(None, iter.next());
assert_eq!(&[5i32, 4], iter.remainder());
}
#[test]
fn exact_mut_stops_when_data_runs_out() {
let chunks: Vec<usize> = vec![0, 1, 2, 3];
let mut data = vec![8, 7, 6, 5, 4];
let mut iter = data.arbitrary_chunks_exact_mut(&chunks);
assert_eq!(&mut [0i32; 0], iter.next().unwrap());
assert_eq!(&mut [8i32], iter.next().unwrap());
assert_eq!(&mut [7i32, 6], iter.next().unwrap());
assert_eq!(None, iter.next());
assert_eq!(&mut [5i32, 4], iter.remainder());
}
}