diff options
author | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2022-12-08 21:34:32 +0200 |
---|---|---|
committer | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2022-12-08 22:10:58 +0200 |
commit | 259aeb00877557ee85b5cc555d50e605b85b3109 (patch) | |
tree | 388da23b582396b4f0481c2ad19f1fef3e880607 | |
parent | 7382e30160a934ce97dd73c1be44640d5b4a4c75 (diff) | |
download | meli-259aeb00877557ee85b5cc555d50e605b85b3109.zip |
Convert {Account,Mailbox}Hash from typedef to wrapper struct
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(), |