Skip to content

Commit

Permalink
Read all mandatory and optional chunks (#279)
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Dec 20, 2021
1 parent fac8efa commit 99023bb
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 2 deletions.
32 changes: 31 additions & 1 deletion git-chunk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,31 @@ pub mod file {
use crate::file::Index;
use std::ops::Range;

///
pub mod not_found {
use std::fmt::{Display, Formatter};

/// The error returned by [Index::offset_by_kind()][super::Index::offset_by_kind()].
#[allow(missing_docs)]
#[derive(Debug)]
pub struct Error {
pub kind: crate::Kind,
pub name: &'static str,
}

impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Chunk named {:?} (id = {}) was not found in chunk file index",
self.name, self.kind
)
}
}

impl std::error::Error for Error {}
}

/// An entry of a chunk file index
pub struct Entry {
/// The kind of the chunk file
Expand All @@ -32,10 +57,15 @@ pub mod file {
pub const EMPTY_SIZE: usize = Index::ENTRY_SIZE;

/// Find a chunk of `kind` and return its offset into the data if found
pub fn offset_by_kind(&self, kind: crate::Kind) -> Option<Range<crate::file::Offset>> {
pub fn offset_by_kind(
&self,
kind: crate::Kind,
name: &'static str,
) -> Result<Range<crate::file::Offset>, not_found::Error> {
self.chunks
.iter()
.find_map(|c| (c.kind == kind).then(|| c.offset.clone()))
.ok_or_else(|| not_found::Error { kind, name })
}
}
}
Expand Down
31 changes: 30 additions & 1 deletion git-pack/src/multi_index.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#![allow(missing_docs, unused)]

use filebuffer::FileBuffer;
use std::ops::Range;

/// Known multi-index file versions
#[derive(PartialEq, Eq, Ord, PartialOrd, Debug, Hash, Clone, Copy)]
Expand All @@ -25,6 +27,7 @@ pub struct File {
num_chunks: u8,
/// The amount of pack files contained within
num_packs: u32,
fanout: Range<git_chunk::file::Offset>,
}

///
Expand All @@ -41,9 +44,27 @@ pub mod access {
}
}

mod chunk {
pub mod pack_names {
pub const ID: git_chunk::Kind = 0x504e414d; /* "PNAM" */
}
pub mod fanout {
pub const ID: git_chunk::Kind = 0x4f494446; /* "OIDF" */
}
pub mod lookup {
pub const ID: git_chunk::Kind = 0x4f49444c; /* "OIDL" */
}
pub mod offsets {
pub const ID: git_chunk::Kind = 0x4f4f4646; /* "OOFF" */
}
pub mod large_offsets {
pub const ID: git_chunk::Kind = 0x4c4f4646; /* "LOFF" */
}
}

///
pub mod init {
use crate::multi_index::{File, Version};
use crate::multi_index::{chunk, File, Version};
use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
use filebuffer::FileBuffer;
use std::convert::{TryFrom, TryInto};
Expand All @@ -65,6 +86,8 @@ pub mod init {
UnsupportedHashKind { kind: u8 },
#[error(transparent)]
ChunkFileDecode(#[from] git_chunk::file::decode::Error),
#[error(transparent)]
MissingChunk(#[from] git_chunk::file::index::not_found::Error),
}
}
pub use error::Error;
Expand Down Expand Up @@ -128,12 +151,18 @@ pub mod init {
};

let chunks = git_chunk::file::Index::from_bytes(&data, HEADER_LEN, num_chunks as u32)?;
let pack_names = chunks.offset_by_kind(chunk::pack_names::ID, "PNAM")?;
let fanout = chunks.offset_by_kind(chunk::fanout::ID, "OIDF")?;
let lookup = chunks.offset_by_kind(chunk::lookup::ID, "OIDL")?;
let offsets = chunks.offset_by_kind(chunk::offsets::ID, "OOFF")?;
let large_offsets = chunks.offset_by_kind(chunk::large_offsets::ID, "LOFF").ok();

Ok(File {
data,
path: path.to_owned(),
version,
hash_kind,
fanout,
num_chunks,
num_packs,
})
Expand Down

0 comments on commit 99023bb

Please sign in to comment.