use std::{
collections::{BTreeMap, HashMap},
ffi::CString,
sync::{Arc, RwLock},
};
use crate::{
backends::prelude::*,
notmuch::{DbConnection, Message, TagIterator},
};
#[derive(Debug)]
pub struct Snapshot {
pub connection: DbConnection,
pub message_id_index: HashMap<EnvelopeHash, CString>,
pub env_to_mailbox_index: HashMap<EnvelopeHash, SmallVec<[MailboxHash; 16]>>,
pub tag_index: Arc<RwLock<BTreeMap<TagHash, String>>>,
pub account_hash: AccountHash,
}
impl Snapshot {
pub fn insert_envelope(&mut self, message: &Message<'_>) -> Envelope {
let env_hash = message.env_hash();
let mut env = Envelope::new(env_hash);
self.message_id_index
.insert(env_hash, message.msg_id_cstr().into());
let (flags, tags) = TagIterator::new(message).collect_flags_and_tags();
{
let mut tag_index_lck = self.tag_index.write().unwrap();
for tag in tags {
let num = TagHash::from_bytes(tag.as_bytes());
tag_index_lck.entry(num).or_insert(tag);
env.tags_mut().insert(num);
}
}
use crate::email::parser::address::rfc2822address_list;
env.set_message_id(message.msg_id())
.set_date(message.header(c"Date").unwrap_or_default())
.set_from(
rfc2822address_list(message.header(c"From").unwrap_or_default())
.map(|(_, v)| v)
.unwrap_or_default(),
)
.set_to(
rfc2822address_list(message.header(c"To").unwrap_or_default())
.map(|(_, v)| v)
.unwrap_or_default(),
)
.set_cc(
rfc2822address_list(message.header(c"Cc").unwrap_or_default())
.map(|(_, v)| v)
.unwrap_or_default(),
)
.set_bcc(
rfc2822address_list(message.header(c"Bcc").unwrap_or_default())
.map(|(_, v)| v)
.unwrap_or_default()
.to_vec(),
)
.set_subject(message.header(c"Subject").unwrap_or_default().to_vec())
.set_references(message.header(c"References").unwrap_or_default())
.set_in_reply_to(message.header(c"In-Reply-To").unwrap_or_default())
.set_datetime(message.date())
.set_flags(flags);
env
}
pub fn remove_envelope(&mut self, env_hash: EnvelopeHash) -> Vec<RefreshEvent> {
let mut events = vec![];
for mailbox_hash in self
.env_to_mailbox_index
.entry(env_hash)
.or_default()
.drain(..)
{
events.push(RefreshEvent {
account_hash: self.account_hash,
mailbox_hash,
kind: RefreshEventKind::Remove(env_hash),
});
}
self.message_id_index.remove(&env_hash);
self.env_to_mailbox_index.remove(&env_hash);
events
}
}