Rename MailUuid in MailIdent

This commit is contained in:
Quentin 2022-06-14 11:10:21 +02:00
parent 13ed1b3890
commit da6881199c
Signed by: quentin
GPG key ID: E9602264D639FF68
2 changed files with 51 additions and 42 deletions

View file

@ -69,7 +69,7 @@ impl Mailbox {
let add_mail_op = self let add_mail_op = self
.uid_index .uid_index
.state() .state()
.op_mail_add(MailUuid(rand_id), vec!["\\Unseen".into()]); .op_mail_add(MailIdent(rand_id), vec!["\\Unseen".into()]);
self.uid_index.push(add_mail_op).await?; self.uid_index.push(add_mail_op).await?;
dump(&self.uid_index); dump(&self.uid_index);

View file

@ -1,4 +1,4 @@
use im::{HashMap, HashSet, OrdMap}; use im::{HashMap, HashSet, OrdSet, OrdMap};
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
use crate::bayou::*; use crate::bayou::*;
@ -7,11 +7,15 @@ pub type ImapUid = u32;
pub type ImapUidvalidity = u32; pub type ImapUidvalidity = u32;
pub type Flag = String; pub type Flag = String;
/// A Mail UUID is composed of two components: /// Mail Identifier (MailIdent) are composed of two components:
/// - a process identifier, 128 bits /// - a process identifier, 128 bits
/// - a sequence number, 64 bits /// - a sequence number, 64 bits
/// They are not part of the protocol but an internal representation
/// required by Mailrage/Aerogramme.
/// Their main property is to be unique without having to rely
/// on synchronization between IMAP processes.
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
pub struct MailUuid(pub [u8; 24]); pub struct MailIdent(pub [u8; 24]);
#[derive(Clone)] #[derive(Clone)]
/// A UidIndex handles the mutable part of a mailbox /// A UidIndex handles the mutable part of a mailbox
@ -20,10 +24,10 @@ pub struct MailUuid(pub [u8; 24]);
/// and applying the event. This is why we use immutable datastructures /// and applying the event. This is why we use immutable datastructures
/// that are optimized for cloning (they clone underlying values only if they are modified) /// that are optimized for cloning (they clone underlying values only if they are modified)
pub struct UidIndex { pub struct UidIndex {
pub mail_uid: OrdMap<MailUuid, ImapUid>, pub mail_uid: OrdMap<MailIdent, ImapUid>,
pub mail_flags: OrdMap<MailUuid, Vec<Flag>>, pub mail_flags: OrdMap<MailIdent, Vec<Flag>>,
pub mails_by_uid: OrdMap<ImapUid, MailUuid>, pub mails_by_uid: OrdMap<ImapUid, MailIdent>,
pub flags: HashMap<Flag, HashSet<MailUuid>>, pub flags: HashMap<Flag, OrdSet<ImapUid>>,
pub uidvalidity: ImapUidvalidity, pub uidvalidity: ImapUidvalidity,
pub uidnext: ImapUid, pub uidnext: ImapUid,
@ -32,31 +36,31 @@ pub struct UidIndex {
#[derive(Clone, Serialize, Deserialize, Debug)] #[derive(Clone, Serialize, Deserialize, Debug)]
pub enum UidIndexOp { pub enum UidIndexOp {
MailAdd(MailUuid, ImapUid, Vec<Flag>), MailAdd(MailIdent, ImapUid, Vec<Flag>),
MailDel(MailUuid), MailDel(MailIdent),
FlagAdd(MailUuid, Vec<Flag>), FlagAdd(MailIdent, Vec<Flag>),
FlagDel(MailUuid, Vec<Flag>), FlagDel(MailIdent, Vec<Flag>),
} }
impl UidIndex { impl UidIndex {
#[must_use] #[must_use]
pub fn op_mail_add(&self, uuid: MailUuid, flags: Vec<Flag>) -> UidIndexOp { pub fn op_mail_add(&self, ident: MailIdent, flags: Vec<Flag>) -> UidIndexOp {
UidIndexOp::MailAdd(uuid, self.internalseq, flags) UidIndexOp::MailAdd(ident, self.internalseq, flags)
} }
#[must_use] #[must_use]
pub fn op_mail_del(&self, uuid: MailUuid) -> UidIndexOp { pub fn op_mail_del(&self, ident: MailIdent) -> UidIndexOp {
UidIndexOp::MailDel(uuid) UidIndexOp::MailDel(ident)
} }
#[must_use] #[must_use]
pub fn op_flag_add(&self, uuid: MailUuid, flags: Vec<Flag>) -> UidIndexOp { pub fn op_flag_add(&self, ident: MailIdent, flags: Vec<Flag>) -> UidIndexOp {
UidIndexOp::FlagAdd(uuid, flags) UidIndexOp::FlagAdd(ident, flags)
} }
#[must_use] #[must_use]
pub fn op_flag_del(&self, uuid: MailUuid, flags: Vec<Flag>) -> UidIndexOp { pub fn op_flag_del(&self, ident: MailIdent, flags: Vec<Flag>) -> UidIndexOp {
UidIndexOp::FlagDel(uuid, flags) UidIndexOp::FlagDel(ident, flags)
} }
} }
@ -80,60 +84,65 @@ impl BayouState for UidIndex {
fn apply(&self, op: &UidIndexOp) -> Self { fn apply(&self, op: &UidIndexOp) -> Self {
let mut new = self.clone(); let mut new = self.clone();
match op { match op {
UidIndexOp::MailAdd(uuid, uid, flags) => { UidIndexOp::MailAdd(ident, uid, flags) => {
// Change UIDValidity if there is a conflict
if *uid < new.internalseq { if *uid < new.internalseq {
new.uidvalidity += new.internalseq - *uid; new.uidvalidity += new.internalseq - *uid;
} }
// Assign the real uid
let new_uid = new.internalseq; let new_uid = new.internalseq;
if let Some(prev_uid) = new.mail_uid.get(uuid) { if let Some(prev_uid) = new.mail_uid.get(ident) {
new.mails_by_uid.remove(prev_uid); new.mails_by_uid.remove(prev_uid);
} else { } else {
new.mail_flags.insert(*uuid, flags.clone()); new.mail_flags.insert(*ident, flags.clone());
} }
new.mails_by_uid.insert(new_uid, *uuid); new.mails_by_uid.insert(new_uid, *ident);
new.mail_uid.insert(*uuid, new_uid); new.mail_uid.insert(*ident, new_uid);
new.internalseq += 1; new.internalseq += 1;
new.uidnext = new.internalseq; new.uidnext = new.internalseq;
} }
UidIndexOp::MailDel(uuid) => { UidIndexOp::MailDel(ident) => {
if let Some(uid) = new.mail_uid.get(uuid) { if let Some(uid) = new.mail_uid.get(ident) {
new.mails_by_uid.remove(uid); new.mails_by_uid.remove(uid);
new.mail_uid.remove(uuid); new.mail_uid.remove(ident);
new.mail_flags.remove(uuid); new.mail_flags.remove(ident);
} }
new.internalseq += 1; new.internalseq += 1;
} }
UidIndexOp::FlagAdd(uuid, new_flags) => { UidIndexOp::FlagAdd(ident, new_flags) => {
// Upate mapping Email -> Flag // Upate mapping Email -> Flag
let mail_flags = new.mail_flags.entry(*uuid).or_insert(vec![]); let mail_flags = new.mail_flags.entry(*ident).or_insert(vec![]);
for flag in new_flags { for flag in new_flags {
if !mail_flags.contains(flag) { if !mail_flags.contains(flag) {
mail_flags.push(flag.to_string()); mail_flags.push(flag.to_string());
} }
} }
// Update mapping Flag -> Email // Update mapping Flag -> ImapUid
/*
let _ = new_flags.iter().map(|flag| { let _ = new_flags.iter().map(|flag| {
new.flags new.flags
.entry(flag.clone()) .entry(flag.clone())
.or_insert(HashSet::new()) .or_insert(OrdSet::new())
.update(*uuid) .update(*uuid)
}); });*/
} }
UidIndexOp::FlagDel(uuid, rm_flags) => { UidIndexOp::FlagDel(ident, rm_flags) => {
// Upate mapping Email -> Flag // Upate mapping Email -> Flag
if let Some(mail_flags) = new.mail_flags.get_mut(uuid) { if let Some(mail_flags) = new.mail_flags.get_mut(ident) {
mail_flags.retain(|x| !rm_flags.contains(x)); mail_flags.retain(|x| !rm_flags.contains(x));
} }
// Update mapping Flag -> Email // Update mapping Flag -> ImapUid
rm_flags.iter().for_each(|flag| { /*rm_flags.iter().for_each(|flag| {
new.flags new.flags
.entry(flag.clone()) .entry(flag.clone())
.and_modify(|hs| { hs.remove(uuid); }); .and_modify(|hs| { hs.remove(uuid); });
}); });*/
} }
} }
new new
@ -144,7 +153,7 @@ impl BayouState for UidIndex {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct UidIndexSerializedRepr { struct UidIndexSerializedRepr {
mails: Vec<(ImapUid, MailUuid, Vec<Flag>)>, mails: Vec<(ImapUid, MailIdent, Vec<Flag>)>,
uidvalidity: ImapUidvalidity, uidvalidity: ImapUidvalidity,
uidnext: ImapUid, uidnext: ImapUid,
internalseq: ImapUid, internalseq: ImapUid,
@ -202,7 +211,7 @@ impl Serialize for UidIndex {
} }
} }
impl<'de> Deserialize<'de> for MailUuid { impl<'de> Deserialize<'de> for MailIdent {
fn deserialize<D>(d: D) -> Result<Self, D::Error> fn deserialize<D>(d: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
@ -220,7 +229,7 @@ impl<'de> Deserialize<'de> for MailUuid {
} }
} }
impl Serialize for MailUuid { impl Serialize for MailIdent {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
S: Serializer, S: Serializer,