use gix_object::bstr::{BStr, ByteSlice};
use crate::{parse, store_impl::packed};
#[derive(Debug, PartialEq, Eq)]
enum Peeled {
Unspecified,
Partial,
Fully,
}
#[derive(Debug, PartialEq, Eq)]
pub struct Header {
peeled: Peeled,
pub sorted: bool,
}
impl Default for Header {
fn default() -> Self {
Header {
peeled: Peeled::Unspecified,
sorted: false,
}
}
}
fn until_line_end_without_separator<'a>(input: &mut &'a [u8]) -> Result<&'a BStr, ()> {
let line_end = input.iter().position(|b| *b == b'\r' || *b == b'\n').ok_or(())?;
let out = input[..line_end].as_bstr();
let mut maybe_start_of_newline = &input[line_end..];
parse::newline(&mut maybe_start_of_newline)?;
*input = maybe_start_of_newline;
Ok(out)
}
pub fn header(input: &mut &[u8]) -> Result<Header, ()> {
let Some(rest) = input.strip_prefix(b"# pack-refs with: ") else {
return Err(());
};
*input = rest;
let traits = until_line_end_without_separator(input)?;
let mut peeled = Peeled::Unspecified;
let mut sorted = false;
for token in traits.split_str(b" ") {
if token == b"fully-peeled" {
peeled = Peeled::Fully;
} else if token == b"peeled" {
peeled = Peeled::Partial;
} else if token == b"sorted" {
sorted = true;
}
}
Ok(Header { peeled, sorted })
}
pub fn reference<'a>(input: &mut &'a [u8], hash_kind: gix_hash::Kind) -> Result<packed::Reference<'a>, ()> {
let target = parse::hex_hash(input, hash_kind)?;
let Some(rest) = input.strip_prefix(b" ") else {
return Err(());
};
*input = rest;
let name = until_line_end_without_separator(input)?.try_into().map_err(|_| ())?;
let object = if let Some(rest) = input.strip_prefix(b"^") {
*input = rest;
let object = parse::hex_hash(input, hash_kind)?;
parse::newline(input)?;
Some(object)
} else {
None
};
Ok(packed::Reference { name, target, object })
}
#[cfg(test)]
mod tests;