]> git.proxmox.com Git - rustc.git/blob - vendor/gix-object/src/commit/message/decode.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / vendor / gix-object / src / commit / message / decode.rs
1 use winnow::{
2 combinator::{alt, eof, preceded, rest, terminated},
3 error::ParserError,
4 prelude::*,
5 stream::{Offset, Stream},
6 token::take_till1,
7 };
8
9 use crate::bstr::{BStr, ByteSlice};
10
11 pub(crate) fn newline<'a, E: ParserError<&'a [u8]>>(i: &mut &'a [u8]) -> PResult<&'a [u8], E> {
12 alt((b"\n", b"\r\n")).parse_next(i)
13 }
14
15 fn subject_and_body<'a, E: ParserError<&'a [u8]>>(i: &mut &'a [u8]) -> PResult<(&'a BStr, Option<&'a BStr>), E> {
16 let start_i = *i;
17 let start = i.checkpoint();
18 while !i.is_empty() {
19 match take_till1::<_, _, E>(|c| c == b'\n' || c == b'\r').parse_next(i) {
20 Ok(_) => {
21 let consumed_bytes = i.offset_from(&start);
22 match preceded((newline::<E>, newline::<E>), rest).parse_next(i) {
23 Ok(body) => {
24 let body = (!body.is_empty()).then(|| body.as_bstr());
25 return Ok((start_i[0usize..consumed_bytes].as_bstr(), body));
26 }
27 Err(_) => match i.next_token() {
28 Some(_) => {}
29 None => break,
30 },
31 }
32 }
33 Err(_) => match i.next_token() {
34 Some(_) => {}
35 None => break,
36 },
37 }
38 }
39
40 i.reset(start);
41 rest.map(|r: &[u8]| (r.as_bstr(), None)).parse_next(i)
42 }
43
44 /// Returns title and body, without separator
45 pub fn message(mut input: &[u8]) -> (&BStr, Option<&BStr>) {
46 terminated(subject_and_body::<()>, eof)
47 .parse_next(&mut input)
48 .expect("cannot fail")
49 }