imap_proto/parser/rfc4315.rs
1//!
2//! https://tools.ietf.org/html/rfc4315
3//!
4//! The IMAP UIDPLUS Extension
5//!
6
7use nom::{
8 branch::alt,
9 bytes::streaming::{tag, tag_no_case},
10 combinator::map,
11 multi::separated_list1,
12 sequence::{preceded, tuple},
13 IResult,
14};
15
16use crate::parser::core::number;
17use crate::types::*;
18
19/// Extends resp-text-code as follows:
20///
21/// ```ignore
22/// resp-text-code =/ resp-code-apnd
23/// resp-code-apnd = "APPENDUID" SP nz-number SP append-uid
24/// append-uid =/ uid-set
25/// ; only permitted if client uses [MULTIAPPEND]
26/// ; to append multiple messages.
27/// ```
28///
29/// [RFC4315 - 3 Additional Response Codes](https://tools.ietf.org/html/rfc4315#section-3)
30pub(crate) fn resp_text_code_append_uid(i: &[u8]) -> IResult<&[u8], ResponseCode> {
31 map(
32 preceded(
33 tag_no_case(b"APPENDUID "),
34 tuple((number, tag(" "), uid_set)),
35 ),
36 |(fst, _, snd)| ResponseCode::AppendUid(fst, snd),
37 )(i)
38}
39
40/// Extends resp-text-code as follows:
41///
42/// ```ignore
43/// resp-text-code =/ resp-code-copy
44/// resp-code-copy = "COPYUID" SP nz-number SP uid-set
45/// ```
46///
47/// [RFC4315 - 3 Additional Response Codes](https://tools.ietf.org/html/rfc4315#section-3)
48pub(crate) fn resp_text_code_copy_uid(i: &[u8]) -> IResult<&[u8], ResponseCode> {
49 map(
50 preceded(
51 tag_no_case(b"COPYUID "),
52 tuple((number, tag(" "), uid_set, tag(" "), uid_set)),
53 ),
54 |(fst, _, snd, _, trd)| ResponseCode::CopyUid(fst, snd, trd),
55 )(i)
56}
57
58/// Extends resp-text-code as follows:
59///
60/// ```ignore
61/// resp-text-code =/ "UIDNOTSTICKY"
62/// ```
63///
64/// [RFC4315 - 3 Additional Response Codes](https://tools.ietf.org/html/rfc4315#section-3)
65pub(crate) fn resp_text_code_uid_not_sticky(i: &[u8]) -> IResult<&[u8], ResponseCode> {
66 map(tag_no_case(b"UIDNOTSTICKY"), |_| ResponseCode::UidNotSticky)(i)
67}
68
69/// Parses the uid-set nonterminal:
70///
71/// ```ignore
72/// uid-set = (uniqueid / uid-range) *("," uid-set)
73/// ```
74///
75/// [RFC4315 - 4 Formal Syntax](https://tools.ietf.org/html/rfc4315#section-4)
76fn uid_set(i: &[u8]) -> IResult<&[u8], Vec<UidSetMember>> {
77 separated_list1(tag(","), alt((uid_range, map(number, From::from))))(i)
78}
79
80/// Parses the uid-set nonterminal:
81///
82/// ```ignore
83/// uid-range = (uniqueid ":" uniqueid)
84/// ; two uniqueid values and all values
85/// ; between these two regards of order.
86/// ; Example: 2:4 and 4:2 are equivalent.
87/// ```
88///
89/// [RFC4315 - 4 Formal Syntax](https://tools.ietf.org/html/rfc4315#section-4)
90fn uid_range(i: &[u8]) -> IResult<&[u8], UidSetMember> {
91 map(
92 nom::sequence::separated_pair(number, tag(":"), number),
93 |(fst, snd)| if fst <= snd { fst..=snd } else { snd..=fst }.into(),
94 )(i)
95}