use std::sync::Arc;
use crate::persistence::LoadError;
use super::payload::PayloadSection;
use super::{StreamCore, StreamError, StreamLimits};
#[derive(Clone)]
pub(crate) struct StreamCoreParts {
pub(crate) node_size: usize,
pub(crate) num_items: usize,
pub(crate) num_nodes: usize,
pub(crate) level_count: usize,
pub(crate) level_bounds: Vec<usize>,
pub(crate) record: usize,
pub(crate) box_stride: usize,
pub(crate) interleaved: bool,
pub(crate) box0: u64,
pub(crate) idx0: u64,
pub(crate) dir_node_start: usize,
pub(crate) dir_boxes: Arc<[u8]>,
pub(crate) dir_indices: Arc<[u8]>,
pub(crate) payload: Option<PayloadSection>,
}
pub(super) fn directory_start(level_bounds: &[usize], level_count: usize, budget: usize) -> usize {
let width = |level: usize| -> usize {
let end = level_bounds[level];
let start = if level == 0 {
0
} else {
level_bounds[level - 1]
};
end - start
};
let mut first_level = level_count - 1;
let mut cached_nodes = width(first_level);
while first_level > 0 {
let next = first_level - 1;
let next_width = width(next);
if cached_nodes + next_width > budget {
break;
}
cached_nodes += next_width;
first_level = next;
}
if first_level == 0 {
0
} else {
level_bounds[first_level - 1]
}
}
#[derive(Clone)]
pub struct StreamDirectory {
pub(crate) parts: StreamCoreParts,
}
impl StreamDirectory {
pub fn num_items(&self) -> usize {
self.parts.num_items
}
pub fn is_empty(&self) -> bool {
self.parts.num_items == 0
}
pub fn node_size(&self) -> usize {
self.parts.node_size
}
pub fn has_payload(&self) -> bool {
self.parts.payload.is_some()
}
pub(crate) fn reattach<R>(
&self,
reader: R,
limits: StreamLimits,
expected_record: usize,
) -> Result<StreamCore<R>, StreamError> {
if self.parts.record != expected_record {
return Err(StreamError::Format(LoadError::UnsupportedVersion));
}
Ok(StreamCore::from_parts(self.parts.clone(), reader, limits))
}
}