use imap_types::{
core::NonEmptyVec,
sequence::{SeqNo, Sequence, SequenceSet},
};
use nom::{
branch::alt,
bytes::streaming::tag,
combinator::{map, value},
multi::separated_list1,
sequence::tuple,
IResult,
};
use crate::rfc3501::core::nz_number;
pub fn sequence_set(input: &[u8]) -> IResult<&[u8], SequenceSet> {
map(
separated_list1(
tag(b","),
alt((
map(seq_range, |(from, to)| Sequence::Range(from, to)),
map(seq_number, Sequence::Single),
)),
),
|set| SequenceSet(unsafe { NonEmptyVec::new_unchecked(set) }),
)(input)
}
pub fn seq_range(input: &[u8]) -> IResult<&[u8], (SeqNo, SeqNo)> {
let mut parser = tuple((seq_number, tag(b":"), seq_number));
let (remaining, (from, _, to)) = parser(input)?;
Ok((remaining, (from, to)))
}
pub fn seq_number(input: &[u8]) -> IResult<&[u8], SeqNo> {
alt((
map(nz_number, SeqNo::Value),
value(SeqNo::Largest, tag(b"*")),
))(input)
}
#[cfg(test)]
mod test {
use std::convert::TryInto;
use super::*;
#[test]
fn test_sequence_set() {
let (rem, val) = sequence_set(b"1:*?").unwrap();
println!("{:?}, {:?}", rem, val);
let (rem, val) = sequence_set(b"1:*,5?").unwrap();
println!("{:?}, {:?}", rem, val);
}
#[test]
fn test_seq_number() {
assert!(seq_number(b"0?").is_err());
let (rem, val) = seq_number(b"1?").unwrap();
println!("{:?}, {:?}", rem, val);
let (rem, val) = seq_number(b"*?").unwrap();
println!("{:?}, {:?}", rem, val);
}
#[test]
fn test_seq_range() {
assert!(seq_range(b"0:1?").is_err());
assert_eq!(
(
SeqNo::Value(1.try_into().unwrap()),
SeqNo::Value(2.try_into().unwrap())
),
seq_range(b"1:2?").unwrap().1
);
assert_eq!(
(SeqNo::Value(1.try_into().unwrap()), SeqNo::Largest),
seq_range(b"1:*?").unwrap().1
);
assert_eq!(
(SeqNo::Largest, SeqNo::Value(10.try_into().unwrap())),
seq_range(b"*:10?").unwrap().1
);
}
}