Showing the changes to git-object/src/commit/message/decode.rs (1 of 4 files). Show all
Unified · Split
| @@ -0,0 +1,57 @@ | |||
| 1 | use nom::{ | ||
| 2 | branch::alt, | ||
| 3 | bytes::complete::{tag, take_till1}, | ||
| 4 | combinator::all_consuming, | ||
| 5 | error::ParseError, | ||
| 6 | sequence::pair, | ||
| 7 | IResult, | ||
| 8 | }; | ||
| 9 | |||
| 10 | use crate::bstr::{BStr, ByteSlice}; | ||
| 11 | |||
| 12 | pub(crate) fn newline<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> { | ||
| 13 | alt((tag(b"\r\n"), tag(b"\n")))(i) | ||
| 14 | } | ||
| 15 | |||
| 16 | fn subject_and_body<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], (&'a BStr, Option<&'a BStr>), E> { | ||
| 17 | let mut c = i; | ||
| 18 | let mut consumed_bytes = 0; | ||
| 19 | while !c.is_empty() { | ||
| 20 | c = match take_till1::<_, _, E>(|c| c == b'\n' || c == b'\r')(c) { | ||
| 21 | Ok((i1, segment)) => { | ||
| 22 | consumed_bytes += segment.len(); | ||
| 23 | match pair::<_, _, _, E, _, _>(newline, newline)(i1) { | ||
| 24 | Ok((body, _)) => { | ||
| 25 | return Ok(( | ||
| 26 | &[], | ||
| 27 | ( | ||
| 28 | i[0usize..consumed_bytes].as_bstr(), | ||
| 29 | (!body.is_empty()).then(|| body.as_bstr()), | ||
| 30 | ), | ||
| 31 | )); | ||
| 32 | } | ||
| 33 | Err(_) => match i1.get(1..) { | ||
| 34 | Some(next) => { | ||
| 35 | consumed_bytes += 1; | ||
| 36 | next | ||
| 37 | } | ||
| 38 | None => break, | ||
| 39 | }, | ||
| 40 | } | ||
| 41 | } | ||
| 42 | Err(_) => match c.get(1..) { | ||
| 43 | Some(next) => { | ||
| 44 | consumed_bytes += 1; | ||
| 45 | next | ||
| 46 | } | ||
| 47 | None => break, | ||
| 48 | }, | ||
| 49 | }; | ||
| 50 | } | ||
| 51 | Ok((&[], (i.as_bstr(), None))) | ||
| 52 | } | ||
| 53 | |||
| 54 | /// Returns title and body, without separator | ||
| 55 | pub fn message(input: &[u8]) -> (&BStr, Option<&BStr>) { | ||
| 56 | all_consuming(subject_and_body::<()>)(input).expect("cannot fail").1 | ||
| 57 | } | ||