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()
.filter_map(|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(_, _, _) => None,
})
.collect()
}
pub fn num_values(nested: &[Nested]) -> usize {
let pr = match nested.last().unwrap() {
Nested::Primitive(_, _, len) => *len,
_ => todo!(),
};
iter(nested)
.into_iter()
.enumerate()
.map(|(_, lengths)| {
lengths
.map(|length| if length == 0 { 1 } else { 0 })
.sum::<usize>()
})
.sum::<usize>()
+ pr
}
#[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 = vec![0; iter.len()];
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_values == 0 {
return None;
}
if self.remaining.is_empty() {
self.remaining_values -= 1;
return Some(0);
}
for (iter, remaining) in self
.iter
.iter_mut()
.zip(self.remaining.iter_mut())
.skip(self.current_level)
{
let length: usize = iter.next()?;
*remaining = length;
if length == 0 {
break;
}
self.current_level += 1;
self.total += 1;
}
if let Some(x) = self.remaining.get_mut(self.current_level.saturating_sub(1)) {
*x = x.saturating_sub(1)
}
let r = Some((self.current_level - self.total) as u32);
for index in (1..self.current_level).rev() {
if self.remaining[index] == 0 {
self.current_level -= 1;
self.remaining[index - 1] -= 1;
}
}
if self.remaining[0] == 0 {
self.current_level = self.current_level.saturating_sub(1);
}
self.total = 0;
self.remaining_values -= 1;
r
}
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());
assert_eq!(iter.by_ref().collect::<Vec<_>>(), 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 {
is_optional: false,
offsets: vec![0, 2, 2, 5, 8, 8, 11, 11, 12].try_into().unwrap(),
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 {
is_optional: false,
offsets: vec![0, 2, 2, 4].try_into().unwrap(),
validity: None,
}),
Nested::List(ListNested {
is_optional: false,
offsets: vec![0, 3, 7, 8, 10].try_into().unwrap(),
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: vec![0, 1, 2].try_into().unwrap(),
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: vec![0, 2, 3].try_into().unwrap(),
validity: None,
}),
Nested::Struct(None, true, 3),
Nested::List(ListNested {
is_optional: true,
offsets: vec![0, 3, 6, 7].try_into().unwrap(),
validity: None,
}),
Nested::Primitive(None, true, 7),
];
let expected = vec![0, 2, 2, 1, 2, 2, 0];
test(nested, expected)
}
#[test]
fn struct_list_optional() {
let nested = vec![
Nested::Struct(None, true, 1),
Nested::List(ListNested {
is_optional: true,
offsets: vec![0, 4].try_into().unwrap(),
validity: None,
}),
Nested::Primitive(None, true, 4),
];
let expected = vec![0, 1, 1, 1];
test(nested, expected)
}
#[test]
fn l2_other() {
let nested = vec![
Nested::List(ListNested {
is_optional: false,
offsets: vec![0, 1, 1, 3, 5, 5, 8, 8, 9].try_into().unwrap(),
validity: None,
}),
Nested::List(ListNested {
is_optional: false,
offsets: vec![0, 2, 4, 5, 7, 8, 9, 10, 11, 12].try_into().unwrap(),
validity: None,
}),
Nested::Primitive(None, false, 12),
];
let expected = vec![0, 2, 0, 0, 2, 1, 0, 2, 1, 0, 0, 1, 1, 0, 0];
test(nested, expected)
}
#[test]
fn list_struct_list_1() {
let nested = vec![
Nested::List(ListNested {
is_optional: true,
offsets: vec![0, 2, 2, 5, 8, 8, 11, 11, 12].try_into().unwrap(),
validity: None,
}),
Nested::Struct(None, true, 12),
Nested::List(ListNested {
is_optional: true,
offsets: vec![0, 1, 2, 3, 3, 4, 4, 4, 4, 5, 6, 8].try_into().unwrap(),
validity: None,
}),
Nested::Primitive(None, true, 8),
];
let expected = vec![0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 2, 0];
test(nested, expected)
}
#[test]
fn list_struct_list_2() {
let nested = vec![
Nested::List(ListNested {
is_optional: true,
offsets: vec![0, 1].try_into().unwrap(),
validity: None,
}),
Nested::Struct(None, true, 12),
Nested::List(ListNested {
is_optional: true,
offsets: vec![0, 0].try_into().unwrap(),
validity: None,
}),
Nested::Primitive(None, true, 0),
];
let expected = vec![0];
test(nested, expected)
}
#[test]
fn list_struct_list_3() {
let nested = vec![
Nested::List(ListNested {
is_optional: true,
offsets: vec![0, 1, 1].try_into().unwrap(),
validity: None,
}),
Nested::Struct(None, true, 12),
Nested::List(ListNested {
is_optional: true,
offsets: vec![0, 0].try_into().unwrap(),
validity: None,
}),
Nested::Primitive(None, true, 0),
];
let expected = vec![0, 0];
test(nested, expected)
}
}