Skip to content

Commit 5c731f8

Browse files
committed
parse index header (#293)
1 parent 4122306 commit 5c731f8

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

git-index/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ repository = "https://github.com/Byron/gitoxide"
55
license = "MIT/Apache-2.0"
66
description = "A WIP crate of the gitoxide project dedicated implementing the git index file"
77
authors = ["Sebastian Thiel <[email protected]>"]
8-
edition = "2018"
8+
edition = "2021"
99

1010
[lib]
1111
doctest = false

git-index/src/file.rs

+46-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
pub mod init {
22
#![allow(unused)]
3+
4+
use crate::file::decode;
35
use crate::{File, State};
46
use memmap2::Mmap;
57
use std::path::{Path, PathBuf};
68

79
mod error {
10+
use crate::file::decode;
811
use quick_error::quick_error;
912

1013
quick_error! {
@@ -15,6 +18,11 @@ pub mod init {
1518
source(err)
1619
from()
1720
}
21+
DecodeHeader(err: decode::header::Error) {
22+
display("The header could not be understood")
23+
source(err)
24+
from()
25+
}
1826
}
1927
}
2028
}
@@ -31,6 +39,8 @@ pub mod init {
3139
(data, filetime::FileTime::from_last_modification_time(&file.metadata()?))
3240
};
3341

42+
let (version, num_entries, data) = decode::header(&data)?;
43+
3444
Ok(File {
3545
state: State { timestamp: mtime },
3646
path,
@@ -40,25 +50,55 @@ pub mod init {
4050
}
4151

4252
pub mod decode {
53+
use crate::Version;
54+
4355
pub mod header {
4456
mod error {
4557
use quick_error::quick_error;
4658

4759
quick_error! {
4860
#[derive(Debug)]
4961
pub enum Error {
50-
Io(err: std::io::Error) {
51-
display("An IO error occurred while opening the index")
52-
source(err)
53-
from()
62+
Corrupt(message: &'static str) {
63+
display("{}", message)
64+
}
65+
UnsupportedVersion(version: u32) {
66+
display("Index version {} is not supported", version)
5467
}
5568
}
5669
}
5770
}
5871
pub use error::Error;
5972
}
6073

61-
fn header(data: &[u8]) -> Result<(crate::Version, &[u8]), header::Error> {
62-
todo!("header parsing")
74+
pub(crate) fn header(data: &[u8]) -> Result<(crate::Version, u32, &[u8]), header::Error> {
75+
if data.len() < 3 * 4 {
76+
return Err(header::Error::Corrupt("The header is truncated"));
77+
}
78+
79+
const SIGNATURE: &[u8] = b"DIRC";
80+
let (signature, data) = data.split_at(4);
81+
if signature != SIGNATURE {
82+
return Err(header::Error::Corrupt(
83+
"Signature mismatch - this doesn't claim to be a header file",
84+
));
85+
}
86+
87+
let (version, data) = data.split_at(4);
88+
let version = match read_u32(version) {
89+
2 => Version::V2,
90+
3 => Version::V3,
91+
4 => Version::V4,
92+
unknown => return Err(header::Error::UnsupportedVersion(unknown)),
93+
};
94+
let (entries, data) = data.split_at(4);
95+
let entries = read_u32(entries);
96+
97+
Ok((version, entries, data))
98+
}
99+
100+
#[inline]
101+
fn read_u32(b: &[u8]) -> u32 {
102+
u32::from_be_bytes(b.try_into().unwrap())
63103
}
64104
}

0 commit comments

Comments
 (0)