@ -26,7 +26,6 @@ use crate::{
email ::{ Envelope , EnvelopeHash } ,
error ::* ,
} ;
use std ::convert ::TryFrom ;
#[ derive(Debug, PartialEq, Hash, Eq, Ord, PartialOrd, Copy, Clone) ]
@ -55,10 +54,36 @@ pub struct CachedEnvelope {
pub modsequence : Option < ModSequence > ,
}
pub struct CacheHandle {
#[ cfg(feature = " sqlite3 " ) ]
connection : crate ::sqlite3 ::Connection ,
uid_store : Arc < UIDStore > ,
pub trait ImapCache : Send {
fn mailbox_state ( & mut self , mailbox_hash : MailboxHash ) -> Result < Option < ( ) > > ;
fn find_envelope (
& mut self ,
identifier : std ::result ::Result < UID , EnvelopeHash > ,
mailbox_hash : MailboxHash ,
) -> Result < Option < CachedEnvelope > > ;
fn update (
& mut self ,
mailbox_hash : MailboxHash ,
refresh_events : & [ ( UID , RefreshEvent ) ] ,
) -> Result < ( ) > ;
fn insert_envelopes (
& mut self ,
mailbox_hash : MailboxHash ,
fetches : & [ FetchResponse < ' _ > ] ,
) -> Result < ( ) > ;
fn envelopes ( & mut self , mailbox_hash : MailboxHash ) -> Result < Option < Vec < EnvelopeHash > > > ;
fn clear ( & mut self , mailbox_hash : MailboxHash , select_response : & SelectResponse ) -> Result < ( ) > ;
fn rfc822 (
& mut self ,
identifier : std ::result ::Result < UID , EnvelopeHash > ,
mailbox_hash : MailboxHash ,
) -> Result < Option < Vec < u8 > > > ;
}
#[ cfg(feature = " sqlite3 " ) ]
@ -71,28 +96,43 @@ mod sqlite3_m {
FromSql , FromSqlError , FromSqlResult , ToSql , ToSqlOutput ,
} ;
use crate ::sqlite3 ::{ self , DatabaseDescription } ;
type Sqlite3UID = i32 ;
pub struct Sqlite3Cache {
connection : crate ::sqlite3 ::Connection ,
loaded_mailboxes : BTreeSet < MailboxHash > ,
uid_store : Arc < UIDStore > ,
}
const DB_DESCRIPTION : DatabaseDescription = DatabaseDescription {
name : "header_cache.db" ,
init_script : Some ( " PRAGMA foreign_keys = true ;
init_script : Some (
" PRAGMA foreign_keys = true ;
PRAGMA encoding = ' UTF - 8 ' ;
CREATE TABLE IF NOT EXISTS envelopes (
mailbox_hash INTEGER ,
uid INTEGER ,
hash INTEGER NOT NULL ,
mailbox_hash INTEGER NOT NULL ,
uid INTEGER NOT NULL ,
modsequence INTEGER ,
rfc822 BLOB ,
envelope BLOB NOT NULL ,
PRIMARY KEY ( mailbox_hash , uid ) ,
FOREIGN KEY ( mailbox_hash ) REFERENCES uidvalidity ( mailbox_hash ) ON DELETE CASCADE
FOREIGN KEY ( mailbox_hash ) REFERENCES mailbox ( mailbox_hash ) ON DELETE CASCADE
) ;
CREATE TABLE IF NOT EXISTS uidvalidity (
uid INTEGER UNIQUE ,
CREATE TABLE IF NOT EXISTS mailbox (
mailbox_hash INTEGER UNIQUE ,
uidvalidity INTEGER ,
flags BLOB NOT NULL ,
highestmodseq INTEGER ,
PRIMARY KEY ( mailbox_hash , uid )
PRIMARY KEY ( mailbox_hash )
) ;
CREATE INDEX IF NOT EXISTS envelope_idx ON envelopes ( mailbox_hash ) ;
CREATE INDEX IF NOT EXISTS uidvalidity_idx ON uidvalidity ( mailbox_hash ) ; " ) ,
version : 1 ,
CREATE INDEX IF NOT EXISTS envelope_uid_idx ON envelopes ( mailbox_hash , uid ) ;
CREATE INDEX IF NOT EXISTS envelope_idx ON envelopes ( hash ) ;
CREATE INDEX IF NOT EXISTS mailbox_idx ON mailbox ( mailbox_hash ) ; " ,
) ,
version : 1 ,
} ;
impl ToSql for ModSequence {
@ -111,47 +151,108 @@ mod sqlite3_m {
}
}
impl CacheHandl e {
pub fn get ( uid_store : Arc < UIDStore > ) -> Result < Self > {
Ok ( Self {
impl Sqlite3 Cache {
pub fn get ( uid_store : Arc < UIDStore > ) -> Result < Box < dyn ImapCache > > {
Ok ( Box ::new ( Self {
connection : sqlite3 ::open_or_create_db (
& DB_DESCRIPTION ,
Some ( uid_store . account_name . as_str ( ) ) ,
) ? ,
loaded_mailboxes : BTreeSet ::default ( ) ,
uid_store ,
} )
} ) )
}
pub fn mailbox_state (
& self ,
mailbox_hash : MailboxHash ,
) -> Result < Option < ( UID , Option < ModSequence > ) > > {
fn max_uid ( & self , mailbox_hash : MailboxHash ) -> Result < UID > {
let mut stmt = self
. connection
. prepare ( "SELECT uid, highestmodseq FROM uidvalidity WHERE mailbox_hash = ?1;" ) ? ;
. 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 | {
Ok ( row . get ( 0 ) . map ( | i : Sqlite3UID | i as UID ) ? )
} ) ?
. collect ::< std ::result ::Result < _ , _ > > ( ) ? ;
Ok ( ret . pop ( ) . unwrap_or ( 0 ) )
}
}
impl ImapCache for Sqlite3Cache {
fn mailbox_state ( & mut self , mailbox_hash : MailboxHash ) -> Result < Option < ( ) > > {
if self . loaded_mailboxes . contains ( & mailbox_hash ) {
return Ok ( Some ( ( ) ) ) ;
}
debug ! ( "loading mailbox state {} from cache" , mailbox_hash ) ;
let mut stmt = self . connection . prepare (
"SELECT uidvalidity, flags, highestmodseq FROM mailbox WHERE mailbox_hash = ?1;" ,
) ? ;
let mut ret = stmt . query_map ( sqlite3 ::params ! [ mailbox_hash as i64 ] , | row | {
Ok ( ( row . get ( 0 ) . map ( | u : i64 | u as usize ) ? , row . get ( 1 ) ? ) )
Ok ( (
row . get ( 0 ) . map ( | u : Sqlite3UID | u as UID ) ? ,
row . get ( 1 ) ? ,
row . get ( 2 ) ? ,
) )
} ) ? ;
if let Some ( row_res ) = ret . next ( ) {
Ok ( Some ( row_res ? ) )
if let Some ( v ) = ret . next ( ) {
let ( uidvalidity , flags , highestmodseq ) : (
UIDVALIDITY ,
Vec < u8 > ,
Option < ModSequence > ,
) = v ? ;
debug ! (
"mailbox state {} in cache uidvalidity {}" ,
mailbox_hash , uidvalidity
) ;
debug ! (
"mailbox state {} in cache highestmodseq {:?}" ,
mailbox_hash , & highestmodseq
) ;
debug ! (
"mailbox state {} inserting flags: {:?}" ,
mailbox_hash ,
to_str ! ( & flags )
) ;
self . uid_store
. highestmodseqs
. lock ( )
. unwrap ( )
. entry ( mailbox_hash )
. and_modify ( | entry | * entry = highestmodseq . ok_or ( ( ) ) )
. or_insert ( highestmodseq . ok_or ( ( ) ) ) ;
self . uid_store
. uidvalidity
. lock ( )
. unwrap ( )
. entry ( mailbox_hash )
. and_modify ( | entry | * entry = uidvalidity )
. or_insert ( uidvalidity ) ;
let mut tag_lck = self . uid_store . tag_index . write ( ) . unwrap ( ) ;
for f in to_str ! ( & flags ) . split ( '\0' ) {
let hash = tag_hash ! ( f ) ;
//debug!("hash {} flag {}", hash, &f);
if ! tag_lck . contains_key ( & hash ) {
tag_lck . insert ( hash , f . to_string ( ) ) ;
}
}
self . loaded_mailboxes . insert ( mailbox_hash ) ;
Ok ( Some ( ( ) ) )
} else {
debug ! ( "mailbox state {} not in cache" , mailbox_hash ) ;
Ok ( None )
}
}
pub fn clear (
& self ,
fn clear (
& mut self ,
mailbox_hash : MailboxHash ,
new_uidvalidity : UID ,
highestmodseq : Option < ModSequence > ,
select_response : & SelectResponse ,
) -> Result < ( ) > {
debug ! ( "clear mailbox_hash {}" , mailbox_hash ) ;
debug ! ( new_uidvalidity ) ;
debug ! ( & highestmodseq ) ;
debug ! ( "clear mailbox_hash {} {:?}" , mailbox_hash , select_response ) ;
self . loaded_mailboxes . remove ( & mailbox_hash ) ;
self . connection
. execute (
"DELETE FROM uidvalidity WHERE mailbox_hash = ?1" ,
"DELETE FROM mailbox WHERE mailbox_hash = ?1",
sqlite3 ::params ! [ mailbox_hash as i64 ] ,
)
. chain_err_summary ( | | {
@ -161,20 +262,38 @@ mod sqlite3_m {
)
} ) ? ;
self . connection . execute (
"INSERT OR IGNORE INTO uidvalidity (uid, highestmodseq, mailbox_hash) VALUES (?1, ?2, ?3)" ,
sqlite3 ::params ! [ new_uidvalidity as i64 , highestmodseq , mailbox_hash as i64 ] ,
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 ] ,
)
. chain_err_summary ( | | {
format! (
"Could not insert uidvalidity {} in header_cache of account {}" ,
new_ uidvalidity, self . uid_store . account_name
select_response. uidvalidity, self . uid_store . account_name
)
} ) ? ;
} else {
self . connection
. execute (
"INSERT OR IGNORE INTO mailbox (uidvalidity, flags, mailbox_hash) VALUES (?1, ?2, ?3)" ,
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
] ,
)
. chain_err_summary ( | | {
format! (
"Could not insert mailbox {} in header_cache of account {}" ,
select_response . uidvalidity , self . uid_store . account_name
)
} ) ? ;
}
Ok ( ( ) )
}
pub fn envelopes ( & self , mailbox_hash : MailboxHash ) -> Result < Option < Vec < EnvelopeHash > > > {
fn envelopes ( & mut self , mailbox_hash : MailboxHash ) -> Result < Option < Vec < EnvelopeHash > > > {
debug ! ( "envelopes mailbox_hash {}" , mailbox_hash ) ;
if debug ! ( self . mailbox_state ( mailbox_hash ) ? . is_none ( ) ) {
return Ok ( None ) ;
@ -187,7 +306,7 @@ mod sqlite3_m {
let ret : Vec < ( UID , Envelope , Option < ModSequence > ) > = stmt
. query_map ( sqlite3 ::params ! [ mailbox_hash as i64 ] , | row | {
Ok ( (
row . get ( 0 ) . map ( | i : i64 | i as usize ) ? ,
row . get ( 0 ) . map ( | i : Sqlite3UID | i as UID ) ? ,
row . get ( 1 ) ? ,
row . get ( 2 ) ? ,
) )
@ -221,7 +340,7 @@ mod sqlite3_m {
Ok ( Some ( env_hashes ) )
}
pub fn insert_envelopes (
fn insert_envelopes (
& mut self ,
mailbox_hash : MailboxHash ,
fetches : & [ FetchResponse < ' _ > ] ,
@ -231,35 +350,22 @@ mod sqlite3_m {
mailbox_hash ,
fetches . len ( )
) ;
let mut max_uid = self
. uid_store
. max_uids
. lock ( )
. unwrap ( )
. get ( & mailbox_hash )
. cloned ( )
. unwrap_or_default ( ) ;
if self . mailbox_state ( mailbox_hash ) ? . is_none ( ) {
debug ! ( self . mailbox_state ( mailbox_hash ) ? . is_none ( ) ) ;
let uidvalidity = self
. uid_store
. uidvalidity
. lock ( )
. unwrap ( )
. get ( & mailbox_hash )
. cloned ( ) ;
let highestmodseq = self
. uid_store
. highestmodseqs
. lock ( )
. unwrap ( )
. get ( & mailbox_hash )
. cloned ( ) ;
debug ! ( & uidvalidity ) ;
debug ! ( & highestmodseq ) ;
if let Some ( uidvalidity ) = uidvalidity {
debug ! ( self . clear (
mailbox_hash ,
uidvalidity ,
highestmodseq . and_then ( | v | v . ok ( ) ) ,
) ) ? ;
}
return Err ( MeliError ::new ( "Mailbox is not in cache" ) . set_kind ( ErrorKind ::Bug ) ) ;
}
let Self {
ref mut connection ,
ref uid_store ,
loaded_mailboxes : _ ,
} = self ;
let tx = connection . transaction ( ) ? ;
for item in fetches {
@ -272,17 +378,23 @@ mod sqlite3_m {
envelope : Some ( envelope ) ,
} = item
{
max_uid = std ::cmp ::max ( max_uid , * uid ) ;
tx . execute (
"INSERT OR REPLACE INTO envelopes ( uid, mailbox_hash, modsequence, envelope) VALUES (?1, ?2, ?3, ?4)",
sqlite3 ::params ! [ * uid as i64 , mailbox_hash as i64 , modseq , & envelope ] ,
"INSERT OR REPLACE INTO envelopes ( hash, uid, mailbox_hash, modsequence, envelope) VALUES (?1, ?2, ?3, ?4, ?5 )",
sqlite3 ::params ! [ envelope . hash ( ) as i64 , * uid as Sqlite3UID , mailbox_hash as i64 , modseq , & envelope ] ,
) . chain_err_summary ( | | format! ( "Could not insert envelope {} {} in header_cache of account {}" , envelope . message_id ( ) , envelope . hash ( ) , uid_store . account_name ) ) ? ;
}
}
tx . commit ( ) ? ;
self . uid_store
. max_uids
. lock ( )
. unwrap ( )
. insert ( mailbox_hash , max_uid ) ;
Ok ( ( ) )
}
pub fn update (
fn update (
& mut self ,
mailbox_hash : MailboxHash ,
refresh_events : & [ ( UID , RefreshEvent ) ] ,
@ -294,33 +406,12 @@ mod sqlite3_m {
) ;
if self . mailbox_state ( mailbox_hash ) ? . is_none ( ) {
debug ! ( self . mailbox_state ( mailbox_hash ) ? . is_none ( ) ) ;
let uidvalidity = self
. uid_store
. uidvalidity
. lock ( )
. unwrap ( )
. get ( & mailbox_hash )
. cloned ( ) ;
let highestmodseq = self
. uid_store
. highestmodseqs
. lock ( )
. unwrap ( )
. get ( & mailbox_hash )
. cloned ( ) ;
debug ! ( & uidvalidity ) ;
debug ! ( & highestmodseq ) ;
if let Some ( uidvalidity ) = uidvalidity {
debug ! ( self . clear (
mailbox_hash ,
uidvalidity ,
highestmodseq . and_then ( | v | v . ok ( ) ) ,
) ) ? ;
}
return Err ( MeliError ::new ( "Mailbox is not in cache" ) . set_kind ( ErrorKind ::Bug ) ) ;
}
let Self {
ref mut connection ,
ref uid_store ,
loaded_mailboxes : _ ,
} = self ;
let tx = connection . transaction ( ) ? ;
let mut hash_index_lck = uid_store . hash_index . lock ( ) . unwrap ( ) ;
@ -330,7 +421,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 i64 ] ,
sqlite3 ::params ! [ mailbox_hash as i64 , * uid as Sqlite3UID ] ,
)
. chain_err_summary ( | | {
format! (
@ -345,9 +436,10 @@ mod sqlite3_m {
) ? ;
let mut ret : Vec < Envelope > = stmt
. query_map ( sqlite3 ::params ! [ mailbox_hash as i64 , * uid as i64 ] , | row | {
Ok ( row . get ( 0 ) ? )
} ) ?
. query_map (
sqlite3 ::params ! [ mailbox_hash as i64 , * uid as Sqlite3UID ] ,
| row | Ok ( row . get ( 0 ) ? ) ,
) ?
. collect ::< std ::result ::Result < _ , _ > > ( ) ? ;
if let Some ( mut env ) = ret . pop ( ) {
env . set_flags ( * flags ) ;
@ -355,7 +447,7 @@ mod sqlite3_m {
env . labels_mut ( ) . extend ( tags . iter ( ) . map ( | t | tag_hash ! ( t ) ) ) ;
tx . execute (
"UPDATE envelopes SET envelope = ?1 WHERE mailbox_hash = ?2 AND uid = ?3;" ,
sqlite3 ::params ! [ & env , mailbox_hash as i64 , * uid as i64 ] ,
sqlite3 ::params ! [ & env , mailbox_hash as i64 , * uid as Sqlite3UID ] ,
)
. chain_err_summary ( | | {
format! (
@ -377,48 +469,108 @@ mod sqlite3_m {
}
}
tx . commit ( ) ? ;
let new_max_uid = self . max_uid ( mailbox_hash ) ? ;
self . uid_store
. max_uids
. lock ( )
. unwrap ( )
. insert ( mailbox_hash , new_max_uid ) ;
Ok ( ( ) )
}
}
}
#[ cfg(not(feature = " sqlite3 " )) ]
pub use filesystem_m ::* ;
#[ cfg(not(feature = " sqlite3 " )) ]
mod filesystem_m {
use super ::* ;
impl CacheHandle {
pub fn get ( uid_store : Arc < UIDStore > ) -> Result < Self > {
Ok ( Self { uid_store } )
}
pub fn mailbox_state (
& self ,
_mailbox_hash : MailboxHash ,
) -> Result < Option < ( UID , Option < ModSequence > ) > > {
Ok ( None )
}
fn find_envelope (
& mut self ,
identifier : std ::result ::Result < UID , EnvelopeHash > ,
mailbox_hash : MailboxHash ,
) -> Result < Option < CachedEnvelope > > {
let mut ret : Vec < ( UID , Envelope , Option < ModSequence > ) > = match identifier {
Ok ( uid ) = > {
let mut stmt = self . connection . prepare (
"SELECT uid, envelope, modsequence FROM envelopes WHERE mailbox_hash = ?1 AND uid = ?2;" ,
) ? ;
pub fn clear (
& self ,
_mailbox_hash : MailboxHash ,
_new_uidvalidity : UID ,
_highestmodseq : Option < ModSequence > ,
) -> Result < ( ) > {
Ok ( ( ) )
}
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 ) ? ,
) )
} ,
) ?
. collect ::< std ::result ::Result < _ , _ > > ( ) ? ;
x
}
Err ( env_hash ) = > {
let mut stmt = self . connection . prepare (
"SELECT uid, envelope, modsequence FROM envelopes WHERE mailbox_hash = ?1 AND hash = ?2;" ,
) ? ;
pub fn envelopes ( & self , _mailbox_hash : MailboxHash ) -> Result < Option < Vec < EnvelopeHash > > > {
Ok ( None )
let x = stmt
. query_map (
sqlite3 ::params ! [ mailbox_hash as i64 , env_hash as i64 ] ,
| row | {
Ok ( (
row . get ( 0 ) . map ( | u : Sqlite3UID | u as UID ) ? ,
row . get ( 1 ) ? ,
row . get ( 2 ) ? ,
) )
} ,
) ?
. collect ::< std ::result ::Result < _ , _ > > ( ) ? ;
x
}
} ;
if ret . len ( ) ! = 1 {
return Ok ( None ) ;
}
let ( uid , inner , modsequence ) = ret . pop ( ) . unwrap ( ) ;
return Ok ( Some ( CachedEnvelope {
inner ,
uid ,
mailbox_hash ,
modsequence ,
} ) ) ;
}
pub fn insert_envelopes (
fn rfc822 (
& mut self ,
_mailbox_hash : MailboxHash ,
_fetches : & [ FetchResponse < ' _ > ] ,
) -> Result < ( ) > {
Ok ( ( ) )
identifier : std ::result ::Result < UID , EnvelopeHash > ,
mailbox_hash : MailboxHash ,
) -> Result < Option < Vec < u8 > > > {
let mut ret : Vec < Option < Vec < u8 > > > = match identifier {
Ok ( uid ) = > {
let mut stmt = self . connection . prepare (
"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 | Ok ( row . get ( 0 ) ? ) ,
) ?
. collect ::< std ::result ::Result < _ , _ > > ( ) ? ;
x
}
Err ( env_hash ) = > {
let mut stmt = self . connection . prepare (
"SELECT rfc822 FROM envelopes WHERE mailbox_hash = ?1 AND hash = ?2;" ,
) ? ;
let x = stmt
. query_map (
sqlite3 ::params ! [ mailbox_hash as i64 , env_hash as i64 ] ,
| row | Ok ( row . get ( 0 ) ? ) ,
) ?
. collect ::< std ::result ::Result < _ , _ > > ( ) ? ;
x
}
} ;
if ret . len ( ) ! = 1 {
return Ok ( None ) ;
}
Ok ( ret . pop ( ) . unwrap ( ) )
}
}
}
@ -428,7 +580,6 @@ pub(super) async fn fetch_cached_envs(state: &mut FetchState) -> Result<Option<V
stage : _ ,
ref mut connection ,
mailbox_hash ,
can_create_flags : _ ,
ref uid_store ,
} = state ;
debug ! ( uid_store . keep_offline_cache ) ;
@ -481,3 +632,59 @@ pub(super) async fn fetch_cached_envs(state: &mut FetchState) -> Result<Option<V
}
}
}
#[ cfg(not(feature = " sqlite3 " )) ]
pub use default_m ::* ;
#[ cfg(not(feature = " sqlite3 " )) ]
mod default_m {
pub struct DefaultCache ;
impl DefaultCache {
pub fn get ( _uid_store : Arc < UIDStore > ) -> Result < Box < dyn ImapCache > > {
Ok ( Box ::new ( Self ) )
}
}
impl ImapCache for DefaultCache {
fn mailbox_state ( & mut self , _mailbox_hash : MailboxHash ) -> Result < Option < ( ) > > {
Err ( MeliError ::new ( "melib is not built with any imap cache" ) . set_kind ( ErrorKind ::Bug ) )
}
fn clear (
& mut self ,
_mailbox_hash : MailboxHash ,
_select_response : & SelectResponse ,
) -> Result < ( ) > {
Err ( MeliError ::new ( "melib is not built with any imap cache" ) . set_kind ( ErrorKind ::Bug ) )
}
fn envelopes ( & mut self , _mailbox_hash : MailboxHash ) -> Result < Option < Vec < EnvelopeHash > > > {
Err ( MeliError ::new ( "melib is not built with any imap cache" ) . set_kind ( ErrorKind ::Bug ) )
}
fn insert_envelopes (
& mut self ,
_mailbox_hash : MailboxHash ,
_fetches : & [ FetchResponse < ' _ > ] ,
) -> Result < ( ) > {
Err ( MeliError ::new ( "melib is not built with any imap cache" ) . set_kind ( ErrorKind ::Bug ) )
}
fn update (
& mut self ,
_mailbox_hash : MailboxHash ,
_refresh_events : & [ ( UID , RefreshEvent ) ] ,
) -> Result < ( ) > {
Err ( MeliError ::new ( "melib is not built with any imap cache" ) . set_kind ( ErrorKind ::Bug ) )
}
fn find_envelope (
& mut self ,
_identifier : std ::result ::Result < UID , EnvelopeHash > ,
_mailbox_hash : MailboxHash ,
) -> Result < Option < CachedEnvelope > > {
Err ( MeliError ::new ( "melib is not built with any imap cache" ) . set_kind ( ErrorKind ::Bug ) )
}
}
}