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
//!
//! https://tools.ietf.org/html/rfc4315
//!
//! The IMAP UIDPLUS Extension
//!
use nom::{
branch::alt,
bytes::streaming::{tag, tag_no_case},
combinator::map,
multi::separated_list1,
sequence::{preceded, tuple},
IResult,
};
use crate::parser::core::number;
use crate::types::*;
/// Extends resp-text-code as follows:
///
/// ```ignore
/// resp-text-code =/ resp-code-apnd
/// resp-code-apnd = "APPENDUID" SP nz-number SP append-uid
/// append-uid =/ uid-set
/// ; only permitted if client uses [MULTIAPPEND]
/// ; to append multiple messages.
/// ```
///
/// [RFC4315 - 3 Additional Response Codes](https://tools.ietf.org/html/rfc4315#section-3)
pub(crate) fn resp_text_code_append_uid(i: &[u8]) -> IResult<&[u8], ResponseCode> {
map(
preceded(
tag_no_case(b"APPENDUID "),
tuple((number, tag(" "), uid_set)),
),
|(fst, _, snd)| ResponseCode::AppendUid(fst, snd),
)(i)
}
/// Extends resp-text-code as follows:
///
/// ```ignore
/// resp-text-code =/ resp-code-copy
/// resp-code-copy = "COPYUID" SP nz-number SP uid-set
/// ```
///
/// [RFC4315 - 3 Additional Response Codes](https://tools.ietf.org/html/rfc4315#section-3)
pub(crate) fn resp_text_code_copy_uid(i: &[u8]) -> IResult<&[u8], ResponseCode> {
map(
preceded(
tag_no_case(b"COPYUID "),
tuple((number, tag(" "), uid_set, tag(" "), uid_set)),
),
|(fst, _, snd, _, trd)| ResponseCode::CopyUid(fst, snd, trd),
)(i)
}
/// Extends resp-text-code as follows:
///
/// ```ignore
/// resp-text-code =/ "UIDNOTSTICKY"
/// ```
///
/// [RFC4315 - 3 Additional Response Codes](https://tools.ietf.org/html/rfc4315#section-3)
pub(crate) fn resp_text_code_uid_not_sticky(i: &[u8]) -> IResult<&[u8], ResponseCode> {
map(tag_no_case(b"UIDNOTSTICKY"), |_| ResponseCode::UidNotSticky)(i)
}
/// Parses the uid-set nonterminal:
///
/// ```ignore
/// uid-set = (uniqueid / uid-range) *("," uid-set)
/// ```
///
/// [RFC4315 - 4 Formal Syntax](https://tools.ietf.org/html/rfc4315#section-4)
fn uid_set(i: &[u8]) -> IResult<&[u8], Vec<UidSetMember>> {
separated_list1(tag(","), alt((uid_range, map(number, From::from))))(i)
}
/// Parses the uid-set nonterminal:
///
/// ```ignore
/// uid-range = (uniqueid ":" uniqueid)
/// ; two uniqueid values and all values
/// ; between these two regards of order.
/// ; Example: 2:4 and 4:2 are equivalent.
/// ```
///
/// [RFC4315 - 4 Formal Syntax](https://tools.ietf.org/html/rfc4315#section-4)
fn uid_range(i: &[u8]) -> IResult<&[u8], UidSetMember> {
map(
nom::sequence::separated_pair(number, tag(":"), number),
|(fst, snd)| if fst <= snd { fst..=snd } else { snd..=fst }.into(),
)(i)
}