melib: Hide Envelope behind RwLock

Envelope can now only be accessed from within a RwLock. Two new structs
are introduced: EnvelopeRef and EnvelopeRefMut. These hold a reference
to an Envelope and the mutex guard that keeps them alive.

This change allows sharing of the envelopes hash map amongst threads.
sql
Manos Pitsidianakis 2019-11-02 12:14:31 +02:00
parent e9d17f6897
commit 78eecbb104
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
15 changed files with 305 additions and 216 deletions

View File

@ -19,7 +19,7 @@ notify-rust = { version = "^3", optional = true }
termion = "1.5.1"
xdg = "2.1.0"
native-tls = { version ="0.2", optional=true }
serde = "1.0.71"
serde = { version = "1.0.71", features = ["rc", ] }
serde_derive = "1.0.71"
bincode = "1.2.0"
uuid = { version = "0.7.4", features = ["serde", "v4"] }

View File

@ -4,12 +4,45 @@ use std::collections::BTreeMap;
use std::fs;
use std::io;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
use fnv::FnvHashMap;
pub struct EnvelopeRef<'g> {
guard: RwLockReadGuard<'g, FnvHashMap<EnvelopeHash, Envelope>>,
env_hash: EnvelopeHash,
}
impl Deref for EnvelopeRef<'_> {
type Target = Envelope;
fn deref(&self) -> &Envelope {
self.guard.get(&self.env_hash).unwrap()
}
}
pub struct EnvelopeRefMut<'g> {
guard: RwLockWriteGuard<'g, FnvHashMap<EnvelopeHash, Envelope>>,
env_hash: EnvelopeHash,
}
impl Deref for EnvelopeRefMut<'_> {
type Target = Envelope;
fn deref(&self) -> &Envelope {
self.guard.get(&self.env_hash).unwrap()
}
}
impl DerefMut for EnvelopeRefMut<'_> {
fn deref_mut(&mut self) -> &mut Envelope {
self.guard.get_mut(&self.env_hash).unwrap()
}
}
#[derive(Debug, Clone, Deserialize, Default, Serialize)]
pub struct Collection {
pub envelopes: FnvHashMap<EnvelopeHash, Envelope>,
pub envelopes: Arc<RwLock<FnvHashMap<EnvelopeHash, Envelope>>>,
message_ids: FnvHashMap<Vec<u8>, EnvelopeHash>,
date_index: BTreeMap<UnixTimestamp, EnvelopeHash>,
subject_index: Option<BTreeMap<String, EnvelopeHash>>,
@ -48,7 +81,7 @@ impl Collection {
let threads = FnvHashMap::with_capacity_and_hasher(16, Default::default());
Collection {
envelopes,
envelopes: Arc::new(RwLock::new(envelopes)),
date_index,
message_ids,
subject_index,
@ -58,16 +91,16 @@ impl Collection {
}
pub fn len(&self) -> usize {
self.envelopes.len()
self.envelopes.read().unwrap().len()
}
pub fn is_empty(&self) -> bool {
self.envelopes.is_empty()
self.envelopes.read().unwrap().is_empty()
}
pub fn remove(&mut self, envelope_hash: EnvelopeHash, folder_hash: FolderHash) {
debug!("DEBUG: Removing {}", envelope_hash);
self.envelopes.remove(&envelope_hash);
self.envelopes.write().unwrap().remove(&envelope_hash);
self.threads
.entry(folder_hash)
.or_default()
@ -86,14 +119,14 @@ impl Collection {
new_hash: EnvelopeHash,
folder_hash: FolderHash,
) {
if !self.envelopes.contains_key(&old_hash) {
if !self.envelopes.write().unwrap().contains_key(&old_hash) {
return;
}
let mut env = self.envelopes.remove(&old_hash).unwrap();
let mut env = self.envelopes.write().unwrap().remove(&old_hash).unwrap();
env.set_hash(new_hash);
self.message_ids
.insert(env.message_id().raw().to_vec(), new_hash);
self.envelopes.insert(new_hash, env);
self.envelopes.write().unwrap().insert(new_hash, env);
{
if self
.threads
@ -150,9 +183,9 @@ impl Collection {
} = self;
if !threads.contains_key(&folder_hash) {
threads.insert(folder_hash, Threads::new(&mut new_envelopes));
threads.insert(folder_hash, Threads::new(new_envelopes.len()));
for (h, e) in new_envelopes {
envelopes.insert(h, e);
envelopes.write().unwrap().insert(h, e);
}
} else {
threads.entry(folder_hash).and_modify(|t| {
@ -165,7 +198,10 @@ impl Collection {
.unwrap()
});
for h in ordered_hash_set {
envelopes.insert(h, new_envelopes.remove(&h).unwrap());
envelopes
.write()
.unwrap()
.insert(h, new_envelopes.remove(&h).unwrap());
t.insert(envelopes, h);
}
});
@ -178,17 +214,19 @@ impl Collection {
continue;
}
if sent_folder.map(|f| f == folder_hash).unwrap_or(false) {
let envelopes_lck = envelopes.read().unwrap();
let mut ordered_hash_set = threads[&folder_hash]
.hash_set
.iter()
.cloned()
.collect::<Vec<EnvelopeHash>>();
ordered_hash_set.sort_by(|a, b| {
envelopes[a]
envelopes_lck[a]
.date()
.partial_cmp(&envelopes[b].date())
.partial_cmp(&envelopes_lck[b].date())
.unwrap()
});
drop(envelopes_lck);
let mut updated = false;
for h in ordered_hash_set {
updated |= threads.entry(t_fh).or_default().insert_reply(envelopes, h);
@ -199,17 +237,19 @@ impl Collection {
continue;
}
if sent_folder.map(|f| f == t_fh).unwrap_or(false) {
let envelopes_lck = envelopes.read().unwrap();
let mut ordered_hash_set = threads[&t_fh]
.hash_set
.iter()
.cloned()
.collect::<Vec<EnvelopeHash>>();
ordered_hash_set.sort_by(|a, b| {
envelopes[a]
envelopes_lck[a]
.date()
.partial_cmp(&envelopes[b].date())
.partial_cmp(&envelopes_lck[b].date())
.unwrap()
});
drop(envelopes_lck);
let mut updated = false;
for h in ordered_hash_set {
updated |= threads
@ -235,12 +275,12 @@ impl Collection {
mut envelope: Envelope,
folder_hash: FolderHash,
) {
let old_env = self.envelopes.remove(&old_hash).unwrap();
let old_env = self.envelopes.write().unwrap().remove(&old_hash).unwrap();
envelope.set_thread(old_env.thread());
let new_hash = envelope.hash();
self.message_ids
.insert(envelope.message_id().raw().to_vec(), new_hash);
self.envelopes.insert(new_hash, envelope);
self.envelopes.write().unwrap().insert(new_hash, envelope);
if self.sent_folder.map(|f| f == folder_hash).unwrap_or(false) {
for (_, t) in self.threads.iter_mut() {
t.update_envelope(&self.envelopes, old_hash, new_hash)
@ -273,11 +313,11 @@ impl Collection {
}
}
pub fn insert(&mut self, envelope: Envelope, folder_hash: FolderHash) -> &Envelope {
pub fn insert(&mut self, envelope: Envelope, folder_hash: FolderHash) {
let hash = envelope.hash();
self.message_ids
.insert(envelope.message_id().raw().to_vec(), hash);
self.envelopes.insert(hash, envelope);
self.envelopes.write().unwrap().insert(hash, envelope);
if !self
.threads
.entry(folder_hash)
@ -289,26 +329,26 @@ impl Collection {
.or_default()
.insert(&mut self.envelopes, hash);
}
&self.envelopes[&hash]
}
pub fn insert_reply(&mut self, env_hash: EnvelopeHash) {
debug_assert!(self.envelopes.contains_key(&env_hash));
debug_assert!(self.envelopes.read().unwrap().contains_key(&env_hash));
for (_, t) in self.threads.iter_mut() {
t.insert_reply(&mut self.envelopes, env_hash);
}
}
}
impl Deref for Collection {
type Target = FnvHashMap<EnvelopeHash, Envelope>;
pub fn get_env<'g>(&'g self, env_hash: EnvelopeHash) -> EnvelopeRef<'g> {
let guard: RwLockReadGuard<'g, _> = self.envelopes.read().unwrap();
EnvelopeRef { guard, env_hash }
}
fn deref(&self) -> &FnvHashMap<EnvelopeHash, Envelope> {
&self.envelopes
}
}
impl DerefMut for Collection {
fn deref_mut(&mut self) -> &mut FnvHashMap<EnvelopeHash, Envelope> {
&mut self.envelopes
pub fn get_env_mut<'g>(&'g mut self, env_hash: EnvelopeHash) -> EnvelopeRefMut<'g> {
let guard = self.envelopes.write().unwrap();
EnvelopeRefMut { guard, env_hash }
}
pub fn contains_key(&self, env_hash: &EnvelopeHash) -> bool {
self.envelopes.read().unwrap().contains_key(env_hash)
}
}

View File

@ -50,8 +50,9 @@ use std::ops::Index;
use std::result::Result as StdResult;
use std::str::FromStr;
use std::string::ToString;
use std::sync::{Arc, RwLock};
type Envelopes = FnvHashMap<EnvelopeHash, Envelope>;
type Envelopes = Arc<RwLock<FnvHashMap<EnvelopeHash, Envelope>>>;
#[derive(PartialEq, Hash, Eq, Copy, Clone, Serialize, Deserialize, Default)]
pub struct ThreadHash(Uuid);
@ -485,6 +486,7 @@ impl ThreadNode {
buf: &FnvHashMap<ThreadHash, ThreadNode>,
envelopes: &Envelopes,
) -> usize {
let envelopes = envelopes.read().unwrap();
match sort {
(SortField::Date, SortOrder::Asc) => {
match vec.binary_search_by(|probe| buf[&probe].date.cmp(&buf[&child].date)) {
@ -682,25 +684,25 @@ impl Threads {
x_root
}
pub fn new(envelopes: &mut Envelopes) -> Threads {
pub fn new(length: usize) -> Threads {
/* To reconstruct thread information from the mails we need: */
/* a vector to hold thread members */
let thread_nodes: FnvHashMap<ThreadHash, ThreadNode> = FnvHashMap::with_capacity_and_hasher(
(envelopes.len() as f64 * 1.2) as usize,
(length as f64 * 1.2) as usize,
Default::default(),
);
/* A hash table of Message IDs */
let message_ids: FnvHashMap<Vec<u8>, ThreadHash> =
FnvHashMap::with_capacity_and_hasher(envelopes.len(), Default::default());
FnvHashMap::with_capacity_and_hasher(length, Default::default());
/* A hash set of Message IDs we haven't encountered yet as an Envelope */
let missing_message_ids: FnvHashSet<Vec<u8>> =
FnvHashSet::with_capacity_and_hasher(envelopes.len(), Default::default());
FnvHashSet::with_capacity_and_hasher(length, Default::default());
/* A hash set of Message IDs we have encountered as a MessageID */
let message_ids_set: FnvHashSet<Vec<u8>> =
FnvHashSet::with_capacity_and_hasher(envelopes.len(), Default::default());
FnvHashSet::with_capacity_and_hasher(length, Default::default());
let hash_set: FnvHashSet<EnvelopeHash> =
FnvHashSet::with_capacity_and_hasher(envelopes.len(), Default::default());
FnvHashSet::with_capacity_and_hasher(length, Default::default());
Threads {
thread_nodes,
@ -754,12 +756,12 @@ impl Threads {
};
self.thread_nodes.get_mut(&thread_hash).unwrap().message = Some(new_hash);
self.thread_nodes.get_mut(&thread_hash).unwrap().has_unseen = !envelopes[&new_hash]
.is_seen()
|| self.thread_nodes[&thread_hash]
.children
.iter()
.fold(false, |acc, x| acc || self.thread_nodes[x].has_unseen);
self.thread_nodes.get_mut(&thread_hash).unwrap().has_unseen =
!envelopes.read().unwrap()[&new_hash].is_seen()
|| self.thread_nodes[&thread_hash]
.children
.iter()
.fold(false, |acc, x| acc || self.thread_nodes[x].has_unseen);
let mut thread_hash_iter = thread_hash;
while self.thread_nodes[&thread_hash_iter].parent.is_some() {
@ -802,18 +804,20 @@ impl Threads {
}
pub fn amend(&mut self, envelopes: &mut Envelopes) {
let new_hash_set = FnvHashSet::from_iter(envelopes.keys().cloned());
let envelopes_lck = envelopes.read().unwrap();
let new_hash_set = FnvHashSet::from_iter(envelopes_lck.keys().cloned());
let difference: Vec<EnvelopeHash> =
self.hash_set.difference(&new_hash_set).cloned().collect();
for h in difference {
self.remove(h);
}
drop(envelopes_lck);
let difference: Vec<EnvelopeHash> =
new_hash_set.difference(&self.hash_set).cloned().collect();
for h in difference {
debug!("inserting {}", envelopes[&h].subject());
//debug!("inserting {}", envelopes_lck[&h].subject());
self.insert(envelopes, h);
}
}
@ -825,6 +829,7 @@ impl Threads {
env_hash: EnvelopeHash,
envelopes: &Envelopes,
) {
let envelopes = envelopes.read().unwrap();
let mut subject = envelopes[&env_hash].subject();
let mut subject = subject.to_mut().as_bytes();
let stripped_subject = subject.strip_prefixes();
@ -861,17 +866,18 @@ impl Threads {
}
pub fn insert(&mut self, envelopes: &mut Envelopes, env_hash: EnvelopeHash) {
let envelopes_lck = envelopes.read().unwrap();
if self
.message_ids
.contains_key(envelopes[&env_hash].message_id().raw())
.contains_key(envelopes_lck[&env_hash].message_id().raw())
&& !self
.missing_message_ids
.contains(envelopes[&env_hash].message_id().raw())
.contains(envelopes_lck[&env_hash].message_id().raw())
{
return;
}
let reply_to_id: Option<ThreadHash> = envelopes[&env_hash]
let reply_to_id: Option<ThreadHash> = envelopes_lck[&env_hash]
.in_reply_to()
.map(crate::email::StrBuild::raw)
.and_then(|r| self.message_ids.get(r).cloned());
@ -881,24 +887,28 @@ impl Threads {
ThreadNode {
message: Some(env_hash),
parent: reply_to_id,
date: envelopes[&env_hash].date(),
has_unseen: !envelopes[&env_hash].is_seen(),
date: envelopes_lck[&env_hash].date(),
has_unseen: !envelopes_lck[&env_hash].is_seen(),
..ThreadNode::new(new_id)
},
);
self.message_ids
.insert(envelopes[&env_hash].message_id().raw().to_vec(), new_id);
self.message_ids_set
.insert(envelopes[&env_hash].message_id().raw().to_vec().to_vec());
.insert(envelopes_lck[&env_hash].message_id().raw().to_vec(), new_id);
self.message_ids_set.insert(
envelopes_lck[&env_hash]
.message_id()
.raw()
.to_vec()
.to_vec(),
);
self.missing_message_ids
.remove(envelopes[&env_hash].message_id().raw());
envelopes.get_mut(&env_hash).unwrap().set_thread(new_id);
.remove(envelopes_lck[&env_hash].message_id().raw());
self.hash_set.insert(env_hash);
if let Some(reply_to_id) = reply_to_id {
self.union(reply_to_id, new_id);
make!((reply_to_id) parent of (new_id), &mut self.thread_nodes);
} else {
if let Some(r) = envelopes[&env_hash]
if let Some(r) = envelopes_lck[&env_hash]
.in_reply_to()
.map(crate::email::StrBuild::raw)
{
@ -906,7 +916,7 @@ impl Threads {
self.thread_nodes.insert(
reply_to_id,
ThreadNode {
date: envelopes[&env_hash].date(),
date: envelopes_lck[&env_hash].date(),
thread_group: reply_to_id,
..ThreadNode::new(reply_to_id)
},
@ -919,23 +929,31 @@ impl Threads {
}
self.tree_insert_root(new_id, envelopes);
}
drop(envelopes_lck);
self.update_show_subject(new_id, env_hash, envelopes);
envelopes
.write()
.unwrap()
.get_mut(&env_hash)
.unwrap()
.set_thread(new_id);
}
/* Insert or update */
pub fn insert_reply(&mut self, envelopes: &mut Envelopes, env_hash: EnvelopeHash) -> bool {
let reply_to_id: Option<ThreadHash> = envelopes[&env_hash]
let mut envelopes_lck = envelopes.write().unwrap();
let reply_to_id: Option<ThreadHash> = envelopes_lck[&env_hash]
.in_reply_to()
.map(crate::email::StrBuild::raw)
.and_then(|r| self.message_ids.get(r).cloned());
if let Some(id) = self
.message_ids
.get(envelopes[&env_hash].message_id().raw())
.get(envelopes_lck[&env_hash].message_id().raw())
.cloned()
{
self.thread_nodes.entry(id).and_modify(|n| {
n.message = Some(env_hash);
n.date = envelopes[&env_hash].date();
n.date = envelopes_lck[&env_hash].date();
n.pruned = false;
if n.parent.is_none() {
if let Some(reply_to_id) = reply_to_id {
@ -951,13 +969,19 @@ impl Threads {
}
self.message_ids
.insert(envelopes[&env_hash].message_id().raw().to_vec(), id);
self.message_ids_set
.insert(envelopes[&env_hash].message_id().raw().to_vec().to_vec());
.insert(envelopes_lck[&env_hash].message_id().raw().to_vec(), id);
self.message_ids_set.insert(
envelopes_lck[&env_hash]
.message_id()
.raw()
.to_vec()
.to_vec(),
);
self.missing_message_ids
.remove(envelopes[&env_hash].message_id().raw());
envelopes.get_mut(&env_hash).unwrap().set_thread(id);
.remove(envelopes_lck[&env_hash].message_id().raw());
envelopes_lck.get_mut(&env_hash).unwrap().set_thread(id);
self.hash_set.insert(env_hash);
drop(envelopes_lck);
if self.thread_nodes[&id].parent.is_none() {
self.tree_insert_root(id, envelopes);
}
@ -978,21 +1002,27 @@ impl Threads {
ThreadNode {
message: Some(env_hash),
parent: Some(reply_to_id),
date: envelopes[&env_hash].date(),
has_unseen: !envelopes[&env_hash].is_seen(),
date: envelopes_lck[&env_hash].date(),
has_unseen: !envelopes_lck[&env_hash].is_seen(),
..ThreadNode::new(new_id)
},
);
self.message_ids
.insert(envelopes[&env_hash].message_id().raw().to_vec(), new_id);
self.message_ids_set
.insert(envelopes[&env_hash].message_id().raw().to_vec().to_vec());
.insert(envelopes_lck[&env_hash].message_id().raw().to_vec(), new_id);
self.message_ids_set.insert(
envelopes_lck[&env_hash]
.message_id()
.raw()
.to_vec()
.to_vec(),
);
self.missing_message_ids
.remove(envelopes[&env_hash].message_id().raw());
envelopes.get_mut(&env_hash).unwrap().set_thread(new_id);
.remove(envelopes_lck[&env_hash].message_id().raw());
envelopes_lck.get_mut(&env_hash).unwrap().set_thread(new_id);
self.hash_set.insert(env_hash);
self.union(reply_to_id, new_id);
make!((reply_to_id) parent of (new_id), &mut self.thread_nodes);
drop(envelopes_lck);
self.update_show_subject(new_id, env_hash, envelopes);
true
} else {
@ -1073,6 +1103,7 @@ impl Threads {
sort: (SortField, SortOrder),
envelopes: &Envelopes,
) {
let envelopes = envelopes.read().unwrap();
vec.sort_by(|b, a| match sort {
(SortField::Date, SortOrder::Desc) => {
let a = &self.thread_nodes[&a];
@ -1148,6 +1179,7 @@ impl Threads {
}
fn inner_sort_by(&self, sort: (SortField, SortOrder), envelopes: &Envelopes) {
let tree = &mut self.tree_index.borrow_mut();
let envelopes = envelopes.read().unwrap();
tree.sort_by(|b, a| match sort {
(SortField::Date, SortOrder::Desc) => {
let a = &self.thread_nodes[&a];

View File

@ -50,6 +50,7 @@ enum CacheType {
Sqlite3,
}
/*
pub struct Cache {
collection: Collection,
kind: CacheType,
@ -108,3 +109,4 @@ impl Cache {
&self.collection.threads[&f].thread_nodes()[&h]
}
}
*/

View File

@ -169,9 +169,9 @@ impl Composer {
pub fn edit(account_pos: usize, h: EnvelopeHash, context: &Context) -> Result<Self> {
let mut ret = Composer::default();
let op = context.accounts[account_pos].operation(h);
let envelope: &Envelope = context.accounts[account_pos].get_env(&h);
let envelope: EnvelopeRef = context.accounts[account_pos].collection.get_env(h);
ret.draft = Draft::edit(envelope, op)?;
ret.draft = Draft::edit(&envelope, op)?;
ret.account_cursor = account_pos;
Ok(ret)
@ -187,10 +187,10 @@ impl Composer {
let thread_nodes = &threads.thread_nodes();
let mut ret = Composer::default();
let p = &thread_nodes[&msg];
let parent_message = &account.collection[&p.message().unwrap()];
let parent_message = account.collection.get_env(p.message().unwrap());
/* If message is from a mailing list and we detect a List-Post header, ask user if they
* want to reply to the mailing list or the submitter of the message */
if let Some(actions) = list_management::detect(parent_message) {
if let Some(actions) = list_management::detect(&parent_message) {
if let Some(post) = actions.post {
/* Try to parse header value in this order
* - <mailto:*****@*****>
@ -224,16 +224,24 @@ impl Composer {
let mut op = account.operation(parent_message.hash());
let parent_bytes = op.as_bytes();
ret.draft = Draft::new_reply(parent_message, parent_bytes.unwrap());
ret.draft = Draft::new_reply(&parent_message, parent_bytes.unwrap());
ret.draft.headers_mut().insert(
"Subject".into(),
if p.show_subject() {
format!(
"Re: {}",
account.get_env(&p.message().unwrap()).subject().clone()
account
.collection
.get_env(p.message().unwrap())
.subject()
.clone()
)
} else {
account.get_env(&p.message().unwrap()).subject().into()
account
.collection
.get_env(p.message().unwrap())
.subject()
.into()
},
);

View File

@ -579,13 +579,15 @@ impl Component for Listing {
} else {
return Some(String::new());
};
let envelopes = account.collection.envelopes.clone();
let envelopes = envelopes.read().unwrap();
format!(
"Mailbox: {}, Messages: {}, New: {}",
m.folder.name(),
m.envelopes.len(),
m.envelopes
.iter()
.map(|h| &account.collection[&h])
.map(|h| &envelopes[&h])
.filter(|e| !e.is_seen())
.count()
)
@ -714,8 +716,8 @@ impl Listing {
.unwrap()
.envelopes
.iter()
.filter_map(|h| {
if account.collection[&h].is_seen() {
.filter_map(|&h| {
if account.collection.get_env(h).is_seen() {
None
} else {
Some(())

View File

@ -364,10 +364,10 @@ impl ListingTrait for CompactListing {
Ok(results) => {
let threads = &account.collection.threads[&folder_hash];
for env_hash in results {
if !account.collection.envelopes.contains_key(&env_hash) {
if !account.collection.contains_key(&env_hash) {
continue;
}
let env_hash_thread_hash = account.get_env(&env_hash).thread();
let env_hash_thread_hash = account.collection.get_env(env_hash).thread();
if !threads.thread_nodes.contains_key(&env_hash_thread_hash) {
continue;
}
@ -388,7 +388,7 @@ impl ListingTrait for CompactListing {
threads.vec_inner_sort_by(
&mut self.filtered_selection,
self.sort,
&context.accounts[self.cursor_pos.0].collection,
&context.accounts[self.cursor_pos.0].collection.envelopes,
);
self.new_cursor_pos.2 =
std::cmp::min(self.filtered_selection.len() - 1, self.cursor_pos.2);
@ -469,7 +469,11 @@ impl CompactListing {
id: ComponentId::new_v4(),
}
}
fn make_entry_string(e: &Envelope, thread_node: &ThreadNode, is_snoozed: bool) -> EntryStrings {
fn make_entry_string(
e: EnvelopeRef,
thread_node: &ThreadNode,
is_snoozed: bool,
) -> EntryStrings {
if thread_node.len() > 0 {
EntryStrings {
date: DateString(ConversationsListing::format_date(thread_node)),
@ -560,7 +564,7 @@ impl CompactListing {
let mut rows = Vec::with_capacity(1024);
let mut min_width = (0, 0, 0, 0, 0);
threads.sort_by(self.sort, self.subsort, &account.collection);
threads.sort_by(self.sort, self.subsort, &account.collection.envelopes);
let mut refresh_mailbox = false;
let threads_iter = if self.filter_term.is_empty() {
@ -594,7 +598,8 @@ impl CompactListing {
panic!();
}
let root_envelope: &Envelope = &context.accounts[self.cursor_pos.0].get_env(&i);
let root_envelope: EnvelopeRef =
context.accounts[self.cursor_pos.0].collection.get_env(i);
let entry_strings = CompactListing::make_entry_string(
root_envelope,
@ -750,8 +755,9 @@ impl CompactListing {
}
match (
threads.is_snoozed(root_idx),
&context.accounts[self.cursor_pos.0]
.get_env(&i)
context.accounts[self.cursor_pos.0]
.collection
.get_env(i)
.has_attachments(),
) {
(true, true) => {
@ -835,11 +841,11 @@ impl CompactListing {
}
}
for env_hash in envs_to_set {
let hash = account.collection.get_env(env_hash).hash();
let op = account.operation(hash);
let mut envelope: EnvelopeRefMut = account.collection.get_env_mut(env_hash);
match a {
ListingAction::SetSeen => {
let hash = account.get_env(&env_hash).hash();
let op = account.operation(hash);
let envelope: &mut Envelope = &mut account.get_env_mut(&env_hash);
if let Err(e) = envelope.set_seen(op) {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(e.to_string()),
@ -848,19 +854,19 @@ impl CompactListing {
self.row_updates.push(thread_hash);
}
ListingAction::SetUnseen => {
let hash = account.get_env(&env_hash).hash();
let op = account.operation(hash);
let envelope: &mut Envelope = &mut account.get_env_mut(&env_hash);
if let Err(e) = envelope.set_unseen(op) {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(e.to_string()),
));
}
self.row_updates.push(thread_hash);
}
ListingAction::Delete => { /* do nothing */ }
ListingAction::Delete => {
/* do nothing */
continue;
}
_ => unreachable!(),
}
self.row_updates.push(thread_hash);
}
}
}
@ -1009,10 +1015,10 @@ impl Component for CompactListing {
let account = &context.accounts[self.cursor_pos.0];
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
let threads = &account.collection.threads[&folder_hash];
if !account.collection.envelopes.contains_key(&new_hash) {
if !account.collection.contains_key(&new_hash) {
return false;
}
let new_env_thread_hash = account.get_env(new_hash).thread();
let new_env_thread_hash = account.collection.get_env(*new_hash).thread();
if !threads.thread_nodes.contains_key(&new_env_thread_hash) {
return false;
}
@ -1094,7 +1100,7 @@ impl Component for CompactListing {
threads.vec_inner_sort_by(
&mut self.filtered_selection,
self.sort,
&context.accounts[self.cursor_pos.0].collection,
&context.accounts[self.cursor_pos.0].collection.envelopes,
);
self.dirty = true;
} else {

View File

@ -355,10 +355,10 @@ impl ListingTrait for ConversationsListing {
Ok(results) => {
let threads = &account.collection.threads[&folder_hash];
for env_hash in results {
if !account.collection.envelopes.contains_key(&env_hash) {
if !account.collection.contains_key(&env_hash) {
continue;
}
let env_hash_thread_hash = account.get_env(&env_hash).thread();
let env_hash_thread_hash = account.collection.get_env(env_hash).thread();
if !threads.thread_nodes.contains_key(&env_hash_thread_hash) {
continue;
}
@ -379,7 +379,7 @@ impl ListingTrait for ConversationsListing {
threads.vec_inner_sort_by(
&mut self.filtered_selection,
self.sort,
&context.accounts[self.cursor_pos.0].collection,
&context.accounts[self.cursor_pos.0].collection.envelopes,
);
self.new_cursor_pos.2 =
std::cmp::min(self.filtered_selection.len() - 1, self.cursor_pos.2);
@ -555,7 +555,7 @@ impl ConversationsListing {
let mut rows = Vec::with_capacity(1024);
let mut max_entry_columns = 0;
threads.sort_by(self.sort, self.subsort, &account.collection);
threads.sort_by(self.sort, self.subsort, &account.collection.envelopes);
let mut refresh_mailbox = false;
let threads_iter = if self.filter_term.is_empty() {
@ -589,7 +589,8 @@ impl ConversationsListing {
panic!();
}
let root_envelope: &Envelope = &context.accounts[self.cursor_pos.0].get_env(&i);
let root_envelope: &EnvelopeRef =
&context.accounts[self.cursor_pos.0].collection.get_env(i);
let strings = ConversationsListing::make_entry_string(
root_envelope,
@ -808,32 +809,31 @@ impl ConversationsListing {
}
}
for env_hash in envs_to_set {
let hash = account.collection.get_env(env_hash).hash();
let op = account.operation(hash);
let mut envelope: EnvelopeRefMut = account.collection.get_env_mut(env_hash);
match a {
ListingAction::SetSeen => {
let hash = account.get_env(&env_hash).hash();
let op = account.operation(hash);
let envelope: &mut Envelope = &mut account.get_env_mut(&env_hash);
if let Err(e) = envelope.set_seen(op) {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(e.to_string()),
));
}
self.row_updates.push(thread_hash);
}
ListingAction::SetUnseen => {
let hash = account.get_env(&env_hash).hash();
let op = account.operation(hash);
let envelope: &mut Envelope = &mut account.get_env_mut(&env_hash);
if let Err(e) = envelope.set_unseen(op) {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(e.to_string()),
));
}
self.row_updates.push(thread_hash);
}
ListingAction::Delete => { /* do nothing */ }
ListingAction::Delete => {
/* do nothing */
continue;
}
_ => unreachable!(),
}
self.row_updates.push(thread_hash);
}
}
}
@ -1049,10 +1049,10 @@ impl Component for ConversationsListing {
let account = &context.accounts[self.cursor_pos.0];
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
let threads = &account.collection.threads[&folder_hash];
if !account.collection.envelopes.contains_key(&new_hash) {
if !account.collection.contains_key(&new_hash) {
return false;
}
let new_env_thread_hash = account.get_env(new_hash).thread();
let new_env_thread_hash = account.collection.get_env(*new_hash).thread();
if !threads.thread_nodes.contains_key(&new_env_thread_hash) {
return false;
}
@ -1133,7 +1133,7 @@ impl Component for ConversationsListing {
threads.vec_inner_sort_by(
&mut self.filtered_selection,
self.sort,
&context.accounts[self.cursor_pos.0].collection,
&context.accounts[self.cursor_pos.0].collection.envelopes,
);
self.dirty = true;
} else {

View File

@ -97,7 +97,7 @@ impl ListingTrait for PlainListing {
}
fn highlight_line(&mut self, grid: &mut CellBuffer, area: Area, idx: usize, context: &Context) {
let account = &context.accounts[self.cursor_pos.0];
let envelope: &Envelope = &account.get_env(&self.local_collection[idx]);
let envelope: EnvelopeRef = account.collection.get_env(self.local_collection[idx]);
let fg_color = if !envelope.is_seen() {
Color::Byte(0)
@ -323,27 +323,28 @@ impl PlainListing {
);
return;
}
self.local_collection = account.collection.keys().cloned().collect();
let envelopes = account.collection.envelopes.read().unwrap();
self.local_collection = envelopes.keys().cloned().collect();
let sort = self.sort;
self.local_collection.sort_by(|a, b| match sort {
(SortField::Date, SortOrder::Desc) => {
let ma = &account.get_env(a);
let mb = &account.get_env(b);
let ma = &envelopes[a];
let mb = &envelopes[b];
mb.date().cmp(&ma.date())
}
(SortField::Date, SortOrder::Asc) => {
let ma = &account.get_env(a);
let mb = &account.get_env(b);
let ma = &envelopes[a];
let mb = &envelopes[b];
ma.date().cmp(&mb.date())
}
(SortField::Subject, SortOrder::Desc) => {
let ma = &account.get_env(a);
let mb = &account.get_env(b);
let ma = &envelopes[a];
let mb = &envelopes[b];
ma.subject().cmp(&mb.subject())
}
(SortField::Subject, SortOrder::Asc) => {
let ma = &account.get_env(a);
let mb = &account.get_env(b);
let ma = &envelopes[a];
let mb = &envelopes[b];
mb.subject().cmp(&ma.subject())
}
});
@ -353,9 +354,9 @@ impl PlainListing {
let widths: (usize, usize, usize);
for idx in 0..self.local_collection.len() {
let envelope: &Envelope = &account.get_env(&self.local_collection[idx]);
let envelope: EnvelopeRef = account.collection.get_env(self.local_collection[idx]);
let strings = PlainListing::make_entry_string(envelope, idx);
let strings = PlainListing::make_entry_string(&envelope, idx);
min_width.0 = cmp::max(min_width.0, strings.0.len()); /* index */
min_width.1 = cmp::max(min_width.1, strings.2.split_graphemes().len()); /* date */
min_width.2 = cmp::max(min_width.2, strings.3.split_graphemes().len()); /* subject */
@ -381,7 +382,7 @@ impl PlainListing {
break;
}
/* Write an entire line for each envelope entry. */
let envelope: &Envelope = &account.get_env(&self.local_collection[idx]);
let envelope: EnvelopeRef = account.collection.get_env(self.local_collection[idx]);
let fg_color = if !envelope.is_seen() {
Color::Byte(0)
@ -533,9 +534,9 @@ impl Component for PlainListing {
if self.length == 0 {
false
} else {
let account = &mut context.accounts[self.cursor_pos.0];
let envelope: &mut Envelope =
&mut account.get_env_mut(&self.local_collection[idx]);
let account = &context.accounts[self.cursor_pos.0];
let envelope: EnvelopeRef =
account.collection.get_env(self.local_collection[idx]);
!envelope.is_seen()
}
};

View File

@ -177,8 +177,9 @@ impl ListingTrait for ThreadListing {
}
if self.locations[idx] != 0 {
let envelope: &Envelope =
&context.accounts[self.cursor_pos.0].get_env(&self.locations[idx]);
let envelope: EnvelopeRef = context.accounts[self.cursor_pos.0]
.collection
.get_env(self.locations[idx]);
let fg_color = if !envelope.is_seen() {
Color::Byte(0)
@ -297,7 +298,7 @@ impl ThreadListing {
let mut indentations: Vec<bool> = Vec::with_capacity(6);
let mut thread_idx = 0; // needed for alternate thread colors
/* Draw threaded view. */
threads.sort_by(self.sort, self.subsort, &account.collection);
threads.sort_by(self.sort, self.subsort, &account.collection.envelopes);
let thread_nodes: &FnvHashMap<ThreadHash, ThreadNode> = &threads.thread_nodes();
let mut iter = threads.threads_iter().peekable();
/* This is just a desugared for loop so that we can use .peek() */
@ -309,7 +310,8 @@ impl ThreadListing {
thread_idx += 1;
}
if thread_node.has_message() {
let envelope: &Envelope = &account.get_env(&thread_node.message().unwrap());
let envelope: EnvelopeRef =
account.collection.get_env(thread_node.message().unwrap());
self.locations.push(envelope.hash());
let fg_color = if !envelope.is_seen() {
Color::Byte(0)
@ -325,7 +327,7 @@ impl ThreadListing {
};
let (x, _) = write_string_to_grid(
&ThreadListing::make_thread_entry(
envelope,
&envelope,
idx,
indentation,
thread_hash,
@ -378,8 +380,9 @@ impl ThreadListing {
return;
}
if self.locations[idx] != 0 {
let envelope: &Envelope =
&context.accounts[self.cursor_pos.0].get_env(&self.locations[idx]);
let envelope: EnvelopeRef = context.accounts[self.cursor_pos.0]
.collection
.get_env(self.locations[idx]);
let fg_color = if !envelope.is_seen() {
Color::Byte(0)
@ -509,8 +512,10 @@ impl Component for ThreadListing {
if self.length == 0 {
false
} else {
let account = &mut context.accounts[self.cursor_pos.0];
let envelope: &Envelope = &account.get_env(&self.locations[self.cursor_pos.2]);
let account = &context.accounts[self.cursor_pos.0];
let envelope: EnvelopeRef = account
.collection
.get_env(self.locations[self.cursor_pos.2]);
envelope.is_seen()
}
};

View File

@ -317,12 +317,13 @@ impl Component for MailView {
return;
}
let (hash, is_seen) = {
let envelope: &Envelope = &account.get_env(&self.coordinates.2);
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
(envelope.hash(), envelope.is_seen())
};
if !is_seen {
let op = account.operation(hash);
let envelope: &mut Envelope = &mut account.get_env_mut(&self.coordinates.2);
let mut envelope: EnvelopeRefMut =
account.collection.get_env_mut(self.coordinates.2);
if let Err(e) = envelope.set_seen(op) {
context
.replies
@ -332,7 +333,7 @@ impl Component for MailView {
))));
}
}
let envelope: &Envelope = &account.get_env(&self.coordinates.2);
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
let header_fg = if context.settings.terminal.theme == "light" {
Color::Black
@ -459,7 +460,7 @@ impl Component for MailView {
ref archive,
ref post,
ref unsubscribe,
}) = list_management::detect(envelope)
}) = list_management::detect(&envelope)
{
let mut x = get_x(upper_left);
y += 1;
@ -577,7 +578,7 @@ impl Component for MailView {
if self.dirty {
let body = {
let account = &mut context.accounts[self.coordinates.0];
let envelope: &Envelope = &account.get_env(&self.coordinates.2);
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
let op = account.operation(envelope.hash());
match envelope.body(op) {
Ok(body) => body,
@ -615,7 +616,7 @@ impl Component for MailView {
ViewMode::Raw => {
let text = {
let account = &mut context.accounts[self.coordinates.0];
let envelope: &Envelope = &account.get_env(&self.coordinates.2);
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
let mut op = account.operation(envelope.hash());
op.as_bytes()
.map(|v| String::from_utf8_lossy(v).into_owned())
@ -714,7 +715,7 @@ impl Component for MailView {
match *event {
UIEvent::Input(Key::Char('c')) if !self.mode.is_contact_selector() => {
let account = &mut context.accounts[self.coordinates.0];
let envelope: &Envelope = &account.get_env(&self.coordinates.2);
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
let mut entries = Vec::new();
for addr in envelope.from().iter().chain(envelope.to().iter()) {
@ -723,6 +724,7 @@ impl Component for MailView {
new_card.set_name(addr.get_display_name());
entries.push((new_card, format!("{}", addr)));
}
drop(envelope);
self.mode = ViewMode::ContactSelector(Selector::new(
"select contacts to add",
entries,
@ -777,7 +779,7 @@ impl Component for MailView {
{
let account = &mut context.accounts[self.coordinates.0];
let envelope: &Envelope = &account.get_env(&self.coordinates.2);
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
let op = account.operation(envelope.hash());
let attachments = match envelope.body(op) {
@ -912,7 +914,7 @@ impl Component for MailView {
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
let url = {
let account = &mut context.accounts[self.coordinates.0];
let envelope: &Envelope = &account.get_env(&self.coordinates.2);
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
let finder = LinkFinder::new();
let op = account.operation(envelope.hash());
let t = match envelope.body(op) {
@ -973,8 +975,8 @@ impl Component for MailView {
* arrive */
return true;
}
let envelope: &Envelope = &account.get_env(&self.coordinates.2);
if let Some(actions) = list_management::detect(envelope) {
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
if let Some(actions) = list_management::detect(&envelope) {
match e {
MailingListAction::ListPost if actions.post.is_some() => {
/* open composer */

View File

@ -165,7 +165,7 @@ impl ThreadView {
self.entries.clear();
for (line, (ind, thread_hash)) in thread_iter.enumerate() {
let entry = if let Some(msg_hash) = threads.thread_nodes()[&thread_hash].message() {
let seen: bool = account.get_env(&msg_hash).is_seen();
let seen: bool = account.collection.get_env(msg_hash).is_seen();
self.make_entry((ind, thread_hash, line), msg_hash, seen)
} else {
continue;
@ -190,7 +190,9 @@ impl ThreadView {
let mut highlight_reply_subjects: Vec<Option<usize>> =
Vec::with_capacity(self.entries.len());
for e in &mut self.entries {
let envelope: &Envelope = &context.accounts[self.coordinates.0].get_env(&e.msg_hash);
let envelope: EnvelopeRef = context.accounts[self.coordinates.0]
.collection
.get_env(e.msg_hash);
let thread_node = &threads.thread_nodes()[&e.index.1];
let string = if thread_node.show_subject() {
let subject = envelope.subject();
@ -265,8 +267,9 @@ impl ThreadView {
true,
);
{
let envelope: &Envelope =
&context.accounts[self.coordinates.0].get_env(&e.msg_hash);
let envelope: EnvelopeRef = context.accounts[self.coordinates.0]
.collection
.get_env(e.msg_hash);
if envelope.has_attachments() {
content[(e.index.0 * 4 + e.heading.grapheme_width(), 2 * y)]
.set_fg(Color::Byte(103));
@ -342,8 +345,9 @@ impl ThreadView {
false,
);
{
let envelope: &Envelope =
&context.accounts[self.coordinates.0].get_env(&e.msg_hash);
let envelope: EnvelopeRef = context.accounts[self.coordinates.0]
.collection
.get_env(e.msg_hash);
if envelope.has_attachments() {
content[(e.index.0 * 4 + e.heading.grapheme_width(), 2 * y)]
.set_fg(Color::Byte(103));
@ -624,7 +628,7 @@ impl ThreadView {
}
threads.thread_nodes()[&iter_ptr].message().unwrap()
};
let envelope: &Envelope = account.get_env(&i);
let envelope: EnvelopeRef = account.collection.get_env(i);
let (x, y) = write_string_to_grid(
&envelope.subject(),
@ -710,7 +714,7 @@ impl ThreadView {
}
threads.thread_nodes()[&iter_ptr].message().unwrap()
};
let envelope: &Envelope = account.get_env(&i);
let envelope: EnvelopeRef = account.collection.get_env(i);
let (x, y) = write_string_to_grid(
&envelope.subject(),
@ -954,7 +958,7 @@ impl Component for ThreadView {
.message()
.unwrap()
};
let envelope: &Envelope = &account.get_env(&i);
let envelope: EnvelopeRef = account.collection.get_env(i);
let op = account.operation(envelope.hash());
debug!(
"sending action edit for {}, {}",
@ -1061,7 +1065,7 @@ impl Component for ThreadView {
for e in self.entries.iter_mut() {
if e.msg_hash == *old_hash {
e.msg_hash = *new_hash;
let seen: bool = account.get_env(&new_hash).is_seen();
let seen: bool = account.collection.get_env(*new_hash).is_seen();
if seen != e.seen {
self.dirty = true;
}

View File

@ -1533,7 +1533,8 @@ impl Component for Tabbed {
format!(
"Failed to open envelope {}: {}",
context.accounts[account_pos]
.get_env(&msg)
.collection
.get_env(msg)
.message_id_display(),
e.to_string()
),

View File

@ -484,7 +484,7 @@ impl Account {
}
RefreshEventKind::Create(envelope) => {
let env_hash = envelope.hash();
if self.collection.envelopes.contains_key(&env_hash)
if self.collection.contains_key(&env_hash)
&& mailbox!(&folder_hash, self.folders)
.envelopes
.contains(&env_hash)
@ -492,6 +492,14 @@ impl Account {
return None;
}
mailbox!(&folder_hash, self.folders).insert(env_hash);
let (is_seen, is_draft) =
{ (envelope.is_seen(), envelope.flags().contains(Flag::DRAFT)) };
let (subject, from) = {
(
envelope.subject().into_owned(),
envelope.field_from_to_string(),
)
};
self.collection.insert(*envelope, folder_hash);
if self
.sent_folder
@ -507,20 +515,23 @@ impl Account {
if folder_conf.ignore.is_true() {
return Some(UIEvent::MailboxUpdate((self.index, folder_hash)));
}
let (_, thread_node) = self.mail_and_thread(env_hash, folder_hash);
let thread_node = {
let thread_hash = &mut self.collection.get_env(env_hash).thread();
&self.collection.threads[&folder_hash][&thread_hash]
};
if thread_node.snoozed() {
return Some(UIEvent::MailboxUpdate((self.index, folder_hash)));
}
let env = self.get_env(&env_hash);
if env.is_seen() || env.flags().contains(Flag::DRAFT) {
if is_seen || is_draft {
return Some(UIEvent::MailboxUpdate((self.index, folder_hash)));
}
return Some(Notification(
Some(format!("new e-mail from: {}", env.field_from_to_string())),
Some(format!("new e-mail from: {}", from)),
format!(
"{}\n{} {}",
env.subject(),
subject,
self.name,
ref_folders[&folder_hash].name(),
),
@ -725,12 +736,6 @@ impl Account {
}
}
pub fn get_env(&self, h: &EnvelopeHash) -> &Envelope {
&self.collection[h]
}
pub fn get_env_mut(&mut self, h: &EnvelopeHash) -> &mut Envelope {
self.collection.entry(*h).or_default()
}
pub fn contains_key(&self, h: EnvelopeHash) -> bool {
self.collection.contains_key(&h)
}
@ -752,33 +757,10 @@ impl Account {
}
debug!("didn't find {}", h);
debug!(&self.folders);
debug!(&self.collection.envelopes);
//debug!(&self.collection.envelopes);
unreachable!()
}
pub fn thread_to_mail_mut(&mut self, h: ThreadHash, f: FolderHash) -> &mut Envelope {
self.collection
.envelopes
.entry(self.collection.threads[&f].thread_to_mail(h))
.or_default()
}
pub fn thread_to_mail(&self, h: ThreadHash, f: FolderHash) -> &Envelope {
&self.collection.envelopes[&self.collection.threads[&f].thread_to_mail(h)]
}
pub fn threaded_mail(&self, h: ThreadHash, f: FolderHash) -> EnvelopeHash {
self.collection.threads[&f].thread_to_mail(h)
}
pub fn mail_and_thread(
&mut self,
i: EnvelopeHash,
f: FolderHash,
) -> (&mut Envelope, &ThreadNode) {
let thread;
{
let x = &mut self.collection.envelopes.entry(i).or_default();
thread = &self.collection.threads[&f][&x.thread()];
}
(self.collection.envelopes.entry(i).or_default(), thread)
}
pub fn thread(&self, h: ThreadHash, f: FolderHash) -> &ThreadNode {
&self.collection.threads[&f].thread_nodes()[&h]
}
@ -836,9 +818,11 @@ impl Account {
#[cfg(not(feature = "sqlite3"))]
{
let mut ret = StackVec::new();
let envelopes = self.collection.envelopes.clone().read();
let envelopes = envelopes.unwrap();
for env_hash in self.folders[folder_hash].as_result()?.envelopes {
let envelope = &account.collection[&env_hash];
let envelope = &envelopes[&env_hash];
if envelope.subject().contains(&search_term) {
ret.push(env_hash);
continue;

View File

@ -169,17 +169,19 @@ pub fn insert(context: &crate::state::Context) -> Result<()> {
.map_err(|e| MeliError::new(e.to_string()))?,
)
.map_err(|e| MeliError::new(e.to_string()))?;
for acc in context.accounts.iter() {
debug!("inserting {} envelopes", acc.collection.envelopes.len());
for e in acc.collection.envelopes.values() {
conn.execute(
"INSERT OR REPLACE INTO envelopes (hash, date, _from, _to, cc, bcc, subject, message_id, in_reply_to, _references, flags, has_attachments, body_text, timestamp)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14)",
params![e.hash().to_be_bytes().to_vec(), e.date_as_str(), e.field_from_to_string(), e.field_to_to_string(), e.field_cc_to_string(), e.field_bcc_to_string(), e.subject().into_owned().trim_end_matches('\u{0}'), e.message_id_display().to_string(), e.in_reply_to_display().map(|f| f.to_string()).unwrap_or(String::new()), e.field_references_to_string(), i64::from(e.flags().bits()), if e.has_attachments() { 1 } else { 0 }, String::from("sdfsa"), e.date().to_be_bytes().to_vec()],
)
.map_err(|e| MeliError::new(e.to_string()))?;
/*
for acc in context.accounts.iter() {
debug!("inserting {} envelopes", acc.collection.envelopes.len());
for e in acc.collection.envelopes.values() {
conn.execute(
"INSERT OR REPLACE INTO envelopes (hash, date, _from, _to, cc, bcc, subject, message_id, in_reply_to, _references, flags, has_attachments, body_text, timestamp)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14)",
params![e.hash().to_be_bytes().to_vec(), e.date_as_str(), e.field_from_to_string(), e.field_to_to_string(), e.field_cc_to_string(), e.field_bcc_to_string(), e.subject().into_owned().trim_end_matches('\u{0}'), e.message_id_display().to_string(), e.in_reply_to_display().map(|f| f.to_string()).unwrap_or(String::new()), e.field_references_to_string(), i64::from(e.flags().bits()), if e.has_attachments() { 1 } else { 0 }, String::from("sdfsa"), e.date().to_be_bytes().to_vec()],
)
.map_err(|e| MeliError::new(e.to_string()))?;
}
}
}
*/
Ok(())
}