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 | } | ||