1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
use bstr::{BStr, BString, ByteVec};
use winnow::{
combinator::{preceded, repeat, terminated},
error::{AddContext, ParserError, StrContext},
prelude::*,
token::{take_till1, take_until0, take_while},
Parser,
};
use crate::ByteSlice;
pub(crate) const NL: &[u8] = b"\n";
pub(crate) const SPACE: &[u8] = b" ";
const SPACE_OR_NL: &[u8] = b" \n";
pub(crate) fn any_header_field_multi_line<'a, E: ParserError<&'a [u8]> + AddContext<&'a [u8], StrContext>>(
i: &mut &'a [u8],
) -> PResult<(&'a [u8], BString), E> {
(
terminated(take_till1(SPACE_OR_NL), SPACE),
(
take_till1(NL),
NL,
repeat(1.., terminated((SPACE, take_until0(NL)), NL)).map(|()| ()),
)
.recognize()
.map(|o: &[u8]| {
let bytes = o.as_bstr();
let mut out = BString::from(Vec::with_capacity(bytes.len()));
let mut lines = bytes.lines();
out.push_str(lines.next().expect("first line"));
for line in lines {
out.push(b'\n');
out.push_str(&line[1..]); // cut leading space
}
out
}),
)
.context(StrContext::Expected("name <multi-line-value>".into()))
.parse_next(i)
}
pub(crate) fn header_field<'a, T, E: ParserError<&'a [u8]>>(
i: &mut &'a [u8],
name: &'static [u8],
parse_value: impl Parser<&'a [u8], T, E>,
) -> PResult<T, E> {
terminated(preceded(terminated(name, SPACE), parse_value), NL).parse_next(i)
}
pub(crate) fn any_header_field<'a, T, E: ParserError<&'a [u8]>>(
i: &mut &'a [u8],
parse_value: impl Parser<&'a [u8], T, E>,
) -> PResult<(&'a [u8], T), E> {
terminated((terminated(take_till1(SPACE_OR_NL), SPACE), parse_value), NL).parse_next(i)
}
fn is_hex_digit_lc(b: u8) -> bool {
matches!(b, b'0'..=b'9' | b'a'..=b'f')
}
pub fn hex_hash<'a, E: ParserError<&'a [u8]>>(i: &mut &'a [u8]) -> PResult<&'a BStr, E> {
take_while(
gix_hash::Kind::shortest().len_in_hex()..=gix_hash::Kind::longest().len_in_hex(),
is_hex_digit_lc,
)
.map(ByteSlice::as_bstr)
.parse_next(i)
}
pub(crate) fn signature<'a, E: ParserError<&'a [u8]> + AddContext<&'a [u8], StrContext>>(
i: &mut &'a [u8],
) -> PResult<gix_actor::SignatureRef<'a>, E> {
gix_actor::signature::decode(i)
}
|