History

A manual message parse impl and more tests (#198)

Sebastian Thiel committed 5 years ago

Commit f4b8a0d1 parent 625be8d2 files · +31 −20Browse files

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

Unified · Split

git-object/src/commit/message.rs+17−19
@@ -6,25 +6,25 @@ use crate::{ · 5 unmodified lines
66 };
77
88 mod decode {
9− use nom::{
10− branch::alt,
11− bytes::complete::{tag, take_while},
12− combinator::map,
13− error::ParseError,
14− sequence::{pair, terminated},
15− IResult,
16− };
17−
189 use crate::bstr::{BStr, ByteSlice};
1910
20− pub fn newline<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> {
21− alt((tag(b"\r\n"), tag(b"\n")))(i)
22− }
2311 /// Returns title and body, without separator
24− pub fn bytes<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&[u8], &'a BStr, E> {
25− map(terminated(take_while(|c| c != b'\n'), pair(newline, newline)), |t| {
26− t.as_bstr()
27− })(i)
12+ pub fn bytes(i: &[u8]) -> (&BStr, Option<&BStr>) {
13+ let message = i;
14+ match message
15+ .find(b"\n\n")
16+ .map(|pos| (2, pos))
17+ .or_else(|| message.find(b"\r\n\r\n").map(|pos| (4, pos)))
18+ {
19+ Some((sep_len, end_of_title)) => {
20+ let body = &message[end_of_title + sep_len..];
21+ (
22+ &message[..end_of_title].as_bstr(),
23+ if body.is_empty() { None } else { Some(body.as_bstr()) },
24+ )
25+ }
26+ None => (message.as_bstr(), None),
27+ }
2828 }
2929 }
3030
@@ -33,9 +33,7 @@ impl<'a> MessageRef<'a> { · 2 unmodified lines
3333 ///
3434 /// Note that this cannot fail as everything will be interpreted as title if there is no body separator.
3535 pub fn from_bytes(input: &'a [u8]) -> Self {
36− let (title, body) = decode::bytes::<()>(input)
37− .map(|(body, title)| (title, Some(body.as_bstr())))
38− .unwrap_or_else(|_| (input.as_bstr(), None));
36+ let (title, body) = decode::bytes(input);
3937 MessageRef { title, body }
4038 }
4139 /// Produce a short commit summary for the message title.