summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2022-12-08 21:34:32 +0200
committerManos Pitsidianakis <el13635@mail.ntua.gr>2022-12-08 22:10:58 +0200
commit259aeb00877557ee85b5cc555d50e605b85b3109 (patch)
tree388da23b582396b4f0481c2ad19f1fef3e880607
parent7382e30160a934ce97dd73c1be44640d5b4a4c75 (diff)
downloadmeli-259aeb00877557ee85b5cc555d50e605b85b3109.zip
Convert {Account,Mailbox}Hash from typedef to wrapper struct
-rw-r--r--melib/src/backends.rs20
-rw-r--r--melib/src/backends/imap.rs21
-rw-r--r--melib/src/backends/imap/cache.rs66
-rw-r--r--melib/src/backends/imap/cache/sync.rs32
-rw-r--r--melib/src/backends/imap/protocol_parser.rs11
-rw-r--r--melib/src/backends/imap/untagged.rs9
-rw-r--r--melib/src/backends/imap/watch.rs4
-rw-r--r--melib/src/backends/jmap.rs48
-rw-r--r--melib/src/backends/jmap/objects/mailbox.rs4
-rw-r--r--melib/src/backends/maildir.rs2
-rw-r--r--melib/src/backends/maildir/backend.rs24
-rw-r--r--melib/src/backends/mbox.rs19
-rw-r--r--melib/src/backends/nntp.rs10
-rw-r--r--melib/src/backends/notmuch.rs30
-rw-r--r--melib/src/backends/notmuch/message.rs8
-rw-r--r--melib/src/collection.rs4
-rw-r--r--melib/src/email.rs41
-rw-r--r--melib/src/lib.rs66
-rw-r--r--melib/src/sqlite3.rs16
-rw-r--r--src/components/mail/compose.rs4
-rw-r--r--src/components/mail/listing.rs18
-rw-r--r--src/components/mail/listing/compact.rs4
-rw-r--r--src/components/mail/listing/conversations.rs4
-rw-r--r--src/components/mail/listing/plain.rs4
-rw-r--r--src/components/mail/listing/thread.rs4
-rw-r--r--src/components/mail/view.rs2
-rw-r--r--src/conf.rs2
-rw-r--r--src/conf/accounts.rs10
-rw-r--r--src/conf/overrides.rs4
-rw-r--r--src/conf/tags.rs27
-rw-r--r--src/main.rs7
-rw-r--r--src/managesieve.rs2
-rw-r--r--src/state.rs16
33 files changed, 245 insertions, 298 deletions
diff --git a/melib/src/backends.rs b/melib/src/backends.rs
index b174abbd..78eec1c2 100644
--- a/melib/src/backends.rs
+++ b/melib/src/backends.rs
@@ -20,16 +20,6 @@
*/
use smallvec::SmallVec;
-#[macro_export]
-macro_rules! tag_hash {
- ($tag:ident) => {{
- use std::collections::hash_map::DefaultHasher;
- use std::hash::Hasher;
- let mut hasher = DefaultHasher::new();
- hasher.write($tag.as_bytes());
- hasher.finish()
- }};
-}
#[cfg(feature = "imap_backend")]
pub mod imap;
@@ -580,8 +570,10 @@ pub trait BackendMailbox: Debug {
fn count(&self) -> Result<(usize, usize)>;
}
-pub type AccountHash = u64;
-pub type MailboxHash = u64;
+crate::declare_u64_hash!(AccountHash);
+crate::declare_u64_hash!(MailboxHash);
+crate::declare_u64_hash!(TagHash);
+
pub type Mailbox = Box<dyn BackendMailbox + Send + Sync>;
impl Clone for Mailbox {
@@ -742,10 +734,10 @@ fn test_lazy_count_set() {
new.set_not_yet_seen(10);
assert_eq!(new.len(), 10);
for i in 0..10 {
- assert!(new.insert_existing(i));
+ assert!(new.insert_existing(EnvelopeHash(i)));
}
assert_eq!(new.len(), 10);
- assert!(!new.insert_existing(10));
+ assert!(!new.insert_existing(EnvelopeHash(10)));
assert_eq!(new.len(), 10);
}
diff --git a/melib/src/backends/imap.rs b/melib/src/backends/imap.rs
index 88be46dd..980812fa 100644
--- a/melib/src/backends/imap.rs
+++ b/melib/src/backends/imap.rs
@@ -19,7 +19,6 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
-use crate::get_path_hash;
use smallvec::SmallVec;
#[macro_use]
mod protocol_parser;
@@ -516,7 +515,7 @@ impl MailBackend for ImapType {
let account_hash = uid_store.account_hash;
main_conn_lck.add_refresh_event(RefreshEvent {
account_hash,
- mailbox_hash: 0,
+ mailbox_hash: MailboxHash::default(),
kind: RefreshEventKind::Failure(err.clone()),
});
return Err(err);
@@ -754,7 +753,7 @@ impl MailBackend for ImapType {
return Err(MeliError::new(format!("Application error: more than one flag bit set in set_flags: {:?}", flags)).set_kind(crate::ErrorKind::Bug));
}
Err(tag) => {
- let hash = tag_hash!(tag);
+ let hash = TagHash::from_bytes(tag.as_bytes());
if !tag_lck.contains_key(&hash) {
tag_lck.insert(hash, tag.to_string());
}
@@ -949,7 +948,7 @@ impl MailBackend for ImapType {
}
let ret: Result<()> = ImapResponse::try_from(response.as_slice())?.into();
ret?;
- let new_hash = get_path_hash!(path.as_str());
+ let new_hash = MailboxHash::from_bytes(path.as_str().as_bytes());
uid_store.mailboxes.lock().await.clear();
Ok((new_hash, new_mailbox_fut?.await.map_err(|err| MeliError::new(format!("Mailbox create was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`", String::from_utf8_lossy(&response), err)))?))
}))
@@ -1086,7 +1085,7 @@ impl MailBackend for ImapType {
.read_response(&mut response, RequiredResponses::empty())
.await?;
}
- let new_hash = get_path_hash!(new_path.as_str());
+ let new_hash = MailboxHash::from_bytes(new_path.as_str().as_bytes());
let ret: Result<()> = ImapResponse::try_from(response.as_slice())?.into();
ret?;
uid_store.mailboxes.lock().await.clear();
@@ -1330,11 +1329,7 @@ impl ImapType {
},
timeout,
};
- let account_hash = {
- let mut hasher = DefaultHasher::new();
- hasher.write(s.name.as_bytes());
- hasher.finish()
- };
+ let account_hash = AccountHash::from_bytes(s.name.as_bytes());
let account_name = Arc::new(s.name().to_string());
let uid_store: Arc<UIDStore> = Arc::new(UIDStore {
keep_offline_cache,
@@ -1486,7 +1481,7 @@ impl ImapType {
debug!("parse error for {:?}", l);
}
}
- mailboxes.retain(|_, v| v.hash != 0);
+ mailboxes.retain(|_, v| !v.hash.is_null());
conn.send_command(b"LSUB \"\" \"*\"").await?;
conn.read_response(&mut res, RequiredResponses::LSUB_REQUIRED)
.await?;
@@ -1824,11 +1819,11 @@ async fn fetch_hlpr(state: &mut FetchState) -> Result<Vec<Envelope>> {
our_unseen.insert(env.hash());
}
for f in keywords {
- let hash = tag_hash!(f);
+ let hash = TagHash::from_bytes(f.as_bytes());
if !tag_lck.contains_key(&hash) {
tag_lck.insert(hash, f.to_string());
}
- env.labels_mut().push(hash);
+ env.tags_mut().push(hash);
}
}
}
diff --git a/melib/src/backends/imap/cache.rs b/melib/src/backends/imap/cache.rs
index 9ee95665..125dccff 100644
--- a/melib/src/backends/imap/cache.rs
+++ b/melib/src/backends/imap/cache.rs
@@ -183,7 +183,7 @@ mod sqlite3_m {
.prepare("SELECT MAX(uid) FROM envelopes WHERE mailbox_hash = ?1;")?;
let mut ret: Vec<UID> = stmt
- .query_map(sqlite3::params![mailbox_hash as i64], |row| {
+ .query_map(sqlite3::params![mailbox_hash], |row| {
row.get(0).map(|i: Sqlite3UID| i as UID)
})?
.collect::<std::result::Result<_, _>>()?;
@@ -211,7 +211,7 @@ mod sqlite3_m {
"SELECT uidvalidity, flags, highestmodseq FROM mailbox WHERE mailbox_hash = ?1;",
)?;
- let mut ret = stmt.query_map(sqlite3::params![mailbox_hash as i64], |row| {
+ let mut ret = stmt.query_map(sqlite3::params![mailbox_hash], |row| {
Ok((
row.get(0).map(|u: Sqlite3UID| u as UID)?,
row.get(1)?,
@@ -253,7 +253,7 @@ mod sqlite3_m {
.or_insert(uidvalidity);
let mut tag_lck = self.uid_store.collection.tag_index.write().unwrap();
for f in to_str!(&flags).split('\0') {
- let hash = tag_hash!(f);
+ let hash = TagHash::from_bytes(f.as_bytes());
//debug!("hash {} flag {}", hash, &f);
if !tag_lck.contains_key(&hash) {
tag_lck.insert(hash, f.to_string());
@@ -277,7 +277,7 @@ mod sqlite3_m {
self.connection
.execute(
"DELETE FROM mailbox WHERE mailbox_hash = ?1",
- sqlite3::params![mailbox_hash as i64],
+ sqlite3::params![mailbox_hash],
)
.chain_err_summary(|| {
format!(
@@ -289,7 +289,7 @@ mod sqlite3_m {
if let Some(Ok(highestmodseq)) = select_response.highestmodseq {
self.connection.execute(
"INSERT OR IGNORE INTO mailbox (uidvalidity, flags, highestmodseq, mailbox_hash) VALUES (?1, ?2, ?3, ?4)",
- sqlite3::params![select_response.uidvalidity as Sqlite3UID, select_response.flags.1.iter().map(|s| s.as_str()).collect::<Vec<&str>>().join("\0").as_bytes(), highestmodseq, mailbox_hash as i64],
+ sqlite3::params![select_response.uidvalidity as Sqlite3UID, select_response.flags.1.iter().map(|s| s.as_str()).collect::<Vec<&str>>().join("\0").as_bytes(), highestmodseq, mailbox_hash],
)
.chain_err_summary(|| {
format!(
@@ -304,7 +304,7 @@ mod sqlite3_m {
sqlite3::params![
select_response.uidvalidity as Sqlite3UID,
select_response.flags.1.iter().map(|s| s.as_str()).collect::<Vec<&str>>().join("\0").as_bytes(),
- mailbox_hash as i64
+ mailbox_hash
],
)
.chain_err_summary(|| {
@@ -340,7 +340,7 @@ mod sqlite3_m {
.join("\0")
.as_bytes(),
highestmodseq,
- mailbox_hash as i64
+ mailbox_hash
],
)
.chain_err_summary(|| {
@@ -362,7 +362,7 @@ mod sqlite3_m {
.collect::<Vec<&str>>()
.join("\0")
.as_bytes(),
- mailbox_hash as i64
+ mailbox_hash
],
)
.chain_err_summary(|| {
@@ -386,7 +386,7 @@ mod sqlite3_m {
)?;
let ret: Vec<(UID, Envelope, Option<ModSequence>)> = stmt
- .query_map(sqlite3::params![mailbox_hash as i64], |row| {
+ .query_map(sqlite3::params![mailbox_hash], |row| {
Ok((
row.get(0).map(|i: Sqlite3UID| i as UID)?,
row.get(1)?,
@@ -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(), *uid as Sqlite3UID, mailbox_hash as i64, modseq, &envelope],
+ sqlite3::params![envelope.hash(), *uid as Sqlite3UID, mailbox_hash, modseq, &envelope],
).chain_err_summary(|| format!("Could not insert envelope {} {} in header_cache of account {}", envelope.message_id(), envelope.hash(), uid_store.account_name))?;
}
}
@@ -498,7 +498,7 @@ mod sqlite3_m {
hash_index_lck.remove(env_hash);
tx.execute(
"DELETE FROM envelopes WHERE mailbox_hash = ?1 AND uid = ?2;",
- sqlite3::params![mailbox_hash as i64, *uid as Sqlite3UID],
+ sqlite3::params![mailbox_hash, *uid as Sqlite3UID],
)
.chain_err_summary(|| {
format!(
@@ -513,18 +513,18 @@ mod sqlite3_m {
)?;
let mut ret: Vec<Envelope> = stmt
- .query_map(
- sqlite3::params![mailbox_hash as i64, *uid as Sqlite3UID],
- |row| row.get(0),
- )?
+ .query_map(sqlite3::params![mailbox_hash, *uid as Sqlite3UID], |row| {
+ row.get(0)
+ })?
.collect::<std::result::Result<_, _>>()?;
if let Some(mut env) = ret.pop() {
env.set_flags(*flags);
- env.labels_mut().clear();
- env.labels_mut().extend(tags.iter().map(|t| tag_hash!(t)));
+ env.tags_mut().clear();
+ env.tags_mut()
+ .extend(tags.iter().map(|t| TagHash::from_bytes(t.as_bytes())));
tx.execute(
"UPDATE envelopes SET envelope = ?1 WHERE mailbox_hash = ?2 AND uid = ?3;",
- sqlite3::params![&env, mailbox_hash as i64, *uid as Sqlite3UID],
+ sqlite3::params![&env, mailbox_hash, *uid as Sqlite3UID],
)
.chain_err_summary(|| {
format!(
@@ -567,16 +567,13 @@ mod sqlite3_m {
)?;
let x = stmt
- .query_map(
- sqlite3::params![mailbox_hash as i64, uid as Sqlite3UID],
- |row| {
- Ok((
- row.get(0).map(|u: Sqlite3UID| u as UID)?,
- row.get(1)?,
- row.get(2)?,
- ))
- },
- )?
+ .query_map(sqlite3::params![mailbox_hash, uid as Sqlite3UID], |row| {
+ Ok((
+ row.get(0).map(|u: Sqlite3UID| u as UID)?,
+ row.get(1)?,
+ row.get(2)?,
+ ))
+ })?
.collect::<std::result::Result<_, _>>()?;
x
}
@@ -586,7 +583,7 @@ mod sqlite3_m {
)?;
let x = stmt
- .query_map(sqlite3::params![mailbox_hash as i64, env_hash], |row| {
+ .query_map(sqlite3::params![mailbox_hash, env_hash], |row| {
Ok((
row.get(0).map(|u: Sqlite3UID| u as UID)?,
row.get(1)?,
@@ -620,10 +617,9 @@ mod sqlite3_m {
"SELECT rfc822 FROM envelopes WHERE mailbox_hash = ?1 AND uid = ?2;",
)?;
let x = stmt
- .query_map(
- sqlite3::params![mailbox_hash as i64, uid as Sqlite3UID],
- |row| row.get(0),
- )?
+ .query_map(sqlite3::params![mailbox_hash, uid as Sqlite3UID], |row| {
+ row.get(0)
+ })?
.collect::<std::result::Result<_, _>>()?;
x
}
@@ -632,9 +628,7 @@ 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], |row| {
- row.get(0)
- })?
+ .query_map(sqlite3::params![mailbox_hash, env_hash], |row| row.get(0))?
.collect::<std::result::Result<_, _>>()?;
x
}
diff --git a/melib/src/backends/imap/cache/sync.rs b/melib/src/backends/imap/cache/sync.rs
index f7fbc913..65101612 100644
--- a/melib/src/backends/imap/cache/sync.rs
+++ b/melib/src/backends/imap/cache/sync.rs
@@ -166,11 +166,11 @@ impl ImapConnection {
new_unseen.insert(env.hash());
}
for f in keywords {
- let hash = tag_hash!(f);
+ let hash = TagHash::from_bytes(f.as_bytes());
if !tag_lck.contains_key(&hash) {
tag_lck.insert(hash, f.to_string());
}
- env.labels_mut().push(hash);
+ env.tags_mut().push(hash);
}
}
}
@@ -252,19 +252,19 @@ impl ImapConnection {
}
let (flags, tags) = flags.unwrap();
if env_lck[&env_hash].inner.flags() != flags
- || env_lck[&env_hash].inner.labels()
+ || env_lck[&env_hash].inner.tags()
!= &tags
.iter()
- .map(|t| tag_hash!(t))
- .collect::<SmallVec<[u64; 8]>>()
+ .map(|t| TagHash::from_bytes(t.as_bytes()))
+ .collect::<SmallVec<[TagHash; 8]>>()
{
env_lck.entry(env_hash).and_modify(|entry| {
entry.inner.set_flags(flags);
- entry.inner.labels_mut().clear();
+ entry.inner.tags_mut().clear();
entry
.inner
- .labels_mut()
- .extend(tags.iter().map(|t| tag_hash!(t)));
+ .tags_mut()
+ .extend(tags.iter().map(|t| TagHash::from_bytes(t.as_bytes())));
});
refresh_events.push((
uid,
@@ -452,11 +452,11 @@ impl ImapConnection {
new_unseen.insert(env.hash());
}
for f in keywords {
- let hash = tag_hash!(f);
+ let hash = TagHash::from_bytes(f.as_bytes());
if !tag_lck.contains_key(&hash) {
tag_lck.insert(hash, f.to_string());
}
- env.labels_mut().push(hash);
+ env.tags_mut().push(hash);
}
}
}
@@ -540,19 +540,19 @@ impl ImapConnection {
}
let (flags, tags) = flags.unwrap();
if env_lck[&env_hash].inner.flags() != flags
- || env_lck[&env_hash].inner.labels()
+ || env_lck[&env_hash].inner.tags()
!= &tags
.iter()
- .map(|t| tag_hash!(t))
- .collect::<SmallVec<[u64; 8]>>()
+ .map(|t| TagHash::from_bytes(t.as_bytes()))
+ .collect::<SmallVec<[TagHash; 8]>>()
{
env_lck.entry(env_hash).and_modify(|entry| {
entry.inner.set_flags(flags);
- entry.inner.labels_mut().clear();
+ entry.inner.tags_mut().clear();
entry
.inner
- .labels_mut()
- .extend(tags.iter().map(|t| tag_hash!(t)));
+ .tags_mut()
+ .extend(tags.iter().map(|t| TagHash::from_bytes(t.as_bytes())));
});
refresh_events.push((
uid,
diff --git a/melib/src/backends/imap/protocol_parser.rs b/melib/src/backends/imap/protocol_parser.rs
index eaf2b08f..38a4f415 100644
--- a/melib/src/backends/imap/protocol_parser.rs
+++ b/melib/src/backends/imap/protocol_parser.rs
@@ -26,7 +26,6 @@ use crate::email::parser::{
BytesExt, IResult,
};
use crate::error::ResultIntoMeliError;
-use crate::get_path_hash;
use nom::{
branch::{alt, permutation},
bytes::complete::{is_a, is_not, tag, take, take_until, take_while},
@@ -479,7 +478,7 @@ pub fn list_mailbox_result(input: &[u8]) -> IResult<&[u8], ImapMailbox> {
}
}
f.imap_path = path.to_string();
- f.hash = get_path_hash!(&f.imap_path);
+ f.hash = MailboxHash::from_bytes(f.imap_path.as_bytes());
f.path = if separator == b'/' {
f.imap_path.clone()
} else {
@@ -487,7 +486,7 @@ pub fn list_mailbox_result(input: &[u8]) -> IResult<&[u8], ImapMailbox> {
};
f.name = if let Some(pos) = f.imap_path.as_bytes().iter().rposition(|&c| c == separator)
{
- f.parent = Some(get_path_hash!(&f.imap_path[..pos]));
+ f.parent = Some(MailboxHash::from_bytes(f.imap_path[..pos].as_bytes()));
f.imap_path[pos + 1..].to_string()
} else {
f.imap_path.clone()
@@ -984,7 +983,7 @@ fn test_imap_fetch_response() {
let mut address = SmallVec::new();
address.push(Address::new(None, "xx@xx.com".to_string()));
- let mut env = Envelope::new(0);
+ let mut env = Envelope::new(EnvelopeHash::default());
env.set_subject("xxxx/xxxx".as_bytes().to_vec());
env.set_date("Fri, 24 Jun 2011 10:09:10 +0000".as_bytes());
env.set_from(address.clone());
@@ -1599,7 +1598,9 @@ pub struct StatusResponse {
pub fn status_response(input: &[u8]) -> IResult<&[u8], StatusResponse> {
let (input, _) = tag("* STATUS ")(input)?;
let (input, mailbox) = take_until(" (")(input)?;
- let mailbox = mailbox_token(mailbox).map(|(_, m)| get_path_hash!(m)).ok();
+ let mailbox = mailbox_token(mailbox)
+ .map(|(_, m)| MailboxHash::from_bytes(m.as_bytes()))
+ .ok();
let (input, _) = tag(" (")(input)?;
let (input, result) = permutation((
opt(preceded(
diff --git a/melib/src/backends/imap/untagged.rs b/melib/src/backends/imap/untagged.rs
index e081a877..785a8610 100644
--- a/melib/src/backends/imap/untagged.rs
+++ b/melib/src/backends/imap/untagged.rs
@@ -27,6 +27,7 @@ use crate::backends::BackendMailbox;
use crate::backends::{
RefreshEvent,
RefreshEventKind::{self, *},
+ TagHash,
};
use crate::error::*;
use std::convert::TryInto;
@@ -233,11 +234,11 @@ impl ImapConnection {
mailbox.unseen.lock().unwrap().insert_new(env.hash());
}
for f in keywords {
- let hash = tag_hash!(f);
+ let hash = TagHash::from_bytes(f.as_bytes());
if !tag_lck.contains_key(&hash) {
tag_lck.insert(hash, f.to_string());
}
- env.labels_mut().push(hash);
+ env.tags_mut().push(hash);
}
}
mailbox.exists.lock().unwrap().insert_new(env.hash());
@@ -364,11 +365,11 @@ impl ImapConnection {
mailbox.unseen.lock().unwrap().insert_new(env.hash());
}
for f in keywords {
- let hash = tag_hash!(f);
+ let hash = TagHash::from_bytes(f.as_bytes());
if !tag_lck.contains_key(&hash) {
tag_lck.insert(hash, f.to_string());
}
- env.labels_mut().push(hash);
+ env.tags_mut().push(hash);
}
}
mailbox.exists.lock().unwrap().insert_new(env.hash());
diff --git a/melib/src/backends/imap/watch.rs b/melib/src/backends/imap/watch.rs
index ce88e7b8..37f682d2 100644
--- a/melib/src/backends/imap/watch.rs
+++ b/melib/src/backends/imap/watch.rs
@@ -382,11 +382,11 @@ pub async fn examine_updates(
}
mailbox.exists.lock().unwrap().insert_new(env.hash());
for f in keywords {
- let hash = tag_hash!(f);
+ let hash = TagHash::from_bytes(f.as_bytes());
if !tag_lck.contains_key(&hash) {
tag_lck.insert(hash, f.to_string());
}
- env.labels_mut().push(hash);
+ env.tags_mut().push(hash);
}
}
}
diff --git a/melib/src/backends/jmap.rs b/melib/src/backends/jmap.rs
index 238e2651..8c2fe37c 100644
--- a/melib/src/backends/jmap.rs
+++ b/melib/src/backends/jmap.rs
@@ -29,26 +29,12 @@ use futures::lock::Mutex as FutureMutex;
use isahc::config::RedirectPolicy;
use isahc::{AsyncReadResponseExt, HttpClient};
use serde_json::Value;
-use std::collections::{hash_map::DefaultHasher, HashMap, HashSet};
+use std::collections::{HashMap, HashSet};
use std::convert::TryFrom;
-use std::hash::{Hash, Hasher};
use std::str::FromStr;
use std::sync::{Arc, Mutex, RwLock};
use std::time::{Duration, Instant};
-macro_rules! tag_hash {
- ($t:ident) => {{
- let mut hasher = DefaultHasher::default();
- $t.hash(&mut hasher);
- hasher.finish()
- }};
- ($t:literal) => {{
- let mut hasher = DefaultHasher::default();
- $t.hash(&mut hasher);
- hasher.finish()
- }};
-}
-
#[macro_export]
macro_rules! _impl {
($(#[$outer:meta])*$field:ident : $t:ty) => {
@@ -178,29 +164,25 @@ impl Store {
.keywords()
.keys()
.map(|tag| {
- let tag_hash = {
- let mut hasher = DefaultHasher::default();
- tag.hash(&mut hasher);
- hasher.finish()
- };
+ let tag_hash = TagHash::from_bytes(tag.as_bytes());
if !tag_lck.contains_key(&tag_hash) {
tag_lck.insert(tag_hash, tag.to_string());
}
tag_hash
})
- .collect::<SmallVec<[u64; 1024]>>();
+ .collect::<SmallVec<[TagHash; 1024]>>();
let id = obj.id.clone();
let mailbox_ids = obj.mailbox_ids.clone();
let blob_id = obj.blob_id.clone();
drop(tag_lck);
let mut ret: Envelope = obj.into();
- debug_assert_eq!(tag_hash!("$draft"), 6613915297903591176);
- debug_assert_eq!(tag_hash!("$seen"), 1683863812294339685);
- debug_assert_eq!(tag_hash!("$flagged"), 2714010747478170100);
- debug_assert_eq!(tag_hash!("$answered"), 8940855303929342213);
- debug_assert_eq!(tag_hash!("$junk"), 2656839745430720464);
- debug_assert_eq!(tag_hash!("$notjunk"), 4091323799684325059);
+ debug_assert_eq!(TagHash::from_bytes(b"$draft").0, 6613915297903591176);
+ debug_assert_eq!(TagHash::from_bytes(b"$seen").0, 1683863812294339685);
+ debug_assert_eq!(TagHash::from_bytes(b"$flagged").0, 2714010747478170100);
+ debug_assert_eq!(TagHash::from_bytes(b"$answered").0, 8940855303929342213);
+ debug_assert_eq!(TagHash::from_bytes(b"$junk").0, 2656839745430720464);
+ debug_assert_eq!(TagHash::from_bytes(b"$notjunk").0, 4091323799684325059);
let mut id_store_lck = self.id_store.lock().unwrap();
let mut reverse_id_store_lck = self.reverse_id_store.lock().unwrap();
let mut blob_id_store_lck = self.blob_id_store.lock().unwrap();
@@ -219,7 +201,7 @@ impl Store {
id_store_lck.insert(ret.hash(), id);
blob_id_store_lck.insert(ret.hash(), blob_id);
for t in tags {
- match t {
+ match t.0 {
6613915297903591176 => {
ret.set_flags(ret.flags() | Flag::DRAFT);
}
@@ -233,7 +215,7 @@ impl Store {
ret.set_flags(ret.flags() | Flag::REPLIED);
}
2656839745430720464 | 4091323799684325059 => { /* ignore */ }
- _ => ret.labels_mut().push(t),
+ _ => ret.tags_mut().push(t),
}
}
ret
@@ -811,7 +793,7 @@ impl MailBackend for JmapType {
Ok(_) => {}
Err(t) => {
if *value {
- tag_index_lck.insert(tag_hash!(t), t.clone());
+ tag_index_lck.insert(TagHash::from_bytes(t.as_bytes()), t.clone());
}
}
}
@@ -883,11 +865,7 @@ impl JmapType {
)));
let server_conf = JmapServerConf::new(s)?;
- let account_hash = {
- let mut hasher = DefaultHasher::new();
- hasher.write(s.name.as_bytes());
- hasher.finish()
- };
+ let account_hash = AccountHash::from_bytes(s.name.as_bytes());
let store = Arc::new(Store {
account_name: Arc::new(s.name.clone()),
account_hash,
diff --git a/melib/src/backends/jmap/objects/mailbox.rs b/melib/src/backends/jmap/objects/mailbox.rs
index 9a25b4ec..2a38e94c 100644
--- a/melib/src/backends/jmap/objects/mailbox.rs
+++ b/melib/src/backends/jmap/objects/mailbox.rs
@@ -23,9 +23,7 @@ use super::*;
impl Id<MailboxObject> {
pub fn into_hash(&self) -> MailboxHash {
- let mut h = DefaultHasher::new();
- h.write(self.inner.as_bytes());
- h.finish()
+ MailboxHash::from_bytes(self.inner.as_bytes())
}
}
diff --git a/melib/src/backends/maildir.rs b/melib/src/backends/maildir.rs
index ab8af33c..da755944 100644
--- a/melib/src/backends/maildir.rs
+++ b/melib/src/backends/maildir.rs
@@ -159,7 +159,7 @@ impl MaildirMailbox {
};
let ret = MaildirMailbox {
- hash: h.finish(),
+ hash: MailboxHash(h.finish()),
name: file_name,
path: fname.unwrap().to_path_buf(),
fs_path: pathbuf,
diff --git a/melib/src/backends/maildir/backend.rs b/melib/src/backends/maildir/backend.rs
index a8ac0a55..9c9d1822 100644
--- a/melib/src/backends/maildir/backend.rs
+++ b/melib/src/backends/maildir/backend.rs
@@ -222,11 +222,7 @@ impl MailBackend for MaildirType {
fn refresh(&mut self, mailbox_hash: MailboxHash) -> ResultFuture<()> {
let cache_dir = xdg::BaseDirectories::with_profile("meli", &self.name).unwrap();
- let account_hash = {
- let mut hasher = DefaultHasher::default();
- hasher.write(self.name.as_bytes());
- hasher.finish()
- };
+ let account_hash = AccountHash::from_bytes(self.name.as_bytes());
let sender = self.event_consumer.clone();
let mailbox: &MaildirMailbox = &self.mailboxes[&mailbox_hash];
@@ -329,11 +325,7 @@ impl MailBackend for MaildirType {
let sender = self.event_consumer.clone();
let (tx, rx) = channel();
let mut watcher = watcher(tx, Duration::from_secs(2)).unwrap();
- let account_hash = {
- let mut hasher = DefaultHasher::default();
- hasher.write(self.name.as_bytes());
- hasher.finish()
- };
+ let account_hash = AccountHash::from_bytes(self.name.as_bytes());
let root_mailbox = self.path.to_path_buf();
watcher
.watch(&root_mailbox, RecursiveMode::Recursive)
@@ -384,7 +376,7 @@ impl MailBackend for MaildirType {
}
};
}
- let mailbox_hash = get_path_hash!(pathbuf);
+ let mailbox_hash = MailboxHash(get_path_hash!(pathbuf));
let file_name = pathbuf
.as_path()
.strip_prefix(&root_mailbox)
@@ -425,7 +417,7 @@ impl MailBackend for MaildirType {
/* Update */
DebouncedEvent::NoticeWrite(pathbuf) | DebouncedEvent::Write(pathbuf) => {
debug!("DebouncedEvent::Write(path = {:?}", &pathbuf);
- let mailbox_hash = get_path_hash!(pathbuf);
+ let mailbox_hash = MailboxHash(get_path_hash!(pathbuf));
let mut hash_indexes_lock = hash_indexes.lock().unwrap();
let index_lock =
&mut hash_indexes_lock.entry(mailbox_hash).or_default();
@@ -502,7 +494,7 @@ impl MailBackend for MaildirType {
/* Remove */
DebouncedEvent::NoticeRemove(pathbuf) | DebouncedEvent::Remove(pathbuf) => {
debug!("DebouncedEvent::Remove(path = {:?}", pathbuf);
- let mailbox_hash = get_path_hash!(pathbuf);
+ let mailbox_hash = MailboxHash(get_path_hash!(pathbuf));
let mut hash_indexes_lock = hash_indexes.lock().unwrap();
let index_lock = hash_indexes_lock.entry(mailbox_hash).or_default();
let hash: EnvelopeHash = if let Some((k, _)) =
@@ -556,9 +548,9 @@ impl MailBackend for MaildirType {
/* Envelope hasn't changed */
DebouncedEvent::Rename(src, dest) => {
debug!("DebouncedEvent::Rename(src = {:?}, dest = {:?})", src, dest);
- let mailbox_hash = get_path_hash!(src);
+ let mailbox_hash = MailboxHash(get_path_hash!(src));
let dest_mailbox = {
- let dest_mailbox = get_path_hash!(dest);
+ let dest_mailbox = MailboxHash(get_path_hash!(dest));
if dest_mailbox == mailbox_hash {
None
} else {
@@ -1018,7 +1010,7 @@ impl MailBackend for MaildirType {
.map(|item| *item.0)
});
- let mailbox_hash = get_path_hash!(&path);
+ let mailbox_hash = MailboxHash(get_path_hash!(&path));
if let Some(parent) = parent {
self.mailboxes
.entry(parent)
diff --git a/melib/src/backends/mbox.rs b/melib/src/backends/mbox.rs
index 9b08063b..d14e591b 100644
--- a/melib/src/backends/mbox.rs
+++ b/melib/src/backends/mbox.rs
@@ -136,9 +136,8 @@ use nom::{self, error::Error as NomError, error::ErrorKind as NomErrorKind, IRes
extern crate notify;
use self::notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
-use std::collections::hash_map::{DefaultHasher, HashMap};
+use std::collections::hash_map::HashMap;
use std::fs::File;
-use std::hash::Hasher;
use std::io::{BufReader, Read};
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
@@ -981,11 +980,7 @@ impl MailBackend for MboxType {
.map_err(MeliError::new)?;
debug!("watching {:?}", f.fs_path.as_path());
}
- let account_hash = {
- let mut hasher = DefaultHasher::new();
- hasher.write(self.account_name.as_bytes());
- hasher.finish()
- };
+ let account_hash = AccountHash::from_bytes(self.account_name.as_bytes());
let mailboxes = self.mailboxes.clone();
let mailbox_index = self.mailbox_index.clone();
let prefer_mbox_type = self.prefer_mbox_type;
@@ -1005,7 +1000,7 @@ impl MailBackend for MboxType {
Ok(event) => match event {
/* Update */
DebouncedEvent::NoticeWrite(pathbuf) | DebouncedEvent::Write(pathbuf) => {
- let mailbox_hash = get_path_hash!(&pathbuf);
+ let mailbox_hash = MailboxHash(get_path_hash!(&pathbuf));
let file = match std::fs::OpenOptions::new()
.read(true)
.write(true)
@@ -1067,7 +1062,7 @@ impl MailBackend for MboxType {
.values()
.any(|f| f.fs_path == pathbuf)
{
- let mailbox_hash = get_path_hash!(&pathbuf);
+ let mailbox_hash = MailboxHash(get_path_hash!(&pathbuf));
(sender)(
account_hash,
BackendEvent::Refresh(RefreshEvent {
@@ -1084,7 +1079,7 @@ impl MailBackend for MboxType {
}
DebouncedEvent::Rename(src, dest) => {
if mailboxes.lock().unwrap().values().any(|f| f.fs_path == src) {
- let mailbox_hash = get_path_hash!(&src);
+ let mailbox_hash = MailboxHash(get_path_hash!(&src));
(sender)(
account_hash,
BackendEvent::Refresh(RefreshEvent {
@@ -1336,7 +1331,7 @@ impl MboxType {
.file_name()
.map(|f| f.to_string_lossy().into())
.unwrap_or_default();
- let hash = get_path_hash!(&ret.path);
+ let hash = MailboxHash(get_path_hash!(&ret.path));
let read_only = if let Ok(metadata) = std::fs::metadata(&ret.path) {
metadata.permissions().readonly()
@@ -1374,7 +1369,7 @@ impl MboxType {
/* Look for other mailboxes */
for (k, f) in s.mailboxes.iter() {
if let Some(path_str) = f.extra.get("path") {
- let hash = get_path_hash!(path_str);
+ let hash = MailboxHash(get_path_hash!(path_str));
let pathbuf: PathBuf = path_str.into();
if !pathbuf.exists() || pathbuf.is_dir() {
return Err(MeliError::new(format!(
diff --git a/melib/src/backends/nntp.rs b/melib/src/backends/nntp.rs
index 695242f8..c8d17a21 100644
--- a/melib/src/backends/nntp.rs
+++ b/melib/src/backends/nntp.rs
@@ -589,15 +589,11 @@ impl NntpType {
deflate: get_conf_val!(s["use_deflate"], false)?,
},
};
- let account_hash = {
- let mut hasher = DefaultHasher::new();
- hasher.write(s.name.as_bytes());
- hasher.finish()
- };
+ let account_hash = AccountHash::from_bytes(s.name.as_bytes());
let account_name = Arc::new(s.name().to_string());
let mut mailboxes = HashMap::default();
for (k, _f) in s.mailboxes.iter() {
- let mailbox_hash = get_path_hash!(&k);
+ let mailbox_hash = MailboxHash(get_path_hash!(&k));
mailboxes.insert(
mailbox_hash,
NntpMailbox {
@@ -663,7 +659,7 @@ impl NntpType {
if s.len() != 3 {
continue;
}
- let mailbox_hash = get_path_hash!(&s[0]);
+ let mailbox_hash = MailboxHash(get_path_hash!(&s[0]));
mailboxes_lck.entry(mailbox_hash).and_modify(|m| {
*m.high_watermark.lock().unwrap() = usize::from_str(s[1]).unwrap_or(0);
*m.low_watermark.lock().unwrap() = usize::from_str(s[2]).unwrap_or(0);
diff --git a/melib/src/backends/notmuch.rs b/melib/src/backends/notmuch.rs
index 5fc2331e..69ac6f66 100644
--- a/melib/src/backends/notmuch.rs
+++ b/melib/src/backends/notmuch.rs
@@ -25,13 +25,9 @@ use crate::error::{MeliError, Result};
use crate::shellexpand::ShellExpandTrait;
use crate::{backends::*, Collection};
use smallvec::SmallVec;
-use std::collections::{
- hash_map::{DefaultHasher, HashMap},
- BTreeMap,
-};
+use std::collections::{hash_map::HashMap, BTreeMap};
use std::error::Error;
use std::ffi::{CStr, CString, OsStr};
-use std::hash::{Hash, Hasher};
use std::io::Read;
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};
@@ -91,7 +87,7 @@ impl DbConnection {
mailboxes: Arc<RwLock<HashMap<MailboxHash, NotmuchMailbox>>>,
index: Arc<RwLock<HashMap<EnvelopeHash, CString>>>,
mailbox_index: Arc<RwLock<HashMap<EnvelopeHash, SmallVec<[MailboxHash; 16]>>>>,
- tag_index: Arc<RwLock<BTreeMap<u64, String>>>,
+ tag_index: Arc<RwLock<BTreeMap<TagHash, String>>>,
account_hash: AccountHash,
event_consumer: BackendEventConsumer,
new_revision_uuid: u64,
@@ -112,9 +108,7 @@ impl DbConnection {
let tags: (Flag, Vec<String>) = message.tags().collect_flags_and_tags();
let mut tag_lock = tag_index.write().unwrap();
for tag in tags.1.iter() {
- let mut hasher = DefaultHasher::new();
- hasher.write(tag.as_bytes());
- let num = hasher.finish();
+ let num = TagHash::from_bytes(tag.as_bytes());
if !tag_lock.contains_key(&num) {
tag_lock.insert(num, tag.clone());
}
@@ -366,11 +360,7 @@ impl NotmuchDb {
let mut mailboxes = HashMap::default();
for (k, f) in s.mailboxes.iter() {
if let Some(query_str) = f.extra.get("query") {
- let hash = {
- let mut h = DefaultHasher::new();
- k.hash(&mut h);
- h.finish()
- };
+ let hash = MailboxHash::from_bytes(k.as_bytes());
mailboxes.insert(
hash,
NotmuchMailbox {
@@ -395,11 +385,7 @@ impl NotmuchDb {
}
}
- let account_hash = {
- let mut hasher = DefaultHasher::new();
- hasher.write(s.name().as_bytes());
- hasher.finish()
- };
+ let account_hash = AccountHash::from_bytes(s.name().as_bytes());
Ok(Box::new(NotmuchDb {
lib,
revision_uuid: Arc::new(RwLock::new(0)),
@@ -535,8 +521,8 @@ impl MailBackend for NotmuchDb {
database: Arc<DbConnection>,
index: Arc<RwLock<HashMap<EnvelopeHash, CString>>>,
mailbox_index: Arc<RwLock<HashMap<EnvelopeHash, SmallVec<[MailboxHash; 16]>>>>,
- mailboxes: Arc<RwLock<HashMap<u64, NotmuchMailbox>>>,
- tag_index: Arc<RwLock<BTreeMap<u64, String>>>,
+ mailboxes: Arc<RwLock<HashMap<MailboxHash, NotmuchMailbox>>>,
+ tag_index: Arc<RwLock<BTreeMap<TagHash, String>>>,
iter: std::vec::IntoIter<CString>,
}
impl FetchState {
@@ -860,7 +846,7 @@ impl MailBackend for NotmuchDb {
}
for (f, v) in flags.iter() {
if let (Err(tag), true) = (f, v) {
- let hash = tag_hash!(tag);
+ let hash = TagHash::from_bytes(tag.as_bytes());
collection
.tag_index
.write()
diff --git a/melib/src/backends/notmuch/message.rs b/melib/src/backends/notmuch/message.rs
index a8104b4d..8e503c2f 100644
--- a/melib/src/backends/notmuch/message.rs
+++ b/melib/src/backends/notmuch/message.rs
@@ -88,7 +88,7 @@ impl<'m> Message<'m> {
pub fn into_envelope(
self,
index: &RwLock<HashMap<EnvelopeHash, CString>>,
- tag_index: &RwLock<BTreeMap<u64, String>>,
+ tag_index: &RwLock<BTreeMap<TagHash, String>>,
) -> Envelope {
let env_hash = self.env_hash();
let mut env = Envelope::new(env_hash);
@@ -99,13 +99,11 @@ impl<'m> Message<'m> {
let mut tag_lock = tag_index.write().unwrap();
let (flags, tags) = TagIterator::new(&self).collect_flags_and_tags();
for tag in tags {
- let mut hasher = DefaultHasher::new();
- hasher.write(tag.as_bytes());
- let num = hasher.finish();
+ let num = TagHash::from_bytes(tag.as_bytes());
if !tag_lock.contains_key(&num) {
tag_lock.insert(num, tag);
}
- env.labels_mut().push(num);
+ env.tags_mut().push(num);
}
unsafe {
use crate::email::parser::address::rfc2822address_list;
diff --git a/melib/src/collection.rs b/melib/src/collection.rs
index 82df499d..7320ab6e 100644
--- a/melib/src/collection.rs
+++ b/melib/src/collection.rs
@@ -20,7 +20,7 @@
*/
use super::*;
-use crate::backends::MailboxHash;
+use crate::backends::{MailboxHash, TagHash};
use smallvec::SmallVec;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
@@ -37,7 +37,7 @@ pub struct Collection {
pub threads: Arc<RwLock<HashMap<MailboxHash, Threads>>>,
pub sent_mailbox: Arc<RwLock<Option<MailboxHash>>>,
pub mailboxes: Arc<RwLock<HashMap<MailboxHash, HashSet<EnvelopeHash>>>>,
- pub tag_index: Arc<RwLock<BTreeMap<u64, String>>>,
+ pub tag_index: Arc<RwLock<BTreeMap<TagHash, String>>>,
}
impl Default for Collection {
diff --git a/melib/src/email.rs b/melib/src/email.rs
index 75db0231..6da7c5ab 100644
--- a/melib/src/email.rs
+++ b/melib/src/email.rs
@@ -109,12 +109,11 @@ use crate::datetime::UnixTimestamp;
use crate::error::{MeliError, Result};
use crate::parser::BytesExt;
use crate::thread::ThreadNodeHash;
+use crate::TagHash;
use smallvec::SmallVec;
use std::borrow::Cow;
-use std::collections::hash_map::DefaultHasher;
use std::convert::TryInto;
-use std::hash::Hasher;
use std::ops::Deref;
bitflags! {
@@ -198,31 +197,7 @@ impl Mail {
}
}
-#[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)
- }
-}
+crate::declare_u64_hash!(EnvelopeHash);
/// `Envelope` represents all the header and structure data of an email we need to know.
///
@@ -247,7 +222,7 @@ pub struct Envelope {
pub thread: ThreadNodeHash,
pub flags: Flag,
pub has_attachments: bool,
- pub labels: SmallVec<[u64; 8]>,
+ pub tags: SmallVec<[TagHash; 8]>,
}
impl core::fmt::Debug for Envelope {
@@ -290,7 +265,7 @@ impl Envelope {
thread: ThreadNodeHash::null(),
has_attachments: false,
flags: Flag::default(),
- labels: SmallVec::new(),
+ tags: SmallVec::new(),
}
}
@@ -809,12 +784,12 @@ impl Envelope {
self.has_attachments
}
- pub fn labels(&self) -> &SmallVec<[u64; 8]> {
- &self.labels
+ pub fn tags(&self) -> &SmallVec<[TagHash; 8]> {
+ &self.tags
}
- pub fn labels_mut(&mut self) -> &mut SmallVec<[u64; 8]> {
- &mut self.labels
+ pub fn tags_mut(&mut self) -> &mut SmallVec<[TagHash; 8]> {
+ &mut self.tags
}
}
diff --git a/melib/src/lib.rs b/melib/src/lib.rs
index e1aa4cf1..80e80ae5 100644
--- a/melib/src/lib.rs
+++ b/melib/src/lib.rs
@@ -147,6 +147,7 @@ pub extern crate uuid;
pub extern crate xdg_utils;
#[derive(Debug, Copy, Clone)]
+#[repr(transparent)]
pub struct Bytes(pub usize);
impl Bytes {
@@ -395,3 +396,68 @@ pub mod shellexpand {
assert!(!Path::new("~").expand().complete(true).is_empty());
}
}
+
+#[macro_export]
+macro_rules! declare_u64_hash {
+ ($type_name:ident) => {
+ #[derive(
+ Hash,
+ Eq,
+ PartialEq,
+ Debug,
+ Ord,
+ PartialOrd,
+ Default,
+ Serialize,
+ Deserialize,
+ Copy,
+ Clone,
+ )]
+ #[repr(transparent)]
+ pub struct $type_name(pub u64);
+
+ impl $type_name {
+ #[inline(always)]
+ pub fn from_bytes(bytes: &[u8]) -> Self {
+ use std::collections::hash_map::DefaultHasher;
+ use std::hash::Hasher;
+ 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()
+ }
+
+ #[inline(always)]
+ pub const fn is_null(self) -> bool {
+ self.0 == 0
+ }
+ }
+
+ impl core::fmt::Display for $type_name {
+ fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
+ write!(fmt, "{}", self.0)
+ }
+ }
+ #[cfg(feature = "sqlite3")]
+ impl rusqlite::types::ToSql for $type_name {
+ fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput> {
+ Ok(rusqlite::types::ToSqlOutput::from(self.0 as i64))
+ }
+ }
+
+ #[cfg(feature = "sqlite3")]
+ impl rusqlite::types::FromSql for $type_name {
+ fn column_result(
+ value: rusqlite::types::ValueRef,
+ ) -> rusqlite::types::FromSqlResult<Self> {
+ let b: i64 = rusqlite::types::FromSql::column_result(value)?;
+
+ Ok($type_name(b as u64))
+ }
+ }
+ };
+}
diff --git a/melib/src/sqlite3.rs b/melib/src/sqlite3.rs
index 898454f6..17a7b67f 100644
--- a/melib/src/sqlite3.rs
+++ b/melib/src/sqlite3.rs
@@ -19,7 +19,7 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
-use crate::{error::*, logging::log, Envelope, EnvelopeHash};
+use crate::{error::*, logging::log, Envelope};
use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput};
pub use rusqlite::{self, params, Connection};
use std::path::PathBuf;
@@ -159,17 +159,3 @@ 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))
- }
-}
diff --git a/src/components/mail/compose.rs b/src/components/mail/compose.rs
index 62636668..7cd5f615 100644
--- a/src/components/mail/compose.rs
+++ b/src/components/mail/compose.rs
@@ -150,7 +150,7 @@ impl Composer {
pager.set_show_scrollbar(true);
Composer {
reply_context: None,
- account_hash: 0,
+ account_hash: AccountHash::default(),
cursor: Cursor::Headers,
pager,
draft: Draft::default(),
@@ -2405,7 +2405,7 @@ hello world.
let envelope = Envelope::from_bytes(raw_mail.as_bytes(), None).expect("Could not parse mail");
let mut context = Context::new_mock();
let account_hash = context.accounts[0].hash();
- let mailbox_hash = 0;
+ let mailbox_hash = MailboxHash::default();
let envelope_hash = envelope.hash();
context.accounts[0]
.collection
diff --git a/src/components/mail/listing.rs b/src/components/mail/listing.rs
index f6f72517..a77fd417 100644
--- a/src/components/mail/listing.rs
+++ b/src/components/mail/listing.rs
@@ -628,7 +628,7 @@ pub trait MailListingTrait: ListingTrait {
let tags_lck = collection.tag_index.read().unwrap();
if let Some((env, ref bytes)) = iter.next() {
let tags: Vec<&str> = env
- .labels()
+ .tags()
.iter()
.filter_map(|h| tags_lck.get(h).map(|s| s.as_str()))
.collect();
@@ -645,7 +645,7 @@ pub trait MailListingTrait: ListingTrait {
}
for (env, bytes) in iter {
let tags: Vec<&str> = env
- .labels()
+ .tags()
.iter()
.filter_map(|h| tags_lck.get(h).map(|s| s.as_str()))
.collect();
@@ -929,7 +929,8 @@ impl Component for Listing {
if context.is_online(account_hash).is_err()
&& !matches!(self.component, ListingComponent::Offline(_))
{
- self.component = Offline(OfflineListing::new((account_hash, 0)));
+ self.component =
+ Offline(OfflineListing::new((account_hash, MailboxHash::default())));
}
if let Some(s) = self.status.as_mut() {
@@ -948,7 +949,8 @@ impl Component for Listing {
if context.is_online(account_hash).is_err()
&& !matches!(self.component, ListingComponent::Offline(_))
{
- self.component = Offline(OfflineListing::new((account_hash, 0)));
+ self.component =
+ Offline(OfflineListing::new((account_hash, MailboxHash::default())));
}
if let Some(s) = self.status.as_mut() {
s.draw(grid, (set_x(upper_left, mid + 1), bottom_right), context);
@@ -2044,7 +2046,10 @@ impl Listing {
.collect();
let first_account_hash = account_entries[0].hash;
let mut ret = Listing {
- component: Offline(OfflineListing::new((first_account_hash, 0))),
+ component: Offline(OfflineListing::new((
+ first_account_hash,
+ MailboxHash::default(),
+ ))),
accounts: account_entries,
status: None,
dirty: true,
@@ -2567,7 +2572,8 @@ impl Listing {
mailbox_settings!(context[account_hash][mailbox_hash].listing.index_style);
self.component.set_style(*index_style);
} else if !matches!(self.component, ListingComponent::Offline(_)) {
- self.component = Offline(OfflineListing::new((account_hash, 0)));
+ self.component =
+ Offline(OfflineListing::new((account_hash, MailboxHash::default())));
}
self.status = None;
context
diff --git a/src/components/mail/listing/compact.rs b/src/components/mail/listing/compact.rs
index 1efe0ff5..52387433 100644
--- a/src/components/mail/listing/compact.rs
+++ b/src/components/mail/listing/compact.rs
@@ -815,7 +815,7 @@ impl CompactListing {
pub const DESCRIPTION: &'static str = "compact listing";
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Box<Self> {
Box::new(CompactListing {
- cursor_pos: (coordinates.0, 1, 0),
+ cursor_pos: (coordinates.0, MailboxHash::default(), 0),
new_cursor_pos: (coordinates.0, coordinates.1, 0),
length: 0,
sort: (Default::default(), Default::default()),
@@ -854,7 +854,7 @@ impl CompactListing {
let account = &context.accounts[&self.cursor_pos.0];
if account.backend_capabilities.supports_tags {
let tags_lck = account.collection.tag_index.read().unwrap();
- for t in e.labels().iter() {
+ for t in e.tags().iter() {
if mailbox_settings!(
context[self.cursor_pos.0][&self.cursor_pos.1]
.tags
diff --git a/src/components/mail/listing/conversations.rs b/src/components/mail/listing/conversations.rs
index e7a97299..d462d738 100644
--- a/src/components/mail/listing/conversations.rs
+++ b/src/components/mail/listing/conversations.rs
@@ -603,7 +603,7 @@ impl ConversationsListing {
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Box<Self> {
Box::new(Self {
- cursor_pos: (coordinates.0, 1, 0),
+ cursor_pos: (coordinates.0, MailboxHash::default(), 0),
new_cursor_pos: (coordinates.0, coordinates.1, 0),
length: 0,
sort: (Default::default(), Default::default()),
@@ -641,7 +641,7 @@ impl ConversationsListing {
let account = &context.accounts[&self.cursor_pos.0];
if account.backend_capabilities.supports_tags {
let tags_lck = account.collection.tag_index.read().unwrap();
- for t in e.labels().iter() {
+ for t in e.tags().iter() {
if mailbox_settings!(
context[self.cursor_pos.0][&self.cursor_pos.1]
.tags
diff --git a/src/components/mail/listing/plain.rs b/src/components/mail/listing/plain.rs
index 83fe3d91..1d28f389 100644
--- a/src/components/mail/listing/plain.rs
+++ b/src/components/mail/listing/plain.rs
@@ -607,7 +607,7 @@ impl fmt::Display for PlainListing {
impl PlainListing {
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Box<Self> {
Box::new(PlainListing {
- cursor_pos: (0, 1, 0),
+ cursor_pos: (AccountHash::default(), MailboxHash::default(), 0),
new_cursor_pos: (coordinates.0, coordinates.1, 0),
length: 0,
sort: (Default::default(), Default::default()),
@@ -637,7 +637,7 @@ impl PlainListing {
let account = &context.accounts[&self.cursor_pos.0];
if account.backend_capabilities.supports_tags {
let tags_lck = account.collection.tag_index.read().unwrap();
- for t in e.labels().iter() {
+ for t in e.tags().iter() {
if mailbox_settings!(
context[self.cursor_pos.0][&self.cursor_pos.1]
.tags
diff --git a/src/components/mail/listing/thread.rs b/src/components/mail/listing/thread.rs
index 3396894f..89b641c7 100644
--- a/src/components/mail/listing/thread.rs
+++ b/src/components/mail/listing/thread.rs
@@ -692,7 +692,7 @@ impl fmt::Display for ThreadListing {
impl ThreadListing {
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Box<Self> {
Box::new(ThreadListing {
- cursor_pos: (coordinates.0, 0, 0),
+ cursor_pos: (coordinates.0, MailboxHash::default(), 0),
new_cursor_pos: (coordinates.0, coordinates.1, 0),
length: 0,
sort: (Default::default(), Default::default()),
@@ -792,7 +792,7 @@ impl ThreadListing {
let account = &context.accounts[&self.cursor_pos.0];
if account.backend_capabilities.supports_tags {
let tags_lck = account.collection.tag_index.read().unwrap();
- for t in e.labels().iter() {
+ for t in e.tags().iter() {
if mailbox_settings!(
context[self.cursor_pos.0][&self.cursor_pos.1]
.tags
diff --git a/src/components/mail/view.rs b/src/components/mail/view.rs
index e2090fb4..7ccd352d 100644
--- a/src/components/mail/view.rs
+++ b/src/components/mail/view.rs
@@ -1658,7 +1658,7 @@ impl Component for MailView {
}
fn process_event(&mut self, mut event: &mut UIEvent, context: &mut Context) -> bool {
- if self.coordinates.0 == 0 || self.coordinates.1 == 0 {
+ if self.coordinates.0.is_null() || self.coordinates.1.is_null() {
return false;
}
let shortcuts = self.get_shortcuts(context);
diff --git a/src/conf.rs b/src/conf.rs
index 8c1b6ed4..10a55f97 100644
--- a/src/conf.rs
+++ b/src/conf.rs
@@ -28,6 +28,7 @@ extern crate xdg;
use crate::conf::deserializers::non_empty_string;
use crate::terminal::Color;
+use melib::backends::TagHash;
use melib::search::Query;
use std::collections::HashSet;
mod overrides;
@@ -952,6 +953,7 @@ mod dotaddressable {
impl DotAddressable for char {}
impl DotAddressable for IndexStyle {}
impl DotAddressable for u64 {}
+ impl DotAddressable for TagHash {}
impl DotAddressable for crate::terminal::Color {}
impl DotAddressable for crate::terminal::Attr {}
impl DotAddressable for crate::terminal::Key {}
diff --git a/src/conf/accounts.rs b/src/conf/accounts.rs
index 6945990f..067a0c3d 100644
--- a/src/conf/accounts.rs
+++ b/src/conf/accounts.rs
@@ -766,10 +766,10 @@ impl Account {
.unwrap()
.entry(env_hash)
.and_modify(|entry| {
- entry.labels_mut().clear();
- entry
- .labels_mut()
- .extend(tags.into_iter().map(|h| tag_hash!(h)));
+ entry.tags_mut().clear();
+ entry.tags_mut().extend(
+ tags.into_iter().map(|h| TagHash::from_bytes(h.as_bytes())),
+ );
entry.set_flags(flags);
});
#[cfg(feature = "sqlite3")]
@@ -1128,7 +1128,7 @@ impl Account {
}
pub fn load(&mut self, mailbox_hash: MailboxHash) -> result::Result<(), usize> {
- if mailbox_hash == 0 {
+ if mailbox_hash.is_null() {
return Err(0);
}
match self.mailbox_entries[&mailbox_hash].status {
diff --git a/src/conf/overrides.rs b/src/conf/overrides.rs
index 22e2bf64..4f0d4a6e 100644
--- a/src/conf/overrides.rs
+++ b/src/conf/overrides.rs
@@ -378,10 +378,10 @@ impl Default for ComposingSettingsOverride {
pub struct TagsSettingsOverride {
#[serde(deserialize_with = "tag_color_de")]
#[serde(default)]
- pub colors: Option<HashMap<u64, Color>>,
+ pub colors: Option<HashMap<TagHash, Color>>,
#[serde(deserialize_with = "tag_set_de", alias = "ignore-tags")]
#[serde(default)]
- pub ignore_tags: Option<HashSet<u64>>,
+ pub ignore_tags: Option<HashSet<TagHash>>,
}
impl Default for TagsSettingsOverride {
fn default() -> Self {
diff --git a/src/conf/tags.rs b/src/conf/tags.rs
index 9f75a222..728e17af 100644
--- a/src/conf/tags.rs
+++ b/src/conf/tags.rs
@@ -23,21 +23,20 @@
use super::DotAddressable;
use crate::terminal::Color;
-use melib::{MeliError, Result};
+use melib::{MeliError, Result, TagHash};
use serde::{Deserialize, Deserializer};
-use std::collections::{hash_map::DefaultHasher, HashMap, HashSet};
-use std::hash::Hasher;
+use std::collections::{HashMap, HashSet};
#[derive(Default, Debug, Deserialize, Clone, Serialize)]
#[serde(deny_unknown_fields)]
pub struct TagsSettings {
#[serde(default, deserialize_with = "tag_color_de")]
- pub colors: HashMap<u64, Color>,
+ pub colors: HashMap<TagHash, Color>,
#[serde(default, deserialize_with = "tag_set_de", alias = "ignore-tags")]
- pub ignore_tags: HashSet<u64>,
+ pub ignore_tags: HashSet<TagHash>,
}
-pub fn tag_set_de<'de, D, T: std::convert::From<HashSet<u64>>>(
+pub fn tag_set_de<'de, D, T: std::convert::From<HashSet<TagHash>>>(
deserializer: D,
) -> std::result::Result<T, D::Error>
where
@@ -45,16 +44,12 @@ where
{
Ok(<Vec<String>>::deserialize(deserializer)?
.into_iter()
- .map(|tag| {
- let mut hasher = DefaultHasher::new();
- hasher.write(tag.as_bytes());
- hasher.finish()
- })
- .collect::<HashSet<u64>>()
+ .map(|tag| TagHash::from_bytes(tag.as_bytes()))
+ .collect::<HashSet<TagHash>>()
.into())
}
-pub fn tag_color_de<'de, D, T: std::convert::From<HashMap<u64, Color>>>(
+pub fn tag_color_de<'de, D, T: std::convert::From<HashMap<TagHash, Color>>>(
deserializer: D,
) -> std::result::Result<T, D::Error>
where
@@ -70,17 +65,15 @@ where
Ok(<HashMap<String, _Color>>::deserialize(deserializer)?
.into_iter()
.map(|(tag, color)| {
- let mut hasher = DefaultHasher::new();
- hasher.write(tag.as_bytes());
(
- hasher.finish(),
+ TagHash::from_bytes(tag.as_bytes()),
match color {
_Color::B(b) => Color::Byte(b),
_Color::C(c) => c,
},
)
})
- .collect::<HashMap<u64, Color>>()
+ .collect::<HashMap<TagHash, Color>>()
.into())
}
diff --git a/src/main.rs b/src/main.rs
index 391bef2d..1423802f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -319,7 +319,12 @@ fn run_app(opt: Opt) -> Result<()> {
sender,
receiver.clone(),
)?;
- state.register_component(Box::new(EnvelopeView::new(wrapper, None, None, 0)));
+ state.register_component(Box::new(EnvelopeView::new(
+ wrapper,
+ None,
+ None,
+ AccountHash::default(),
+ )));
} else {
state = State::new(None, sender, receiver.clone())?;
#[cfg(feature = "svgscreenshot")]
diff --git a/src/managesieve.rs b/src/managesieve.rs
index 340978a9..f68ef43f 100644
--- a/src/managesieve.rs
+++ b/src/managesieve.rs
@@ -99,7 +99,7 @@ fn main() -> Result<()> {
}
let account = &settings.accounts[&account_name].account;
let mut conn = ManageSieveConnection::new(
- 0,
+ AccountHash::default(),
account_name.clone(),
account,
melib::backends::BackendEventConsumer::new(std::sync::Arc::new(|_, _| {})),
diff --git a/src/state.rs b/src/state.rs
index e72a4fba..856c7906 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -182,13 +182,7 @@ impl Context {
account_conf.account.format = "maildir".to_string();
account_conf.account.root_mailbox = "/tmp/".to_string();
let sender = sender.clone();
- let account_hash = {
- use std::collections::hash_map::DefaultHasher;
- use std::hash::Hasher;
- let mut hasher = DefaultHasher::new();
- hasher.write(name.as_bytes());
- hasher.finish()
- };
+ let account_hash = AccountHash::from_bytes(name.as_bytes());
Account::new(
account_hash,
name,
@@ -328,13 +322,7 @@ impl State {
.iter()
.map(|(n, a_s)| {
let sender = sender.clone();
- let account_hash = {
- use std::collections::hash_map::DefaultHasher;
- use std::hash::Hasher;
- let mut hasher = DefaultHasher::new();
- hasher.write(n.as_bytes());
- hasher.finish()
- };
+ let account_hash = AccountHash::from_bytes(n.as_bytes());
Account::new(
account_hash,
n.to_string(),