Skip to content

Commit 9594d94

Browse files
committed
refactor PackIndexReader
create explicit struct reading pack indexes use generics rather than trait objects as casting from &Trait to &SuperTrait is not implemented (rust-lang/rfcs#2765) and its very inconveninent to not be able to pass `&mut BufReadSeek` to a function that expects a `&mut BufRead`. Furthermore, the main reason we were using dynamic dispatch in the first place was just to make certain traits (Serialize & hence BitObj) object safe. I think Deserialize was rewritten to use dyn to be consistent with Serialize.
1 parent c8a8e08 commit 9594d94

File tree

2 files changed

+63
-12
lines changed

2 files changed

+63
-12
lines changed

src/libbit/src/pack.rs

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::hash::{BitHash, SHA1Hash, BIT_HASH_SIZE};
33
use crate::io::{BufReadExt, HashReader, ReadExt};
44
use crate::serialize::{BufReadSeek, Deserialize};
55
use std::io::{BufRead, SeekFrom};
6+
use std::ops::{Deref, DerefMut};
67

78
const PACK_IDX_MAGIC: u32 = 0xff744f63;
89
const FANOUT_ENTRYC: usize = 256;
@@ -18,10 +19,48 @@ pub struct PackIndex {
1819
pack_hash: SHA1Hash,
1920
}
2021

21-
impl PackIndex {
22-
fn find_oid_index(mut r: &mut dyn BufReadSeek, oid: BitHash) -> BitResult<usize> {
23-
r.seek(SeekFrom::Start(PACK_IDX_HEADER_SIZE))?;
24-
let fanout = r.read_array::<u32, FANOUT_ENTRYC>()?;
22+
pub struct PackIndexReader<'r, R> {
23+
reader: &'r mut R,
24+
fanout: [u32; FANOUT_ENTRYC],
25+
}
26+
27+
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
28+
enum Layer {
29+
Fan,
30+
Oid,
31+
Crc,
32+
Ofs,
33+
Ext,
34+
}
35+
36+
impl<'r, R: BufReadSeek> PackIndexReader<'r, R> {
37+
pub fn new(reader: &'r mut R) -> BitResult<Self> {
38+
let header = PackIndex::parse_header(reader);
39+
let fanout = reader.read_array::<u32, FANOUT_ENTRYC>()?;
40+
Ok(Self { reader, fanout })
41+
}
42+
}
43+
44+
impl<'r, R: BufReadSeek> PackIndexReader<'r, R> {
45+
fn offset_of(&mut self, layer: Layer) -> u64 {
46+
match layer {
47+
Layer::Fan => PACK_IDX_HEADER_SIZE,
48+
Layer::Oid => PACK_IDX_HEADER_SIZE,
49+
Layer::Crc => todo!(),
50+
Layer::Ofs => todo!(),
51+
Layer::Ext => todo!(),
52+
}
53+
}
54+
55+
fn find_oid_offset(&mut self, oid: BitHash) -> BitResult<usize> {
56+
todo!()
57+
}
58+
59+
fn read_from<T: Deserialize>(&mut self, layer: Layer) -> BitResult<T> {
60+
todo!()
61+
}
62+
63+
fn find_oid_index(&mut self, oid: BitHash) -> BitResult<usize> {
2564
// fanout has 256 elements
2665
// example
2766
// [
@@ -45,18 +84,32 @@ impl PackIndex {
4584
//
4685
let prefix = oid[0] as usize;
4786
// low..high (inclusive lower bound, exclusive upper bound)
48-
let low = if prefix == 0 { 0 } else { fanout[prefix - 1] } as i64;
49-
let high = fanout[prefix] as i64;
87+
let low = if prefix == 0 { 0 } else { self.fanout[prefix - 1] } as i64;
88+
let high = self.fanout[prefix] as i64;
5089

51-
r.seek(SeekFrom::Current(low * BIT_HASH_SIZE as i64))?;
52-
let oids = r.read_vec((high - low) as usize)?;
90+
self.seek(SeekFrom::Current(low * BIT_HASH_SIZE as i64))?;
91+
let oids = self.reader.read_vec((high - low) as usize)?;
5392
match oids.binary_search(&oid) {
5493
Ok(idx) => Ok(low as usize + idx),
5594
Err(..) => Err(anyhow!("oid `{}` not found in packindex", oid)),
5695
}
5796
}
5897
}
5998

99+
impl<'r, R> Deref for PackIndexReader<'r, R> {
100+
type Target = R;
101+
102+
fn deref(&self) -> &Self::Target {
103+
&self.reader
104+
}
105+
}
106+
107+
impl<'r, R> DerefMut for PackIndexReader<'r, R> {
108+
fn deref_mut(&mut self) -> &mut Self::Target {
109+
&mut self.reader
110+
}
111+
}
112+
60113
impl Deserialize for PackIndex {
61114
fn deserialize(reader: &mut dyn BufRead) -> BitResult<Self>
62115
where

src/libbit/src/pack/tests.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ fn test_deserialize_pack_idx_is_ok() -> BitResult<()> {
1515
#[test]
1616
fn test_pack_idx_find_oid_start() -> BitResult<()> {
1717
let mut cursor = Cursor::new(include_bytes!("../../tests/files/pack.idx"));
18-
let pack_idx = PackIndex::find_oid_index(
19-
&mut cursor,
18+
let pack_idx = PackIndexReader::new(&mut cursor)?.find_oid_index(
2019
// this hash is the first oid in sorted list
2120
BitHash::from_str("0004a3cf85dbcbfbef916599145a0c370bb78cf5").unwrap(),
2221
)?;
@@ -26,8 +25,7 @@ fn test_pack_idx_find_oid_start() -> BitResult<()> {
2625
#[test]
2726
fn test_pack_idx_find_oid_end() -> BitResult<()> {
2827
let mut cursor = Cursor::new(include_bytes!("../../tests/files/pack.idx"));
29-
let pack_idx = PackIndex::find_oid_index(
30-
&mut cursor,
28+
let pack_idx = PackIndexReader::new(&mut cursor)?.find_oid_index(
3129
// this hash is the last oid in sorted list
3230
BitHash::from_str("fffc6e8cf5f6798732a6031ebf24d2f6aaa60e47").unwrap(),
3331
)?;

0 commit comments

Comments
 (0)