diff --git a/src/blob/mod.rs b/src/blob/mod.rs index 090f06f..dd41577 100644 --- a/src/blob/mod.rs +++ b/src/blob/mod.rs @@ -19,10 +19,3 @@ pub struct Blob { tpe: BlobType, id: Id, } - -#[derive(Debug, Clone, Constructor)] -pub struct BlobInformation { - blob: Blob, - offset: u32, - length: u32, -} diff --git a/src/commands/cat.rs b/src/commands/cat.rs index ebd8caa..91d7cfb 100644 --- a/src/commands/cat.rs +++ b/src/commands/cat.rs @@ -3,7 +3,7 @@ use clap::Parser; use crate::backend::{FileType, MapResult, ReadBackend}; use crate::id::Id; -use crate::index::{indexfiles::AllIndexFiles, ReadIndex}; +use crate::index::{AllIndexFiles, BoomIndex, ReadIndex}; #[derive(Parser)] pub(super) struct Opts { @@ -19,7 +19,8 @@ pub(super) fn execute(be: &impl ReadBackend, dbe: &impl ReadBackend, opts: Opts) // special treatment for catingg blobs: read the index and use it to locate the blob "blob" => { let id = Id::from_hex(&opts.id)?; - let dec = AllIndexFiles::new(be.clone()) + let index = BoomIndex::from_iter(AllIndexFiles::new(be.clone()).into_iter()); + let dec = index .get_id(&id) .ok_or(anyhow!("blob not found in index"))? .read_data(be)?; diff --git a/src/commands/list.rs b/src/commands/list.rs index 5a0ce89..afe0c04 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs @@ -15,8 +15,10 @@ pub(super) fn execute(be: &impl ReadBackend, opts: Opts) -> Result<()> { let tpe = match opts.tpe.as_str() { // special treatment for listing blobs: read the index and display it "blobs" => { - for ie in AllIndexFiles::new(be.clone()).into_iter() { - println!("{:?} {}", ie.tpe(), ie.id().to_hex()); + for i in AllIndexFiles::new(be.clone()).into_iter() { + for blob in i.blobs() { + println!("{:?} {}", blob.tpe(), blob.id().to_hex()); + } } return Ok(()); } diff --git a/src/index/boom.rs b/src/index/boom.rs index ef884ad..db3f3a0 100644 --- a/src/index/boom.rs +++ b/src/index/boom.rs @@ -1,36 +1,61 @@ use boomphf::hashmap::BoomHashMap; -use super::{AllIndexFiles, IndexEntry, ReadIndex}; -use crate::backend::ReadBackend; +use super::{BlobType, IndexEntry, ReadIndex}; use crate::id::Id; +use crate::repo::IndexPack; -pub struct BoomIndex(BoomHashMap); - -impl BoomIndex { - pub fn from_all_indexfiles(aif: AllIndexFiles) -> Self { - Self::from_iter(aif.into_iter()) - } +#[derive(Debug)] +struct BoomEntry { + pack_idx: usize, + tpe: BlobType, + offset: u32, + length: u32, } -impl FromIterator for BoomIndex { +pub struct BoomIndex { + packs: Vec, + boom: BoomHashMap, +} + +impl FromIterator for BoomIndex { fn from_iter(iter: T) -> Self where - T: IntoIterator, + T: IntoIterator, { + let mut packs = Vec::new(); let mut ids = Vec::new(); - let mut ies = Vec::new(); + let mut bes = Vec::new(); - for ie in iter { - ids.push(*ie.id()); - ies.push(ie); + for i in iter { + let idx = packs.len(); + packs.push(*i.id()); + + let len = i.blobs().len(); + ids.reserve(len); + bes.reserve(len); + for blob in i.blobs() { + let be = BoomEntry { + pack_idx: idx, + tpe: *blob.tpe(), + offset: *blob.offset(), + length: *blob.length(), + }; + ids.push(*blob.id()); + bes.push(be); + } } - BoomIndex(BoomHashMap::new(ids, ies)) + Self { + packs, + boom: BoomHashMap::new(ids, bes), + } } } impl ReadIndex for BoomIndex { fn get_id(&self, id: &Id) -> Option { - self.0.get(id).map(IndexEntry::clone) + self.boom + .get(id) + .map(|be| IndexEntry::new(self.packs[be.pack_idx], be.tpe, be.offset, be.length)) } } diff --git a/src/index/indexfiles.rs b/src/index/indexfiles.rs index 96dffaa..1b098e1 100644 --- a/src/index/indexfiles.rs +++ b/src/index/indexfiles.rs @@ -1,7 +1,5 @@ -use super::{IndexEntry, ReadIndex}; use crate::backend::{FileType, ReadBackend}; -use crate::id::Id; -use crate::repo::IndexFile; +use crate::repo::{IndexFile, IndexPack}; #[derive(Clone)] pub struct AllIndexFiles { @@ -15,25 +13,14 @@ impl AllIndexFiles { } impl AllIndexFiles { - pub fn into_iter(self) -> impl Iterator { + pub fn into_iter(self) -> impl Iterator { self.be .list(FileType::Index) .unwrap() .into_iter() .flat_map(move |id| { let (_, packs) = IndexFile::from_backend(&self.be, id).unwrap().dissolve(); - packs.into_iter().flat_map(|p| { - let (id, blobs) = p.dissolve(); - blobs - .into_iter() - .map(move |b| IndexEntry::from_index_blob(id, b)) - }) + packs }) } } - -impl ReadIndex for AllIndexFiles { - fn get_id(&self, id: &Id) -> Option { - self.clone().into_iter().find(|ie| ie.id() == id) - } -} diff --git a/src/index/mod.rs b/src/index/mod.rs index 75e42f6..9ff46a3 100644 --- a/src/index/mod.rs +++ b/src/index/mod.rs @@ -1,7 +1,6 @@ use crate::backend::{FileType, ReadBackend}; -use crate::blob::{Blob, BlobType}; +use crate::blob::BlobType; use crate::id::Id; -use crate::repo::IndexBlob; use anyhow::Result; use derive_getters::{Dissolve, Getters}; use derive_more::Constructor; @@ -16,31 +15,15 @@ pub use indexfiles::*; pub struct IndexEntry { pack: Id, tpe: BlobType, - id: Id, offset: u32, length: u32, } impl IndexEntry { - pub fn from_index_blob(pid: Id, ie: IndexBlob) -> Self { - Self { - pack: pid, - tpe: *ie.tpe(), - id: *ie.id(), - offset: *ie.offset(), - length: *ie.length(), - } - } - /// Get a blob described by IndexEntry from the backend pub fn read_data(&self, be: &B) -> Result> { Ok(be.read_partial(FileType::Pack, self.pack, self.offset, self.length)?) } - - #[inline] - pub fn blob(&self) -> Blob { - Blob::new(self.tpe, self.id) - } } pub trait ReadIndex { fn get_id(&self, id: &Id) -> Option;