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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
use std::num::NonZeroU32;
use abnf_core::streaming::SP;
use nom::{
branch::alt,
bytes::streaming::{tag, tag_no_case},
combinator::{map, opt},
multi::separated_list1,
sequence::{delimited, terminated, tuple},
IResult,
};
use crate::{
parse::{
body::body,
core::{nstring, number, nz_number},
datetime::date_time,
envelope::envelope,
flag::flag_fetch,
section::section,
},
types::response::{Data, MessageAttribute},
};
pub(crate) fn message_data(input: &[u8]) -> IResult<&[u8], Data> {
let (remaining, seq_or_uid) = terminated(nz_number, SP)(input)?;
alt((
map(tag_no_case(b"EXPUNGE"), move |_| Data::Expunge(seq_or_uid)),
map(
tuple((tag_no_case(b"FETCH"), SP, msg_att)),
move |(_, _, attributes)| Data::Fetch {
seq_or_uid,
attributes,
},
),
))(remaining)
}
fn msg_att(input: &[u8]) -> IResult<&[u8], Vec<MessageAttribute>> {
delimited(
tag(b"("),
separated_list1(SP, alt((msg_att_dynamic, msg_att_static))),
tag(b")"),
)(input)
}
fn msg_att_dynamic(input: &[u8]) -> IResult<&[u8], MessageAttribute> {
let mut parser = tuple((
tag_no_case(b"FLAGS"),
SP,
delimited(tag(b"("), opt(separated_list1(SP, flag_fetch)), tag(b")")),
));
let (remaining, (_, _, flags)) = parser(input)?;
Ok((
remaining,
MessageAttribute::Flags(flags.unwrap_or_default()),
))
}
fn msg_att_static(input: &[u8]) -> IResult<&[u8], MessageAttribute> {
alt((
map(
tuple((tag_no_case(b"ENVELOPE"), SP, envelope)),
|(_, _, envelope)| MessageAttribute::Envelope(envelope),
),
map(
tuple((tag_no_case(b"INTERNALDATE"), SP, date_time)),
|(_, _, date_time)| MessageAttribute::InternalDate(date_time),
),
alt((
map(
tuple((tag_no_case(b"RFC822.HEADER"), SP, nstring)),
|(_, _, nstring)| MessageAttribute::Rfc822Header(nstring.to_owned()),
),
map(
tuple((tag_no_case(b"RFC822.TEXT"), SP, nstring)),
|(_, _, nstring)| MessageAttribute::Rfc822Text(nstring.to_owned()),
),
map(
tuple((tag_no_case(b"RFC822"), SP, nstring)),
|(_, _, nstring)| MessageAttribute::Rfc822(nstring.to_owned()),
),
)),
map(
tuple((tag_no_case(b"RFC822.SIZE"), SP, number)),
|(_, _, num)| MessageAttribute::Rfc822Size(num),
),
alt((
map(
tuple((tag_no_case(b"BODYSTRUCTURE"), SP, body(8))),
|(_, _, body)| MessageAttribute::BodyStructure(body),
),
map(
tuple((tag_no_case(b"BODY"), SP, body(8))),
|(_, _, body)| MessageAttribute::Body(body),
),
)),
map(
tuple((
tag_no_case(b"BODY"),
section,
opt(delimited(tag(b"<"), number, tag(b">"))),
SP,
nstring,
)),
|(_, section, origin, _, data)| MessageAttribute::BodyExt {
section,
origin,
data: data.to_owned(),
},
),
map(tuple((tag_no_case(b"UID"), SP, uniqueid)), |(_, _, uid)| {
MessageAttribute::Uid(uid)
}),
))(input)
}
#[inline]
fn uniqueid(input: &[u8]) -> IResult<&[u8], NonZeroU32> {
nz_number(input)
}