History

[object #177] migrate immutable::commit into crate::commit

Sebastian Thiel committed 5 years ago

Commit 45d39341 parent 7f1955911 files · +75 −67Browse files

Showing the changes to git-object/src/commit/decode.rs (1 of 11 files). Show all

Unified · Split

git-object/src/commit/decode.rs+74−0
@@ -0,0 +1,74 @@
1+use std::borrow::Cow;
2+
3+use nom::{
4+ branch::alt,
5+ bytes::complete::{is_not, tag},
6+ combinator::{all_consuming, opt},
7+ error::{context, ContextError, ParseError},
8+ multi::many0,
9+ IResult,
10+};
11+use smallvec::SmallVec;
12+
13+use crate::{
14+ immutable::{parse, parse::NL},
15+ BStr, ByteSlice, CommitRef,
16+};
17+
18+pub fn message<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], &'a BStr, E> {
19+ if i.is_empty() {
20+ // newline + [message]
21+ return Err(nom::Err::Error(E::add_context(
22+ i,
23+ "newline + <message>",
24+ E::from_error_kind(i, nom::error::ErrorKind::Eof),
25+ )));
26+ }
27+ let (i, _) = context("a newline separates headers from the message", tag(NL))(i)?;
28+ Ok((&[], i.as_bstr()))
29+}
30+
31+pub fn commit<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
32+ i: &'a [u8],
33+) -> IResult<&'a [u8], CommitRef<'_>, E> {
34+ let (i, tree) = context("tree <40 lowercase hex char>", |i| {
35+ parse::header_field(i, b"tree", parse::hex_hash)
36+ })(i)?;
37+ let (i, parents) = context(
38+ "zero or more 'parent <40 lowercase hex char>'",
39+ many0(|i| parse::header_field(i, b"parent", parse::hex_hash)),
40+ )(i)?;
41+ let (i, author) = context("author <signature>", |i| {
42+ parse::header_field(i, b"author", parse::signature)
43+ })(i)?;
44+ let (i, committer) = context("committer <signature>", |i| {
45+ parse::header_field(i, b"committer", parse::signature)
46+ })(i)?;
47+ let (i, encoding) = context(
48+ "encoding <encoding>",
49+ opt(|i| parse::header_field(i, b"encoding", is_not(NL))),
50+ )(i)?;
51+ let (i, extra_headers) = context(
52+ "<field> <single-line|multi-line>",
53+ many0(alt((
54+ |i| parse::any_header_field_multi_line(i).map(|(i, (k, o))| (i, (k.as_bstr(), Cow::Owned(o)))),
55+ |i| {
56+ parse::any_header_field(i, is_not(NL)).map(|(i, (k, o))| (i, (k.as_bstr(), Cow::Borrowed(o.as_bstr()))))
57+ },
58+ ))),
59+ )(i)?;
60+ let (i, message) = all_consuming(message)(i)?;
61+
62+ Ok((
63+ i,
64+ CommitRef {
65+ tree,
66+ parents: SmallVec::from(parents),
67+ author,
68+ committer,
69+ encoding: encoding.map(ByteSlice::as_bstr),
70+ message,
71+ extra_headers,
72+ },
73+ ))
74+}