time/parsing/combinator/rfc/
rfc2822.rs1use crate::parsing::combinator::rfc::rfc2234::wsp;
6use crate::parsing::combinator::{ascii_char, one_or_more, zero_or_more};
7use crate::parsing::ParsedItem;
8
9pub(crate) fn fws(mut input: &[u8]) -> Option<ParsedItem<'_, ()>> {
12 if let [b'\r', b'\n', rest @ ..] = input {
13 one_or_more(wsp)(rest)
14 } else {
15 input = one_or_more(wsp)(input)?.into_inner();
16 while let [b'\r', b'\n', rest @ ..] = input {
17 input = one_or_more(wsp)(rest)?.into_inner();
18 }
19 Some(ParsedItem(input, ()))
20 }
21}
22
23pub(crate) fn cfws(input: &[u8]) -> Option<ParsedItem<'_, ()>> {
26 one_or_more(|input| fws(input).or_else(|| comment(input)))(input)
27}
28
29fn comment(mut input: &[u8]) -> Option<ParsedItem<'_, ()>> {
31 input = ascii_char::<b'('>(input)?.into_inner();
32 input = zero_or_more(fws)(input).into_inner();
33 while let Some(rest) = ccontent(input) {
34 input = rest.into_inner();
35 input = zero_or_more(fws)(input).into_inner();
36 }
37 input = ascii_char::<b')'>(input)?.into_inner();
38
39 Some(ParsedItem(input, ()))
40}
41
42fn ccontent(input: &[u8]) -> Option<ParsedItem<'_, ()>> {
44 ctext(input)
45 .or_else(|| quoted_pair(input))
46 .or_else(|| comment(input))
47}
48
49#[allow(clippy::unnecessary_lazy_evaluations)] fn ctext(input: &[u8]) -> Option<ParsedItem<'_, ()>> {
52 no_ws_ctl(input).or_else(|| match input {
53 [33..=39 | 42..=91 | 93..=126, rest @ ..] => Some(ParsedItem(rest, ())),
54 _ => None,
55 })
56}
57
58fn quoted_pair(mut input: &[u8]) -> Option<ParsedItem<'_, ()>> {
60 input = ascii_char::<b'\\'>(input)?.into_inner();
61 input = text(input).into_inner();
62
63 Some(ParsedItem(input, ()))
70}
71
72const fn no_ws_ctl(input: &[u8]) -> Option<ParsedItem<'_, ()>> {
74 match input {
75 [1..=8 | 11..=12 | 14..=31 | 127, rest @ ..] => Some(ParsedItem(rest, ())),
76 _ => None,
77 }
78}
79
80fn text<'a>(input: &'a [u8]) -> ParsedItem<'a, ()> {
82 let new_text = |input: &'a [u8]| match input {
83 [1..=9 | 11..=12 | 14..=127, rest @ ..] => Some(ParsedItem(rest, ())),
84 _ => None,
85 };
86
87 let obs_char = |input: &'a [u8]| match input {
88 [b')', ..] => None,
91 [0..=9 | 11..=12 | 14..=127, rest @ ..] => Some(rest),
92 _ => None,
93 };
94
95 let obs_text = |mut input| {
96 input = zero_or_more(ascii_char::<b'\n'>)(input).into_inner();
97 input = zero_or_more(ascii_char::<b'\r'>)(input).into_inner();
98 while let Some(rest) = obs_char(input) {
99 input = rest;
100 input = zero_or_more(ascii_char::<b'\n'>)(input).into_inner();
101 input = zero_or_more(ascii_char::<b'\r'>)(input).into_inner();
102 }
103
104 ParsedItem(input, ())
105 };
106
107 new_text(input).unwrap_or_else(|| obs_text(input))
108}