use crate::btree_graph_index::BTreeGraphIndex;
use crate::index::{self, IndexError};
use crate::transport::Transport;
pub type Entry = (Vec<Vec<u8>>, Vec<u8>, Vec<Vec<Vec<Vec<u8>>>>);
pub struct PackIndex {
entries: Vec<Entry>,
node_ref_lists: usize,
}
impl PackIndex {
pub fn open(transport: &dyn Transport, name: &str) -> Result<Self, IndexError> {
let bytes = transport
.get_bytes(name)
.map_err(|e| IndexError::Other(format!("reading {name}: {e}")))?;
Self::from_bytes(&bytes)
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, IndexError> {
if bytes.starts_with(crate::btree_index::BTREE_SIGNATURE) {
let btree = BTreeGraphIndex::from_bytes(bytes)
.map_err(|e| IndexError::Other(format!("btree index: {e:?}")))?;
let node_ref_lists = btree.node_ref_lists();
let entries = btree
.iter_all_entries()
.map(|(k, v, r)| (k.clone(), v.clone(), r.clone()))
.collect();
Ok(PackIndex {
entries,
node_ref_lists,
})
} else {
let (header, body) = index::parse_full(bytes)?;
let entries = body
.into_iter()
.map(|(key, (value, references))| (key, value, references))
.collect();
Ok(PackIndex {
entries,
node_ref_lists: header.node_ref_lists,
})
}
}
pub fn iter_all_entries(&self) -> impl Iterator<Item = &Entry> {
self.entries.iter()
}
pub fn node_ref_lists(&self) -> usize {
self.node_ref_lists
}
}
pub enum IndexBuilder {
BTree(crate::btree_builder::BTreeBuilder),
Graph(crate::index::GraphIndexBuilder),
}
impl IndexBuilder {
pub fn new(uses_btree: bool, ref_lists: usize, key_elements: usize) -> Self {
if uses_btree {
IndexBuilder::BTree(crate::btree_builder::BTreeBuilder::new(
ref_lists,
key_elements,
))
} else {
IndexBuilder::Graph(crate::index::GraphIndexBuilder::new(
ref_lists,
key_elements,
))
}
}
pub fn add_node(
&mut self,
key: Vec<Vec<u8>>,
value: Vec<u8>,
references: Vec<Vec<Vec<Vec<u8>>>>,
) -> Result<(), IndexError> {
match self {
IndexBuilder::BTree(b) => b
.add_node(key, value, references)
.map_err(|e| IndexError::Other(format!("btree node: {e:?}"))),
IndexBuilder::Graph(b) => b.add_node(key, value, references),
}
}
pub fn finish(&self) -> Result<Vec<u8>, IndexError> {
match self {
IndexBuilder::BTree(b) => b
.finish()
.map_err(|e| IndexError::Other(format!("btree finish: {e:?}"))),
IndexBuilder::Graph(b) => b.finish(),
}
}
}