use crate::imp::core::Bytes32;
use crate::imp::core::KeyTableEntry;
use crate::imp::compiler::chunk_index::ChunkIndex;
use crate::imp::compiler::error::{CompilerError, Result};
pub trait ResourceView {
fn resource_key(&self) -> Bytes32;
fn chunks(&self) -> Vec<(Bytes32, Vec<u8>)>;
}
pub trait GenerationView {
fn root(&self) -> Bytes32;
fn resources(&self) -> Vec<Box<dyn ResourceView + '_>>;
}
#[derive(Debug, Default)]
pub struct KeyTable {
entries: Vec<KeyTableEntry>,
}
impl KeyTable {
pub fn entries(&self) -> &[KeyTableEntry] {
&self.entries
}
pub fn lookup(&self, rk: &Bytes32) -> Option<&KeyTableEntry> {
self.entries.iter().find(|e| &e.static_key == rk)
}
fn push(&mut self, e: KeyTableEntry) {
self.entries.push(e);
}
pub fn verify_against(&self, chunk_count: u32) -> Result<()> {
for e in &self.entries {
for &i in &e.chunk_indices {
if i >= chunk_count {
return Err(CompilerError::MissingChunk(i));
}
}
}
Ok(())
}
}
pub fn build_chunk_index_and_key_table<G: GenerationView>(
generations: &[G],
) -> (ChunkIndex, KeyTable) {
let mut index = ChunkIndex::new();
let mut table = KeyTable::default();
for gen in generations {
let root = gen.root();
for resource in gen.resources() {
let mut chunk_indices = Vec::new();
let mut total_size: u64 = 0;
for (hash, body) in resource.chunks() {
total_size += body.len() as u64;
let gi = index.insert(hash, body);
chunk_indices.push(gi);
}
table.push(KeyTableEntry {
static_key: resource.resource_key(),
generation: root,
chunk_indices,
total_size,
});
}
}
(index, table)
}