use super::{Seq, Uid};
use std::ops::RangeInclusive;
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct Deleted {
pub messages: DeletedMessages,
pub mod_seq: Option<u64>,
}
#[derive(Debug, Clone)]
pub enum DeletedMessages {
Expunged(Vec<Seq>),
Vanished(Vec<RangeInclusive<Uid>>),
}
impl Deleted {
pub fn from_expunged(v: Vec<u32>, mod_seq: Option<u64>) -> Self {
Self {
messages: DeletedMessages::Expunged(v),
mod_seq,
}
}
pub fn from_vanished(v: Vec<RangeInclusive<u32>>, mod_seq: Option<u64>) -> Self {
Self {
messages: DeletedMessages::Vanished(v),
mod_seq,
}
}
pub fn seqs(&self) -> impl Iterator<Item = Seq> + '_ {
match &self.messages {
DeletedMessages::Expunged(s) => s.iter(),
DeletedMessages::Vanished(_) => [].iter(),
}
.copied()
}
pub fn uids(&self) -> impl Iterator<Item = Uid> + '_ {
match &self.messages {
DeletedMessages::Expunged(_) => [].iter(),
DeletedMessages::Vanished(s) => s.iter(),
}
.flat_map(|range| range.clone())
}
pub fn is_empty(&self) -> bool {
match &self.messages {
DeletedMessages::Expunged(v) => v.is_empty(),
DeletedMessages::Vanished(v) => v.is_empty(),
}
}
}
impl<'a> IntoIterator for &'a Deleted {
type Item = u32;
type IntoIter = Box<dyn Iterator<Item = u32> + 'a>;
fn into_iter(self) -> Self::IntoIter {
match &self.messages {
DeletedMessages::Expunged(_) => Box::new(self.seqs()),
DeletedMessages::Vanished(_) => Box::new(self.uids()),
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn seq() {
let seqs = Deleted::from_expunged(vec![3, 6, 9, 12], None);
let mut i = seqs.into_iter();
assert_eq!(Some(3), i.next());
assert_eq!(Some(6), i.next());
assert_eq!(Some(9), i.next());
assert_eq!(Some(12), i.next());
assert_eq!(None, i.next());
let seqs = Deleted::from_expunged(vec![], None);
let mut i = seqs.into_iter();
assert_eq!(None, i.next());
}
#[test]
fn seq_set() {
let uids = Deleted::from_vanished(vec![1..=1, 3..=5, 8..=9, 12..=12], None);
let mut i = uids.into_iter();
assert_eq!(Some(1), i.next());
assert_eq!(Some(3), i.next());
assert_eq!(Some(4), i.next());
assert_eq!(Some(5), i.next());
assert_eq!(Some(8), i.next());
assert_eq!(Some(9), i.next());
assert_eq!(Some(12), i.next());
assert_eq!(None, i.next());
let uids = Deleted::from_vanished(vec![], None);
assert_eq!(None, uids.into_iter().next());
}
#[test]
fn seqs() {
let seqs: Deleted = Deleted::from_expunged(vec![3, 6, 9, 12], None);
let mut count: u32 = 0;
for seq in seqs.seqs() {
count += 3;
assert_eq!(seq, count);
}
assert_eq!(count, 12);
}
#[test]
fn uids() {
let uids: Deleted = Deleted::from_vanished(vec![1..=6], None);
let mut count: u32 = 0;
for uid in uids.uids() {
count += 1;
assert_eq!(uid, count);
}
assert_eq!(count, 6);
}
#[test]
fn generic_iteration() {
let seqs: Deleted = Deleted::from_expunged(vec![3, 6, 9, 12], None);
let mut count: u32 = 0;
for seq in &seqs {
count += 3;
assert_eq!(seq, count);
}
assert_eq!(count, 12);
let uids: Deleted = Deleted::from_vanished(vec![1..=6], None);
let mut count: u32 = 0;
for uid in &uids {
count += 1;
assert_eq!(uid, count);
}
assert_eq!(count, 6);
}
}