Convert EnvelopeHash from typedef to wrapper struct

pull/170/head
Manos Pitsidianakis 2022-12-08 20:43:52 +02:00
parent 2427b097c5
commit 7382e30160
11 changed files with 71 additions and 57 deletions

View File

@ -464,7 +464,7 @@ mod sqlite3_m {
max_uid = std::cmp::max(max_uid, *uid); max_uid = std::cmp::max(max_uid, *uid);
tx.execute( tx.execute(
"INSERT OR REPLACE INTO envelopes (hash, uid, mailbox_hash, modsequence, envelope) VALUES (?1, ?2, ?3, ?4, ?5)", "INSERT OR REPLACE INTO envelopes (hash, uid, mailbox_hash, modsequence, envelope) VALUES (?1, ?2, ?3, ?4, ?5)",
sqlite3::params![envelope.hash() as i64, *uid as Sqlite3UID, mailbox_hash as i64, modseq, &envelope], sqlite3::params![envelope.hash(), *uid as Sqlite3UID, mailbox_hash as i64, modseq, &envelope],
).chain_err_summary(|| format!("Could not insert envelope {} {} in header_cache of account {}", envelope.message_id(), envelope.hash(), uid_store.account_name))?; ).chain_err_summary(|| format!("Could not insert envelope {} {} in header_cache of account {}", envelope.message_id(), envelope.hash(), uid_store.account_name))?;
} }
} }
@ -586,16 +586,13 @@ mod sqlite3_m {
)?; )?;
let x = stmt let x = stmt
.query_map( .query_map(sqlite3::params![mailbox_hash as i64, env_hash], |row| {
sqlite3::params![mailbox_hash as i64, env_hash as i64], Ok((
|row| { row.get(0).map(|u: Sqlite3UID| u as UID)?,
Ok(( row.get(1)?,
row.get(0).map(|u: Sqlite3UID| u as UID)?, row.get(2)?,
row.get(1)?, ))
row.get(2)?, })?
))
},
)?
.collect::<std::result::Result<_, _>>()?; .collect::<std::result::Result<_, _>>()?;
x x
} }
@ -635,10 +632,9 @@ mod sqlite3_m {
"SELECT rfc822 FROM envelopes WHERE mailbox_hash = ?1 AND hash = ?2;", "SELECT rfc822 FROM envelopes WHERE mailbox_hash = ?1 AND hash = ?2;",
)?; )?;
let x = stmt let x = stmt
.query_map( .query_map(sqlite3::params![mailbox_hash as i64, env_hash], |row| {
sqlite3::params![mailbox_hash as i64, env_hash as i64], row.get(0)
|row| row.get(0), })?
)?
.collect::<std::result::Result<_, _>>()?; .collect::<std::result::Result<_, _>>()?;
x x
} }

View File

@ -1336,7 +1336,7 @@ pub fn envelope(input: &[u8]) -> IResult<&[u8], Envelope> {
Ok(( Ok((
input, input,
({ ({
let mut env = Envelope::new(0); let mut env = Envelope::new(EnvelopeHash::default());
if let Some(date) = date { if let Some(date) = date {
env.set_date(&date); env.set_date(&date);
if let Ok(d) = if let Ok(d) =
@ -1760,5 +1760,5 @@ pub fn generate_envelope_hash(mailbox_path: &str, uid: &UID) -> EnvelopeHash {
let mut h = DefaultHasher::new(); let mut h = DefaultHasher::new();
h.write_usize(*uid); h.write_usize(*uid);
h.write(mailbox_path.as_bytes()); h.write(mailbox_path.as_bytes());
h.finish() EnvelopeHash(h.finish())
} }

View File

@ -26,9 +26,7 @@ use core::marker::PhantomData;
use serde::de::{Deserialize, Deserializer}; use serde::de::{Deserialize, Deserializer};
use serde_json::value::RawValue; use serde_json::value::RawValue;
use serde_json::Value; use serde_json::Value;
use std::collections::hash_map::DefaultHasher;
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::Hasher;
mod import; mod import;
pub use import::*; pub use import::*;
@ -42,9 +40,7 @@ impl Object for ThreadObject {
impl Id<EmailObject> { impl Id<EmailObject> {
pub fn into_hash(&self) -> EnvelopeHash { pub fn into_hash(&self) -> EnvelopeHash {
let mut h = DefaultHasher::new(); EnvelopeHash::from_bytes(self.inner.as_bytes())
h.write(self.inner.as_bytes());
h.finish()
} }
} }
@ -250,7 +246,7 @@ impl std::fmt::Display for EmailAddress {
impl std::convert::From<EmailObject> for crate::Envelope { impl std::convert::From<EmailObject> for crate::Envelope {
fn from(mut t: EmailObject) -> crate::Envelope { fn from(mut t: EmailObject) -> crate::Envelope {
let mut env = crate::Envelope::new(0); let mut env = crate::Envelope::new(t.id.into_hash());
if let Ok(d) = crate::email::parser::dates::rfc5322_date(env.date_as_str().as_bytes()) { if let Ok(d) = crate::email::parser::dates::rfc5322_date(env.date_as_str().as_bytes()) {
env.set_datetime(d); env.set_datetime(d);
} }
@ -327,7 +323,6 @@ impl std::convert::From<EmailObject> for crate::Envelope {
} }
} }
env.set_hash(t.id.into_hash());
env env
} }
} }

View File

@ -150,7 +150,7 @@ macro_rules! get_path_hash {
pub fn get_file_hash(file: &Path) -> EnvelopeHash { pub fn get_file_hash(file: &Path) -> EnvelopeHash {
let mut hasher = DefaultHasher::default(); let mut hasher = DefaultHasher::default();
file.hash(&mut hasher); file.hash(&mut hasher);
hasher.finish() EnvelopeHash(hasher.finish())
} }
pub fn move_to_cur(p: PathBuf) -> Result<PathBuf> { pub fn move_to_cur(p: PathBuf) -> Result<PathBuf> {

View File

@ -119,7 +119,7 @@ pub fn over_article(input: &str) -> IResult<&str, (UID, Envelope)> {
let mut hasher = DefaultHasher::new(); let mut hasher = DefaultHasher::new();
hasher.write(num.as_bytes()); hasher.write(num.as_bytes());
hasher.write(message_id.unwrap_or_default().as_bytes()); hasher.write(message_id.unwrap_or_default().as_bytes());
hasher.finish() EnvelopeHash(hasher.finish())
}; };
let mut env = Envelope::new(env_hash); let mut env = Envelope::new(env_hash);
if let Some(date) = date { if let Some(date) = date {

View File

@ -903,8 +903,11 @@ impl MailBackend for NotmuchDb {
s.push(' '); s.push(' ');
s s
} else { } else {
return Err(MeliError::new("Mailbox with hash {} not found!") return Err(MeliError::new(format!(
.set_kind(crate::error::ErrorKind::Bug)); "Mailbox with hash {} not found!",
mailbox_hash
))
.set_kind(crate::error::ErrorKind::Bug));
} }
} else { } else {
String::new() String::new()

View File

@ -58,11 +58,7 @@ impl<'m> Message<'m> {
pub fn env_hash(&self) -> EnvelopeHash { pub fn env_hash(&self) -> EnvelopeHash {
let msg_id = unsafe { call!(self.lib, notmuch_message_get_message_id)(self.message) }; let msg_id = unsafe { call!(self.lib, notmuch_message_get_message_id)(self.message) };
let c_str = unsafe { CStr::from_ptr(msg_id) }; let c_str = unsafe { CStr::from_ptr(msg_id) };
{ EnvelopeHash::from_bytes(c_str.to_bytes_with_nul())
let mut hasher = DefaultHasher::default();
c_str.hash(&mut hasher);
hasher.finish()
}
} }
pub fn header(&self, header: &CStr) -> Option<&[u8]> { pub fn header(&self, header: &CStr) -> Option<&[u8]> {

View File

@ -198,7 +198,31 @@ impl Mail {
} }
} }
pub type EnvelopeHash = u64; #[derive(
Hash, Eq, PartialEq, Debug, Ord, PartialOrd, Default, Serialize, Deserialize, Copy, Clone,
)]
#[repr(transparent)]
pub struct EnvelopeHash(pub u64);
impl EnvelopeHash {
#[inline(always)]
pub fn from_bytes(bytes: &[u8]) -> Self {
let mut h = DefaultHasher::new();
h.write(bytes);
Self(h.finish())
}
#[inline(always)]
pub const fn to_be_bytes(self) -> [u8; 8] {
self.0.to_be_bytes()
}
}
impl core::fmt::Display for EnvelopeHash {
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(fmt, "{}", self.0)
}
}
/// `Envelope` represents all the header and structure data of an email we need to know. /// `Envelope` represents all the header and structure data of an email we need to know.
/// ///
@ -244,7 +268,7 @@ impl core::fmt::Debug for Envelope {
impl Default for Envelope { impl Default for Envelope {
fn default() -> Self { fn default() -> Self {
Envelope::new(0) Envelope::new(EnvelopeHash::default())
} }
} }
@ -276,9 +300,7 @@ impl Envelope {
} }
pub fn from_bytes(bytes: &[u8], flags: Option<Flag>) -> Result<Envelope> { pub fn from_bytes(bytes: &[u8], flags: Option<Flag>) -> Result<Envelope> {
let mut h = DefaultHasher::new(); let mut e = Envelope::new(EnvelopeHash::from_bytes(bytes));
h.write(bytes);
let mut e = Envelope::new(h.finish());
let res = e.populate_headers(bytes).ok(); let res = e.populate_headers(bytes).ok();
if res.is_some() { if res.is_some() {
if let Some(f) = flags { if let Some(f) = flags {
@ -396,7 +418,7 @@ impl Envelope {
} }
if self.message_id.raw().is_empty() { if self.message_id.raw().is_empty() {
let hash = self.hash; let hash = self.hash;
self.set_message_id(format!("<{:x}>", hash).as_bytes()); self.set_message_id(format!("<{:x}>", hash.0).as_bytes());
} }
if self.references.is_some() { if self.references.is_some() {
if let Some(pos) = self if let Some(pos) = self

View File

@ -90,7 +90,7 @@ impl FromStr for Draft {
ret.headers ret.headers
.insert(k.try_into()?, String::from_utf8(v.to_vec())?); .insert(k.try_into()?, String::from_utf8(v.to_vec())?);
} }
let body = Envelope::new(0).body_bytes(s.as_bytes()); let body = Envelope::new(EnvelopeHash::default()).body_bytes(s.as_bytes());
ret.body = String::from_utf8(body.decode(Default::default()))?; ret.body = String::from_utf8(body.decode(Default::default()))?;

View File

@ -19,7 +19,7 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>. * along with meli. If not, see <http://www.gnu.org/licenses/>.
*/ */
use crate::{error::*, logging::log, Envelope}; use crate::{error::*, logging::log, Envelope, EnvelopeHash};
use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput}; use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput};
pub use rusqlite::{self, params, Connection}; pub use rusqlite::{self, params, Connection};
use std::path::PathBuf; use std::path::PathBuf;
@ -159,3 +159,17 @@ impl FromSql for Envelope {
.map_err(|e| FromSqlError::Other(Box::new(e))) .map_err(|e| FromSqlError::Other(Box::new(e)))
} }
} }
impl ToSql for EnvelopeHash {
fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
Ok(ToSqlOutput::from(self.0 as i64))
}
}
impl FromSql for EnvelopeHash {
fn column_result(value: rusqlite::types::ValueRef) -> FromSqlResult<Self> {
let b: i64 = FromSql::column_result(value)?;
Ok(EnvelopeHash(b as u64))
}
}

View File

@ -30,17 +30,12 @@ use melib::{
backends::{MailBackend, ResultFuture}, backends::{MailBackend, ResultFuture},
email::{Envelope, EnvelopeHash}, email::{Envelope, EnvelopeHash},
log, log,
sqlite3::{ sqlite3::{self as melib_sqlite3, rusqlite::params, DatabaseDescription},
self as melib_sqlite3,
rusqlite::{self, params},
DatabaseDescription,
},
thread::{SortField, SortOrder}, thread::{SortField, SortOrder},
MeliError, Result, ERROR, MeliError, Result, ERROR,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
use std::convert::TryInto;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
@ -367,16 +362,9 @@ pub fn search(
.map_err(|e| MeliError::new(e.to_string()))?; .map_err(|e| MeliError::new(e.to_string()))?;
let results = stmt let results = stmt
.query_map([], |row| row.get(0)) .query_map([], |row| row.get::<_, EnvelopeHash>(0))
.map_err(|e| MeliError::new(e.to_string()))? .map_err(MeliError::from)?
.map(|r: std::result::Result<Vec<u8>, rusqlite::Error>| { .map(|item| item.map_err(MeliError::from))
Ok(u64::from_be_bytes(
r.map_err(|e| MeliError::new(e.to_string()))?
.as_slice()
.try_into()
.map_err(|e: std::array::TryFromSliceError| MeliError::new(e.to_string()))?,
))
})
.collect::<Result<SmallVec<[EnvelopeHash; 512]>>>(); .collect::<Result<SmallVec<[EnvelopeHash; 512]>>>();
Ok(Box::pin(async { results })) Ok(Box::pin(async { results }))
} }