use super::super::pages::Nested;
use super::to_length;
trait DebugIter: Iterator<Item = usize> + std::fmt::Debug {}
impl<A: Iterator<Item = usize> + std::fmt::Debug> DebugIter for A {}
fn iter<'a>(nested: &'a [Nested]) -> Vec<Box<dyn DebugIter + 'a>> {
nested
.iter()
.enumerate()
.filter_map(|(i, nested)| match nested {
Nested::Primitive(_, _, _) => None,
Nested::List(nested) => Some(Box::new(to_length(nested.offsets)) as Box<dyn DebugIter>),
Nested::LargeList(nested) => {
Some(Box::new(to_length(nested.offsets)) as Box<dyn DebugIter>)
}
Nested::Struct(_, _, length) => {
if i == 0 {
Some(Box::new(std::iter::repeat(1usize).take(*length)) as Box<dyn DebugIter>)
} else {
None
}
}
})
.collect()
}
pub fn num_values(nested: &[Nested]) -> usize {
let iterators = iter(nested);
let depth = iterators.len();
iterators
.into_iter()
.enumerate()
.map(|(index, lengths)| {
if index == depth - 1 {
lengths
.map(|length| if length == 0 { 1 } else { length })
.sum::<usize>()
} else {
lengths
.map(|length| usize::from(length == 0))
.sum::<usize>()
}
})
.sum()
}
#[derive(Debug)]
pub struct RepLevelsIter<'a> {
iter: Vec<Box<dyn DebugIter + 'a>>,
remaining: Vec<usize>, current_level: usize, total: usize, remaining_values: usize,
}
impl<'a> RepLevelsIter<'a> {
pub fn new(nested: &'a [Nested]) -> Self {
let remaining_values = num_values(nested);
let iter = iter(nested);
let remaining = std::iter::repeat(0).take(iter.len()).collect();
Self {
iter,
remaining,
total: 0,
current_level: 0,
remaining_values,
}
}
}
impl<'a> Iterator for RepLevelsIter<'a> {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if *self.remaining.last().unwrap() > 0 {
*self.remaining.last_mut().unwrap() -= 1;
let total = self.total;
self.total = 0;
let r = Some((self.current_level - total) as u32);
for level in 0..self.current_level - 1 {
let level = self.remaining.len() - level - 1;
if self.remaining[level] == 0 {
self.current_level -= 1;
self.remaining[level.saturating_sub(1)] -= 1;
}
}
if self.remaining[0] == 0 {
self.current_level -= 1;
}
self.remaining_values -= 1;
return r;
}
self.total = 0;
for (iter, remaining) in self
.iter
.iter_mut()
.zip(self.remaining.iter_mut())
.skip(self.current_level)
{
let length: usize = iter.next()?;
if length == 0 {
self.remaining_values -= 1;
return Some(self.current_level as u32);
}
*remaining = length;
self.current_level += 1;
self.total += 1;
}
self.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
let length = self.remaining_values;
(length, Some(length))
}
}
#[cfg(test)]
mod tests {
use super::super::super::pages::ListNested;
use super::*;
fn test(nested: Vec<Nested>, expected: Vec<u32>) {
let mut iter = RepLevelsIter::new(&nested);
assert_eq!(iter.size_hint().0, expected.len());
let result = iter.by_ref().collect::<Vec<_>>();
assert_eq!(result, expected);
assert_eq!(iter.size_hint().0, 0);
}
#[test]
fn struct_required() {
let nested = vec![
Nested::Struct(None, false, 10),
Nested::Primitive(None, true, 10),
];
let expected = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
test(nested, expected)
}
#[test]
fn struct_optional() {
let nested = vec![
Nested::Struct(None, true, 10),
Nested::Primitive(None, true, 10),
];
let expected = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
test(nested, expected)
}
#[test]
fn l1() {
let nested = vec![
Nested::List(ListNested::<i32> {
is_optional: false,
offsets: &[0, 2, 2, 5, 8, 8, 11, 11, 12],
validity: None,
}),
Nested::Primitive(None, false, 12),
];
let expected = vec![0u32, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0];
test(nested, expected)
}
#[test]
fn l2() {
let nested = vec![
Nested::List(ListNested::<i32> {
is_optional: false,
offsets: &[0, 2, 2, 4],
validity: None,
}),
Nested::List(ListNested::<i32> {
is_optional: false,
offsets: &[0, 3, 7, 8, 10],
validity: None,
}),
Nested::Primitive(None, false, 10),
];
let expected = vec![0, 2, 2, 1, 2, 2, 2, 0, 0, 1, 2];
test(nested, expected)
}
#[test]
fn list_of_struct() {
let nested = vec![
Nested::List(ListNested {
is_optional: true,
offsets: &[0i32, 1, 2],
validity: None,
}),
Nested::Struct(None, true, 2),
Nested::Primitive(None, true, 2),
];
let expected = vec![0, 0];
test(nested, expected)
}
#[test]
fn list_struct_list() {
let nested = vec![
Nested::List(ListNested {
is_optional: true,
offsets: &[0i32, 2, 3],
validity: None,
}),
Nested::Struct(None, true, 3),
Nested::List(ListNested {
is_optional: true,
offsets: &[0i32, 3, 6, 7],
validity: None,
}),
Nested::Primitive(None, true, 7),
];
let expected = vec![0, 2, 2, 1, 2, 2, 0];
test(nested, expected)
}
}