use super::*;
use anyhow::Result;
use dsi_bitstream::prelude::*;
#[derive(Debug, Clone)]
pub struct OffsetDegIter<D: Decode> {
number_of_nodes: usize,
compression_window: usize,
min_interval_length: usize,
node_id: usize,
decoder: D,
backrefs: Vec<usize>,
}
impl<D: Decode + BitSeek> OffsetDegIter<D> {
pub fn get_pos(&mut self) -> u64 {
self.decoder.bit_pos().unwrap()
}
}
impl<D: Decode + BitSeek> Iterator for OffsetDegIter<D> {
type Item = (u64, usize);
fn next(&mut self) -> Option<(u64, usize)> {
if self.node_id >= self.number_of_nodes {
return None;
}
let offset = self.get_pos();
Some((offset, self.next_degree().unwrap()))
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), Some(self.len()))
}
}
impl<D: Decode + BitSeek> ExactSizeIterator for OffsetDegIter<D> {
#[inline(always)]
fn len(&self) -> usize {
self.number_of_nodes - self.node_id
}
}
impl<D: Decode + BitSeek> std::iter::FusedIterator for OffsetDegIter<D> {}
impl<D: Decode> OffsetDegIter<D> {
pub fn new(
decoder: D,
number_of_nodes: usize,
compression_window: usize,
min_interval_length: usize,
) -> Self {
Self {
number_of_nodes,
compression_window,
min_interval_length,
node_id: 0,
decoder,
backrefs: vec![0; compression_window],
}
}
pub fn new_from(
decoder: D,
number_of_nodes: usize,
compression_window: usize,
min_interval_length: usize,
node_id: usize,
backrefs: Vec<usize>,
) -> Self {
debug_assert_eq!(backrefs.len(), compression_window);
Self {
number_of_nodes,
compression_window,
min_interval_length,
node_id,
decoder,
backrefs,
}
}
#[inline(always)]
pub fn num_nodes(&self) -> usize {
self.number_of_nodes
}
pub fn get_decoder(&self) -> &D {
&self.decoder
}
pub fn map_decoder<D2: Decode, F: FnOnce(D) -> D2>(self, f: F) -> OffsetDegIter<D2> {
OffsetDegIter {
decoder: f(self.decoder),
backrefs: self.backrefs,
node_id: self.node_id,
min_interval_length: self.min_interval_length,
compression_window: self.compression_window,
number_of_nodes: self.number_of_nodes,
}
}
pub fn next_degree(&mut self) -> Result<usize> {
let degree = self.decoder.read_outdegree() as usize;
if degree == 0 {
if self.compression_window != 0 {
self.backrefs[self.node_id % self.compression_window] = degree;
}
self.node_id += 1;
return Ok(degree);
}
let mut nodes_left_to_decode = degree;
let ref_delta = if self.compression_window != 0 {
self.decoder.read_reference_offset() as usize
} else {
0
};
if ref_delta != 0 {
let reference_node_id = self.node_id - ref_delta;
let ref_degree = self.backrefs[reference_node_id % self.compression_window];
let number_of_blocks = self.decoder.read_block_count() as usize;
if number_of_blocks == 0 {
nodes_left_to_decode -= ref_degree;
} else {
let mut idx = self.decoder.read_block() as usize;
nodes_left_to_decode -= idx;
for block_id in 1..number_of_blocks {
let block = self.decoder.read_block() as usize;
let end = idx + block + 1;
if block_id % 2 == 0 {
nodes_left_to_decode -= block + 1;
}
idx = end;
}
if number_of_blocks & 1 == 0 {
nodes_left_to_decode -= ref_degree - idx;
}
}
};
if nodes_left_to_decode != 0 && self.min_interval_length != 0 {
let number_of_intervals = self.decoder.read_interval_count() as usize;
if number_of_intervals != 0 {
let _ = self.decoder.read_interval_start();
let mut delta = self.decoder.read_interval_len() as usize;
delta += self.min_interval_length;
nodes_left_to_decode -= delta;
for _ in 1..number_of_intervals {
let _ = self.decoder.read_interval_start();
delta = self.decoder.read_interval_len() as usize;
delta += self.min_interval_length;
nodes_left_to_decode -= delta;
}
}
}
self.decoder.num_of_residuals(nodes_left_to_decode);
if nodes_left_to_decode != 0 {
let _ = self.decoder.read_first_residual();
for _ in 1..nodes_left_to_decode {
let _ = self.decoder.read_residual();
}
}
if self.compression_window != 0 {
self.backrefs[self.node_id % self.compression_window] = degree;
}
self.node_id += 1;
Ok(degree)
}
}