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);
tx.execute(
"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))?;
}
}
@ -586,16 +586,13 @@ mod sqlite3_m {
)?;
let x = stmt
.query_map(
sqlite3::params![mailbox_hash as i64, env_hash as i64],
|row| {
Ok((
row.get(0).map(|u: Sqlite3UID| u as UID)?,
row.get(1)?,
row.get(2)?,
))
},
)?
.query_map(sqlite3::params![mailbox_hash as i64, env_hash], |row| {
Ok((
row.get(0).map(|u: Sqlite3UID| u as UID)?,
row.get(1)?,
row.get(2)?,
))
})?
.collect::<std::result::Result<_, _>>()?;
x
}
@ -635,10 +632,9 @@ mod sqlite3_m {
"SELECT rfc822 FROM envelopes WHERE mailbox_hash = ?1 AND hash = ?2;",
)?;
let x = stmt
.query_map(
sqlite3::params![mailbox_hash as i64, env_hash as i64],
|row| row.get(0),
)?
.query_map(sqlite3::params![mailbox_hash as i64, env_hash], |row| {
row.get(0)
})?
.collect::<std::result::Result<_, _>>()?;
x
}

View File

@ -1336,7 +1336,7 @@ pub fn envelope(input: &[u8]) -> IResult<&[u8], Envelope> {
Ok((
input,
({
let mut env = Envelope::new(0);
let mut env = Envelope::new(EnvelopeHash::default());
if let Some(date) = date {
env.set_date(&date);
if let Ok(d) =
@ -1760,5 +1760,5 @@ pub fn generate_envelope_hash(mailbox_path: &str, uid: &UID) -> EnvelopeHash {
let mut h = DefaultHasher::new();
h.write_usize(*uid);
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_json::value::RawValue;
use serde_json::Value;
use std::collections::hash_map::DefaultHasher;
use std::collections::HashMap;
use std::hash::Hasher;
mod import;
pub use import::*;
@ -42,9 +40,7 @@ impl Object for ThreadObject {
impl Id<EmailObject> {
pub fn into_hash(&self) -> EnvelopeHash {
let mut h = DefaultHasher::new();
h.write(self.inner.as_bytes());
h.finish()
EnvelopeHash::from_bytes(self.inner.as_bytes())
}
}
@ -250,7 +246,7 @@ impl std::fmt::Display for EmailAddress {
impl std::convert::From<EmailObject> for 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()) {
env.set_datetime(d);
}
@ -327,7 +323,6 @@ impl std::convert::From<EmailObject> for crate::Envelope {
}
}
env.set_hash(t.id.into_hash());
env
}
}

View File

@ -150,7 +150,7 @@ macro_rules! get_path_hash {
pub fn get_file_hash(file: &Path) -> EnvelopeHash {
let mut hasher = DefaultHasher::default();
file.hash(&mut hasher);
hasher.finish()
EnvelopeHash(hasher.finish())
}
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();
hasher.write(num.as_bytes());
hasher.write(message_id.unwrap_or_default().as_bytes());
hasher.finish()
EnvelopeHash(hasher.finish())
};
let mut env = Envelope::new(env_hash);
if let Some(date) = date {

View File

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

View File

@ -58,11 +58,7 @@ impl<'m> Message<'m> {
pub fn env_hash(&self) -> EnvelopeHash {
let msg_id = unsafe { call!(self.lib, notmuch_message_get_message_id)(self.message) };
let c_str = unsafe { CStr::from_ptr(msg_id) };
{
let mut hasher = DefaultHasher::default();
c_str.hash(&mut hasher);
hasher.finish()
}
EnvelopeHash::from_bytes(c_str.to_bytes_with_nul())
}
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.
///
@ -244,7 +268,7 @@ impl core::fmt::Debug for Envelope {
impl Default for Envelope {
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> {
let mut h = DefaultHasher::new();
h.write(bytes);
let mut e = Envelope::new(h.finish());
let mut e = Envelope::new(EnvelopeHash::from_bytes(bytes));
let res = e.populate_headers(bytes).ok();
if res.is_some() {
if let Some(f) = flags {
@ -396,7 +418,7 @@ impl Envelope {
}
if self.message_id.raw().is_empty() {
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 let Some(pos) = self

View File

@ -90,7 +90,7 @@ impl FromStr for Draft {
ret.headers
.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()))?;

View File

@ -19,7 +19,7 @@
* 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};
pub use rusqlite::{self, params, Connection};
use std::path::PathBuf;
@ -159,3 +159,17 @@ impl FromSql for Envelope {
.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},
email::{Envelope, EnvelopeHash},
log,
sqlite3::{
self as melib_sqlite3,
rusqlite::{self, params},
DatabaseDescription,
},
sqlite3::{self as melib_sqlite3, rusqlite::params, DatabaseDescription},
thread::{SortField, SortOrder},
MeliError, Result, ERROR,
};
use smallvec::SmallVec;
use std::convert::TryInto;
use std::path::PathBuf;
use std::sync::{Arc, RwLock};
@ -367,16 +362,9 @@ pub fn search(
.map_err(|e| MeliError::new(e.to_string()))?;
let results = stmt
.query_map([], |row| row.get(0))
.map_err(|e| MeliError::new(e.to_string()))?
.map(|r: std::result::Result<Vec<u8>, rusqlite::Error>| {
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()))?,
))
})
.query_map([], |row| row.get::<_, EnvelopeHash>(0))
.map_err(MeliError::from)?
.map(|item| item.map_err(MeliError::from))
.collect::<Result<SmallVec<[EnvelopeHash; 512]>>>();
Ok(Box::pin(async { results }))
}