diff --git a/src/imap/command/authenticated.rs b/src/imap/command/authenticated.rs index fca15fc..378564b 100644 --- a/src/imap/command/authenticated.rs +++ b/src/imap/command/authenticated.rs @@ -83,6 +83,18 @@ impl<'a> StateContext<'a> { S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited S: A142 OK [READ-WRITE] SELECT completed + --- a mailbox with no unseen message -> no unseen entry + + 20 select "INBOX.achats" + * FLAGS (\Answered \Flagged \Deleted \Seen \Draft $Forwarded JUNK $label1) + * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft $Forwarded JUNK $label1 \*)] Flags permitted. + * 88 EXISTS + * 0 RECENT + * OK [UIDVALIDITY 1347986788] UIDs valid + * OK [UIDNEXT 91] Predicted next UID + * OK [HIGHESTMODSEQ 72] Highest + 20 OK [READ-WRITE] Select completed (0.001 + 0.000 secs). + * TRACE END --- */ async fn select(&self, mailbox: &MailboxCodec) -> Result<(Response, flow::Transition)> { @@ -96,8 +108,6 @@ impl<'a> StateContext<'a> { let body = vec![Data::Exists(sum.exists.try_into()?), Data::Recent(0)]; - let tr = flow::Transition::Select(mb); - let r_unseen = Status::ok( None, Some(Code::Unseen( @@ -108,13 +118,22 @@ impl<'a> StateContext<'a> { .map_err(Error::msg)?; //let r_permanentflags = Status::ok(None, Some(Code:: + let tr = flow::Transition::Select(mb); + Ok(( vec![ ImapRes::Data(Data::Exists(0)), ImapRes::Data(Data::Recent(0)), ImapRes::Data(Data::Flags(vec![])), + ImapRes::Status( + Status::ok( + None, + Some(Code::UidValidity(sum.validity)), + "UIDs valid" + ) + .map_err(Error::msg)?, + ), /*ImapRes::Status(), - ImapRes::Status(), ImapRes::Status(),*/ ImapRes::Status( Status::ok( diff --git a/src/mailbox.rs b/src/mailbox.rs index 249d329..54c22e3 100644 --- a/src/mailbox.rs +++ b/src/mailbox.rs @@ -104,7 +104,7 @@ fn dump(uid_index: &Bayou) { "{} {} {}", uid, hex::encode(ident.0), - s.table.get(ident).cloned().unwrap_or_default().1.join(", ") + s.table.get(ident).cloned().unwrap().1.join(", ") ); } println!(""); diff --git a/src/uidindex.rs b/src/uidindex.rs index 8e4a189..f53d770 100644 --- a/src/uidindex.rs +++ b/src/uidindex.rs @@ -1,11 +1,13 @@ +use std::num::NonZeroU32; + use im::{HashMap, HashSet, OrdMap, OrdSet}; use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; use crate::bayou::*; use crate::mail_ident::MailIdent; -pub type ImapUid = u32; -pub type ImapUidvalidity = u32; +pub type ImapUid = NonZeroU32; +pub type ImapUidvalidity = NonZeroU32; pub type Flag = String; #[derive(Clone)] @@ -90,9 +92,9 @@ impl Default for UidIndex { table: OrdMap::new(), idx_by_uid: OrdMap::new(), idx_by_flag: FlagIndex::new(), - uidvalidity: 1, - uidnext: 1, - internalseq: 1, + uidvalidity: NonZeroU32::new(1).unwrap(), + uidnext: NonZeroU32::new(1).unwrap(), + internalseq: NonZeroU32::new(1).unwrap(), } } } @@ -106,7 +108,9 @@ impl BayouState for UidIndex { UidIndexOp::MailAdd(ident, uid, flags) => { // Change UIDValidity if there is a conflict if *uid < new.internalseq { - new.uidvalidity += new.internalseq - *uid; + new.uidvalidity = + NonZeroU32::new(new.uidvalidity.get() + new.internalseq.get() - uid.get()) + .unwrap(); } // Assign the real uid of the email @@ -123,7 +127,7 @@ impl BayouState for UidIndex { new.reg_email(*ident, new_uid, flags); // Update counters - new.internalseq += 1; + new.internalseq = NonZeroU32::new(new.internalseq.get() + 1).unwrap(); new.uidnext = new.internalseq; } UidIndexOp::MailDel(ident) => { @@ -131,7 +135,7 @@ impl BayouState for UidIndex { new.unreg_email(ident); // We update the counter - new.internalseq += 1; + new.internalseq = NonZeroU32::new(new.internalseq.get() + 1).unwrap(); } UidIndexOp::FlagAdd(ident, new_flags) => { if let Some((uid, existing_flags)) = new.table.get_mut(ident) {