use std::{iter, mem};
use byteorder::{LE, ByteOrder};
use std::marker::PhantomData;
use crate::{accessor, buffer};
fn buffer_view_slice<'a, 's>(
view: buffer::View<'a>,
get_buffer_data: &dyn Fn(buffer::Buffer<'a>) -> Option<&'s [u8]>,
) -> Option<&'s [u8]> {
let start = view.offset();
let end = start + view.length();
get_buffer_data(view.buffer())
.map(|slice| &slice[start..end])
}
#[derive(Clone, Debug)]
pub enum Iter<'a, T: Item> {
Standard(ItemIter<'a, T>),
Sparse(SparseIter<'a, T>),
}
impl<'a, T: Item> Iterator for Iter<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
match self {
&mut Iter::Standard(ref mut iter) => iter.next(),
&mut Iter::Sparse(ref mut iter) => iter.next(),
}
}
}
#[derive(Clone, Debug)]
pub enum SparseIndicesIter<'a> {
U8(ItemIter<'a, u8>),
U16(ItemIter<'a, u16>),
U32(ItemIter<'a, u32>),
}
impl<'a> Iterator for SparseIndicesIter<'a> {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
match *self {
SparseIndicesIter::U8(ref mut iter) => iter.next().map(|x| x as u32),
SparseIndicesIter::U16(ref mut iter) => iter.next().map(|x| x as u32),
SparseIndicesIter::U32(ref mut iter) => iter.next(),
}
}
}
#[derive(Clone, Debug)]
pub struct SparseIter<'a, T: Item> {
base: ItemIter<'a, T>,
indices: iter::Peekable<SparseIndicesIter<'a>>,
values: ItemIter<'a, T>,
counter: u32,
}
impl<'a, T: Item> SparseIter<'a, T> {
pub fn new(
base: ItemIter<'a, T>,
indices: SparseIndicesIter<'a>,
values: ItemIter<'a, T>,
) -> Self {
SparseIter {
base: base,
indices: indices.peekable(),
values: values,
counter: 0,
}
}
}
impl<'a, T: Item> Iterator for SparseIter<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let next_base_value = self.base.next();
if next_base_value.is_none() {
return None;
}
let mut next_value = next_base_value.unwrap();
let next_sparse_index = self.indices.peek().clone();
if let Some(index) = next_sparse_index {
if *index == self.counter {
self.indices.next();
next_value = self.values.next().unwrap();
}
}
self.counter += 1;
Some(next_value)
}
}
pub trait Item {
fn from_slice(slice: &[u8]) -> Self;
}
#[derive(Copy, Clone, Debug)]
pub struct ItemIter<'a, T: Item> {
stride: usize,
data: &'a [u8],
_phantom: PhantomData<T>,
}
impl Item for i8 {
fn from_slice(slice: &[u8]) -> Self {
slice[0] as i8
}
}
impl Item for i16 {
fn from_slice(slice: &[u8]) -> Self {
LE::read_i16(slice)
}
}
impl Item for u8 {
fn from_slice(slice: &[u8]) -> Self {
slice[0]
}
}
impl Item for u16 {
fn from_slice(slice: &[u8]) -> Self {
LE::read_u16(slice)
}
}
impl Item for u32 {
fn from_slice(slice: &[u8]) -> Self {
LE::read_u32(slice)
}
}
impl Item for f32 {
fn from_slice(slice: &[u8]) -> Self {
LE::read_f32(slice)
}
}
impl<T: Item> Item for [T; 2] {
fn from_slice(slice: &[u8]) -> Self {
assert!(slice.len() >= 2 * mem::size_of::<T>());
[T::from_slice(slice),
T::from_slice(&slice[mem::size_of::<T>() ..])]
}
}
impl<T: Item> Item for [T; 3] {
fn from_slice(slice: &[u8]) -> Self {
assert!(slice.len() >= 3 * mem::size_of::<T>());
[T::from_slice(slice),
T::from_slice(&slice[1 * mem::size_of::<T>() ..]),
T::from_slice(&slice[2 * mem::size_of::<T>() ..])]
}
}
impl<T: Item> Item for [T; 4] {
fn from_slice(slice: &[u8]) -> Self {
assert!(slice.len() >= 4 * mem::size_of::<T>());
[T::from_slice(slice),
T::from_slice(&slice[1 * mem::size_of::<T>() ..]),
T::from_slice(&slice[2 * mem::size_of::<T>() ..]),
T::from_slice(&slice[3 * mem::size_of::<T>() ..])]
}
}
impl<'a, T: Item> ItemIter<'a, T> {
pub fn new(slice: &'a [u8], stride: usize) -> Self {
ItemIter {
data: slice,
stride: stride,
_phantom: PhantomData,
}
}
}
impl<'a, 's, T: Item> Iter<'s, T> {
pub fn new<F>(
accessor: super::Accessor<'a>,
get_buffer_data: F,
) -> Option<Iter<'s, T>>
where F: Clone + Fn(buffer::Buffer<'a>) -> Option<&'s [u8]>,
{
let is_sparse = accessor.sparse().is_some();
if is_sparse {
let sparse = accessor.sparse();
let indices = sparse.as_ref().unwrap().indices();
let values = sparse.as_ref().unwrap().values();
let base_iter = {
let view = accessor.view();
let stride = view.stride().unwrap_or(mem::size_of::<T>());
let start = accessor.offset();
let end = start + stride * (accessor.count() - 1) + mem::size_of::<T>();
let subslice = if let Some(slice) = buffer_view_slice(view, &get_buffer_data) {
&slice[start..end]
} else {
return None
};
ItemIter::new(subslice, stride)
};
let sparse_count = sparse.as_ref().unwrap().count() as usize;
let index_iter = {
let view = indices.view();
let index_size = indices.index_type().size();
let stride = view.stride().unwrap_or(index_size);
let subslice = if let Some(slice) = buffer_view_slice(view, &get_buffer_data) {
let start = indices.offset() as usize;
let end = start + stride * (sparse_count - 1) + index_size;
&slice[start..end]
} else {
return None
};
match indices.index_type() {
accessor::sparse::IndexType::U8 => SparseIndicesIter::U8(ItemIter::new(subslice, stride)),
accessor::sparse::IndexType::U16 => SparseIndicesIter::U16(ItemIter::new(subslice, stride)),
accessor::sparse::IndexType::U32 => SparseIndicesIter::U32(ItemIter::new(subslice, stride)),
}
};
let value_iter = {
let view = values.view();
let stride = view.stride().unwrap_or(mem::size_of::<T>());
let subslice = if let Some(slice) = buffer_view_slice(view, &get_buffer_data) {
let start = values.offset() as usize;
let end = start + stride * (sparse_count - 1) + mem::size_of::<T>();
&slice[start..end]
} else {
return None
};
ItemIter::new(subslice, stride)
};
Some(Iter::Sparse(SparseIter::new(base_iter, index_iter, value_iter)))
} else {
debug_assert_eq!(mem::size_of::<T>(), accessor.size());
debug_assert!(mem::size_of::<T>() > 0);
let view = accessor.view();
let stride = view.stride().unwrap_or(mem::size_of::<T>());
debug_assert!(stride >= mem::size_of::<T>(), "Mismatch in stride, expected at least {} stride but found {}", mem::size_of::<T>(), stride);
let start = accessor.offset();
let end = start + stride * (accessor.count() - 1) + mem::size_of::<T>();
let subslice = if let Some(slice) = buffer_view_slice(view, &get_buffer_data) {
&slice[start..end]
} else {
return None
};
Some(Iter::Standard(ItemIter { stride, data: subslice, _phantom: PhantomData }))
}
}
}
impl<'a, T: Item> ExactSizeIterator for ItemIter<'a, T> {}
impl<'a, T: Item> Iterator for ItemIter<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let stride = if self.data.len() >= self.stride {
Some(self.stride)
} else if self.data.len() >= mem::size_of::<T>() {
Some(mem::size_of::<T>())
} else {
None
};
if let Some(stride) = stride {
let (val, data) = self.data.split_at(stride);
let val = T::from_slice(val);
self.data = data;
Some(val)
} else {
None
}
}
fn nth(&mut self, nth: usize) -> Option<Self::Item> {
if let Some(val_data) = self.data.get(nth * self.stride ..) {
if val_data.len() >= mem::size_of::<T>() {
let val = T::from_slice(val_data);
self.data = &val_data[self.stride.min(val_data.len()) ..];
Some(val)
} else {
None
}
} else {
None
}
}
fn last(self) -> Option<Self::Item> {
if self.data.len() >= mem::size_of::<T>() {
self.data
.get((self.data.len() - 1) / self.stride * self.stride ..)
.map(T::from_slice)
} else {
None
}
}
fn count(self) -> usize {
self.size_hint().0
}
fn size_hint(&self) -> (usize, Option<usize>) {
let hint = self.data.len() / self.stride
+ (self.data.len() % self.stride >= mem::size_of::<T>()) as usize;
(hint, Some(hint))
}
}