From db693492510ac24527154917daeefc0717460b51 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Tue, 5 Jan 2021 01:13:13 +0200 Subject: [PATCH] melib/notmuch: avoid parsing entire email in Envelope creation --- melib/src/backends/notmuch.rs | 66 +++++++++------------ melib/src/backends/notmuch/message.rs | 85 ++++++++++++++++++++++----- 2 files changed, 98 insertions(+), 53 deletions(-) diff --git a/melib/src/backends/notmuch.rs b/melib/src/backends/notmuch.rs index 2ea0a8c77..ea98d7246 100644 --- a/melib/src/backends/notmuch.rs +++ b/melib/src/backends/notmuch.rs @@ -22,7 +22,7 @@ use crate::backends::*; use crate::conf::AccountSettings; use crate::email::{Envelope, EnvelopeHash, Flag}; -use crate::error::{MeliError, Result, ResultIntoMeliError}; +use crate::error::{MeliError, Result}; use crate::shellexpand::ShellExpandTrait; use smallvec::SmallVec; use std::collections::{ @@ -130,31 +130,25 @@ impl DbConnection { } } else { let message_id = message.msg_id_cstr().to_string_lossy().to_string(); - match message.into_envelope(index.clone(), tag_index.clone()) { - Ok(env) => { - for (&mailbox_hash, m) in mailboxes_lck.iter() { - let query_str = format!("{} id:{}", m.query_str.as_str(), &message_id); - let query: Query = Query::new(self, &query_str)?; - if query.count().unwrap_or(0) > 0 { - let mut total_lck = m.total.lock().unwrap(); - let mut unseen_lck = m.unseen.lock().unwrap(); - *total_lck += 1; - if !env.is_seen() { - *unseen_lck += 1; - } - (event_consumer)( - account_hash, - BackendEvent::Refresh(RefreshEvent { - account_hash, - mailbox_hash, - kind: Create(Box::new(env.clone())), - }), - ); - } + let env = message.into_envelope(&index, &tag_index); + for (&mailbox_hash, m) in mailboxes_lck.iter() { + let query_str = format!("{} id:{}", m.query_str.as_str(), &message_id); + let query: Query = Query::new(self, &query_str)?; + if query.count().unwrap_or(0) > 0 { + let mut total_lck = m.total.lock().unwrap(); + let mut unseen_lck = m.unseen.lock().unwrap(); + *total_lck += 1; + if !env.is_seen() { + *unseen_lck += 1; } - } - Err(err) => { - debug!("could not parse message {:?}", err); + (event_consumer)( + account_hash, + BackendEvent::Refresh(RefreshEvent { + account_hash, + mailbox_hash, + kind: Create(Box::new(env.clone())), + }), + ); } } } @@ -481,21 +475,15 @@ impl MailBackend for NotmuchDb { } else { continue; }; - match message.into_envelope(self.index.clone(), self.tag_index.clone()) { - Ok(env) => { - mailbox_index_lck - .entry(env.hash()) - .or_default() - .push(self.mailbox_hash); - if !env.is_seen() { - unseen_count += 1; - } - ret.push(env); - } - Err(err) => { - debug!("could not parse message {:?}", err); - } + let env = message.into_envelope(&self.index, &self.tag_index); + mailbox_index_lck + .entry(env.hash()) + .or_default() + .push(self.mailbox_hash); + if !env.is_seen() { + unseen_count += 1; } + ret.push(env); } else { done = true; break; diff --git a/melib/src/backends/notmuch/message.rs b/melib/src/backends/notmuch/message.rs index cf9e2d2a6..3ad5db6c0 100644 --- a/melib/src/backends/notmuch/message.rs +++ b/melib/src/backends/notmuch/message.rs @@ -65,6 +65,16 @@ impl<'m> Message<'m> { } } + pub fn header(&self, header: &CStr) -> Option<&[u8]> { + let header_val = + unsafe { call!(self.lib, notmuch_message_get_header)(self.message, header.as_ptr()) }; + if header_val.is_null() { + None + } else { + Some(unsafe { CStr::from_ptr(header_val).to_bytes() }) + } + } + pub fn msg_id(&self) -> &[u8] { let c_str = self.msg_id_cstr(); c_str.to_bytes() @@ -81,19 +91,11 @@ impl<'m> Message<'m> { pub fn into_envelope( self, - index: Arc>>, - tag_index: Arc>>, - ) -> Result { - let mut contents = Vec::new(); - let path = self.get_filename().to_os_string(); - let mut f = std::fs::File::open(&path)?; - f.read_to_end(&mut contents)?; + index: &RwLock>, + tag_index: &RwLock>, + ) -> Envelope { let env_hash = self.env_hash(); - let mut env = Envelope::from_bytes(&contents, None).chain_err_summary(|| { - index.write().unwrap().remove(&env_hash); - format!("could not parse path {:?}", path) - })?; - env.set_hash(env_hash); + let mut env = Envelope::new(env_hash); index .write() .unwrap() @@ -109,8 +111,63 @@ impl<'m> Message<'m> { } env.labels_mut().push(num); } - env.set_flags(flags); - Ok(env) + unsafe { + use crate::email::parser::address::rfc2822address_list; + env.set_message_id(self.msg_id()) + .set_date( + self.header(CStr::from_bytes_with_nul_unchecked(b"Date\0")) + .unwrap_or_default(), + ) + .set_from( + rfc2822address_list( + self.header(CStr::from_bytes_with_nul_unchecked(b"From\0")) + .unwrap_or_default(), + ) + .map(|(_, v)| v) + .unwrap_or_default(), + ) + .set_to( + rfc2822address_list( + self.header(CStr::from_bytes_with_nul_unchecked(b"To\0")) + .unwrap_or_default(), + ) + .map(|(_, v)| v) + .unwrap_or_default(), + ) + .set_cc( + rfc2822address_list( + self.header(CStr::from_bytes_with_nul_unchecked(b"Cc\0")) + .unwrap_or_default(), + ) + .map(|(_, v)| v) + .unwrap_or_default(), + ) + .set_bcc( + rfc2822address_list( + self.header(CStr::from_bytes_with_nul_unchecked(b"Bcc\0")) + .unwrap_or_default(), + ) + .map(|(_, v)| v) + .unwrap_or_default() + .to_vec(), + ) + .set_subject( + self.header(CStr::from_bytes_with_nul_unchecked(b"Subject\0")) + .unwrap_or_default() + .to_vec(), + ) + .set_references( + self.header(CStr::from_bytes_with_nul_unchecked(b"References\0")) + .unwrap_or_default(), + ) + .set_in_reply_to( + self.header(CStr::from_bytes_with_nul_unchecked(b"In-Reply-To\0")) + .unwrap_or_default(), + ) + .set_datetime(self.date()) + .set_flags(flags); + } + env } pub fn replies_iter(&self) -> Option {