diff options
Diffstat (limited to 'vendor/gix-object/src/commit/decode.rs')
-rw-r--r-- | vendor/gix-object/src/commit/decode.rs | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/vendor/gix-object/src/commit/decode.rs b/vendor/gix-object/src/commit/decode.rs new file mode 100644 index 000000000..821feaabb --- /dev/null +++ b/vendor/gix-object/src/commit/decode.rs @@ -0,0 +1,71 @@ +use std::borrow::Cow; + +use nom::{ + branch::alt, + bytes::complete::{is_not, tag}, + combinator::{all_consuming, opt}, + error::{context, ContextError, ParseError}, + multi::many0, + IResult, Parser, +}; +use smallvec::SmallVec; + +use crate::{parse, parse::NL, BStr, ByteSlice, CommitRef}; + +pub fn message<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], &'a BStr, E> { + if i.is_empty() { + // newline + [message] + return Err(nom::Err::Error(E::add_context( + i, + "newline + <message>", + E::from_error_kind(i, nom::error::ErrorKind::Eof), + ))); + } + let (i, _) = context("a newline separates headers from the message", tag(NL))(i)?; + Ok((&[], i.as_bstr())) +} + +pub fn commit<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>( + i: &'a [u8], +) -> IResult<&'a [u8], CommitRef<'_>, E> { + let (i, tree) = context("tree <40 lowercase hex char>", |i| { + parse::header_field(i, b"tree", parse::hex_hash) + })(i)?; + let (i, parents) = context( + "zero or more 'parent <40 lowercase hex char>'", + many0(|i| parse::header_field(i, b"parent", parse::hex_hash)), + )(i)?; + let (i, author) = context("author <signature>", |i| { + parse::header_field(i, b"author", parse::signature) + })(i)?; + let (i, committer) = context("committer <signature>", |i| { + parse::header_field(i, b"committer", parse::signature) + })(i)?; + let (i, encoding) = context( + "encoding <encoding>", + opt(|i| parse::header_field(i, b"encoding", is_not(NL))), + )(i)?; + let (i, extra_headers) = context( + "<field> <single-line|multi-line>", + many0(alt(( + parse::any_header_field_multi_line.map(|(k, o)| (k.as_bstr(), Cow::Owned(o))), + |i| { + parse::any_header_field(i, is_not(NL)).map(|(i, (k, o))| (i, (k.as_bstr(), Cow::Borrowed(o.as_bstr())))) + }, + ))), + )(i)?; + let (i, message) = all_consuming(message)(i)?; + + Ok(( + i, + CommitRef { + tree, + parents: SmallVec::from(parents), + author, + committer, + encoding: encoding.map(ByteSlice::as_bstr), + message, + extra_headers, + }, + )) +} |