use std::borrow::Cow;
use smallvec::SmallVec;
use crate::{parse, parse::ParseResult, BStr, ByteSlice, CommitRef};
pub fn message<'a>(i: &mut &'a [u8]) -> ParseResult<&'a BStr> {
if let Some(rest) = i.strip_prefix(parse::NL) {
*i = &[];
Ok(rest.as_bstr())
} else {
Err(crate::decode::Error)
}
}
pub fn commit<'a>(i: &mut &'a [u8], hash_kind: gix_hash::Kind) -> ParseResult<CommitRef<'a>> {
let tree = parse::header_field(i, b"tree", |value| parse::hex_hash(value, hash_kind))?;
let mut parents = SmallVec::new();
loop {
let before = *i;
match parse::header_field(i, b"parent", |value| parse::hex_hash(value, hash_kind)) {
Ok(parent) => parents.push(parent),
Err(_) => {
*i = before;
break;
}
}
}
let author = parse::header_field(i, b"author", parse::signature_raw)?;
let committer = parse::header_field(i, b"committer", parse::signature_raw)?;
let before = *i;
let encoding = match parse::header_field(i, b"encoding", Ok) {
Ok(encoding) => Some(encoding.as_bstr()),
Err(_) => {
*i = before;
None
}
};
let mut extra_headers = Vec::new();
loop {
let before = *i;
match parse::any_header_field_multi_line(i)
.map(|(k, v)| (k.as_bstr(), Cow::Owned(v)))
.or_else(|_| {
*i = before;
parse::any_header_field(i).map(|(k, v)| (k.as_bstr(), Cow::Borrowed(v.as_bstr())))
}) {
Ok(header) => extra_headers.push(header),
Err(_) => {
*i = before;
break;
}
}
}
let message = message(i)?;
if !i.is_empty() {
return Err(crate::decode::Error);
}
Ok(CommitRef {
tree,
parents,
author,
committer,
encoding,
message,
extra_headers,
})
}