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}