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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use crate::parsing::combinator::rfc::rfc2234::wsp;
use crate::parsing::combinator::{ascii_char, one_or_more, zero_or_more};
use crate::parsing::ParsedItem;
pub(crate) fn fws(mut input: &[u8]) -> Option<ParsedItem<'_, ()>> {
if let [b'\r', b'\n', rest @ ..] = input {
one_or_more(wsp)(rest)
} else {
input = one_or_more(wsp)(input)?.into_inner();
while let [b'\r', b'\n', rest @ ..] = input {
input = one_or_more(wsp)(rest)?.into_inner();
}
Some(ParsedItem(input, ()))
}
}
pub(crate) fn cfws(input: &[u8]) -> Option<ParsedItem<'_, ()>> {
one_or_more(|input| fws(input).or_else(|| comment(input)))(input)
}
fn comment(mut input: &[u8]) -> Option<ParsedItem<'_, ()>> {
input = ascii_char::<b'('>(input)?.into_inner();
input = zero_or_more(fws)(input).into_inner();
while let Some(rest) = ccontent(input) {
input = rest.into_inner();
input = zero_or_more(fws)(input).into_inner();
}
input = ascii_char::<b')'>(input)?.into_inner();
Some(ParsedItem(input, ()))
}
fn ccontent(input: &[u8]) -> Option<ParsedItem<'_, ()>> {
ctext(input)
.or_else(|| quoted_pair(input))
.or_else(|| comment(input))
}
#[allow(clippy::unnecessary_lazy_evaluations)]
fn ctext(input: &[u8]) -> Option<ParsedItem<'_, ()>> {
no_ws_ctl(input).or_else(|| match input {
[33..=39 | 42..=91 | 93..=126, rest @ ..] => Some(ParsedItem(rest, ())),
_ => None,
})
}
fn quoted_pair(mut input: &[u8]) -> Option<ParsedItem<'_, ()>> {
input = ascii_char::<b'\\'>(input)?.into_inner();
let old_input_len = input.len();
input = text(input).into_inner();
if input.len() == old_input_len {
match input {
[0..=127, rest @ ..] => Some(ParsedItem(rest, ())),
_ => Some(ParsedItem(input, ())),
}
} else {
Some(ParsedItem(input, ()))
}
}
const fn no_ws_ctl(input: &[u8]) -> Option<ParsedItem<'_, ()>> {
match input {
[1..=8 | 11..=12 | 14..=31 | 127, rest @ ..] => Some(ParsedItem(rest, ())),
_ => None,
}
}
fn text<'a>(input: &'a [u8]) -> ParsedItem<'a, ()> {
let new_text = |input: &'a [u8]| match input {
[1..=9 | 11..=12 | 14..=127, rest @ ..] => Some(ParsedItem(rest, ())),
_ => None,
};
let obs_char = |input: &'a [u8]| match input {
[b')', ..] => None,
[0..=9 | 11..=12 | 14..=127, rest @ ..] => Some(rest),
_ => None,
};
let obs_text = |mut input| {
input = zero_or_more(ascii_char::<b'\n'>)(input).into_inner();
input = zero_or_more(ascii_char::<b'\r'>)(input).into_inner();
while let Some(rest) = obs_char(input) {
input = rest;
input = zero_or_more(ascii_char::<b'\n'>)(input).into_inner();
input = zero_or_more(ascii_char::<b'\r'>)(input).into_inner();
}
ParsedItem(input, ())
};
new_text(input).unwrap_or_else(|| obs_text(input))
}