Showing the changes to git-object/src/commit/decode.rs (1 of 11 files). Show all
Unified · Split
| @@ -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 | +} | |