2017-09-07 20:00:08 +00:00
/*
* meli - backends module
*
* Copyright 2017 Manos Pitsidianakis
*
* This file is part of meli .
*
* meli is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* meli is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with meli . If not , see < http ://www.gnu.org/licenses/>.
* /
2019-12-08 08:57:36 +00:00
2020-04-04 17:09:51 +00:00
use smallvec ::SmallVec ;
2019-12-08 08:57:36 +00:00
#[ macro_export ]
macro_rules ! tag_hash {
( $tag :ident ) = > { {
2020-02-28 07:04:01 +00:00
use std ::collections ::hash_map ::DefaultHasher ;
use std ::hash ::Hasher ;
2019-12-08 08:57:36 +00:00
let mut hasher = DefaultHasher ::new ( ) ;
hasher . write ( $tag . as_bytes ( ) ) ;
hasher . finish ( )
} } ;
}
2019-09-21 18:23:06 +00:00
#[ cfg(feature = " imap_backend " ) ]
2018-07-27 18:37:56 +00:00
pub mod imap ;
2020-06-27 18:40:46 +00:00
#[ cfg(feature = " imap_backend " ) ]
pub mod imap_async ;
2020-06-22 08:29:36 +00:00
//#[cfg(feature = "imap_backend")]
//pub mod imap2;
2019-09-21 18:23:06 +00:00
#[ cfg(feature = " maildir_backend " ) ]
2017-09-05 13:41:29 +00:00
pub mod maildir ;
2019-09-21 18:23:06 +00:00
#[ cfg(feature = " mbox_backend " ) ]
2018-07-13 15:38:57 +00:00
pub mod mbox ;
2019-11-14 15:55:06 +00:00
#[ cfg(feature = " notmuch_backend " ) ]
pub mod notmuch ;
#[ cfg(feature = " notmuch_backend " ) ]
pub use self ::notmuch ::NotmuchDb ;
2019-12-03 11:25:49 +00:00
#[ cfg(feature = " jmap_backend " ) ]
pub mod jmap ;
#[ cfg(feature = " jmap_backend " ) ]
pub use self ::jmap ::JmapType ;
2017-09-05 13:41:29 +00:00
2019-09-21 18:23:06 +00:00
#[ cfg(feature = " imap_backend " ) ]
2019-06-28 16:34:40 +00:00
pub use self ::imap ::ImapType ;
2019-04-04 11:21:52 +00:00
use crate ::async_workers ::* ;
use crate ::conf ::AccountSettings ;
2019-07-18 17:16:51 +00:00
use crate ::error ::{ MeliError , Result } ;
2019-09-21 18:23:06 +00:00
#[ cfg(feature = " maildir_backend " ) ]
2019-04-04 11:21:52 +00:00
use self ::maildir ::MaildirType ;
2019-09-21 18:23:06 +00:00
#[ cfg(feature = " mbox_backend " ) ]
2019-07-11 08:44:27 +00:00
use self ::mbox ::MboxType ;
2019-04-04 11:21:52 +00:00
use super ::email ::{ Envelope , EnvelopeHash , Flag } ;
2019-11-06 12:53:12 +00:00
use std ::any ::Any ;
2019-11-30 15:37:00 +00:00
use std ::collections ::BTreeMap ;
2017-09-14 15:08:14 +00:00
use std ::fmt ;
2018-08-11 15:00:21 +00:00
use std ::fmt ::Debug ;
2018-09-23 16:55:29 +00:00
use std ::ops ::Deref ;
2019-11-30 15:37:00 +00:00
use std ::sync ::{ Arc , RwLock } ;
2017-09-14 15:08:14 +00:00
2020-06-27 18:40:46 +00:00
use core ::pin ::Pin ;
2020-06-22 08:29:36 +00:00
pub use futures ::stream ::Stream ;
2020-06-27 18:40:46 +00:00
use std ::future ::Future ;
2020-06-22 08:29:36 +00:00
2017-09-30 17:02:22 +00:00
use std ;
2020-05-10 18:14:49 +00:00
use std ::collections ::HashMap ;
2017-09-30 17:53:14 +00:00
2020-02-05 23:49:18 +00:00
#[ macro_export ]
macro_rules ! get_path_hash {
( $path :expr ) = > { {
use std ::collections ::hash_map ::DefaultHasher ;
use std ::hash ::{ Hash , Hasher } ;
let mut hasher = DefaultHasher ::new ( ) ;
$path . hash ( & mut hasher ) ;
hasher . finish ( )
} } ;
}
2019-11-15 22:33:22 +00:00
pub type BackendCreator = Box <
dyn Fn (
& AccountSettings ,
Box < dyn Fn ( & str ) -> bool + Send + Sync > ,
) -> Result < Box < dyn MailBackend > > ,
> ;
2018-08-11 15:00:21 +00:00
2017-09-30 17:53:14 +00:00
/// A hashmap containing all available mail backends.
2018-07-10 08:18:11 +00:00
/// An abstraction over any available backends.
2017-09-30 17:02:22 +00:00
pub struct Backends {
2020-05-10 18:14:49 +00:00
map : HashMap < std ::string ::String , Backend > ,
2019-11-27 12:22:53 +00:00
}
pub struct Backend {
pub create_fn : Box < dyn Fn ( ) -> BackendCreator > ,
pub validate_conf_fn : Box < dyn Fn ( & AccountSettings ) -> Result < ( ) > > ,
2017-09-30 17:02:22 +00:00
}
2018-08-23 12:36:52 +00:00
impl Default for Backends {
fn default ( ) -> Self {
Backends ::new ( )
}
}
2020-02-26 12:18:00 +00:00
#[ cfg(feature = " notmuch_backend " ) ]
pub const NOTMUCH_ERROR_MSG : & 'static str =
" libnotmuch5 was not found in your system. Make sure it is installed and in the library paths. \n " ;
#[ cfg(not(feature = " notmuch_backend " )) ]
pub const NOTMUCH_ERROR_MSG : & 'static str = " this version of meli is not compiled with notmuch support. Use an appropriate version and make sure libnotmuch5 is installed and in the library paths. \n " ;
2017-09-30 17:02:22 +00:00
impl Backends {
pub fn new ( ) -> Self {
2017-09-30 17:53:14 +00:00
let mut b = Backends {
2020-05-10 18:14:49 +00:00
map : HashMap ::with_capacity_and_hasher ( 1 , Default ::default ( ) ) ,
2017-09-30 17:53:14 +00:00
} ;
2019-09-21 18:23:06 +00:00
#[ cfg(feature = " maildir_backend " ) ]
{
b . register (
" maildir " . to_string ( ) ,
2019-11-27 12:22:53 +00:00
Backend {
create_fn : Box ::new ( | | Box ::new ( | f , i | MaildirType ::new ( f , i ) ) ) ,
validate_conf_fn : Box ::new ( MaildirType ::validate_config ) ,
} ,
2019-09-21 18:23:06 +00:00
) ;
}
#[ cfg(feature = " mbox_backend " ) ]
{
b . register (
" mbox " . to_string ( ) ,
2019-11-27 12:22:53 +00:00
Backend {
create_fn : Box ::new ( | | Box ::new ( | f , i | MboxType ::new ( f , i ) ) ) ,
validate_conf_fn : Box ::new ( MboxType ::validate_config ) ,
} ,
2019-09-21 18:23:06 +00:00
) ;
}
#[ cfg(feature = " imap_backend " ) ]
{
b . register (
" imap " . to_string ( ) ,
2019-11-27 12:22:53 +00:00
Backend {
create_fn : Box ::new ( | | Box ::new ( | f , i | ImapType ::new ( f , i ) ) ) ,
validate_conf_fn : Box ::new ( ImapType ::validate_config ) ,
} ,
2019-09-21 18:23:06 +00:00
) ;
2020-06-27 18:40:46 +00:00
b . register (
" imap_async " . to_string ( ) ,
Backend {
create_fn : Box ::new ( | | Box ::new ( | f , i | imap_async ::ImapType ::new ( f , i ) ) ) ,
validate_conf_fn : Box ::new ( imap_async ::ImapType ::validate_config ) ,
} ,
) ;
2019-09-21 18:23:06 +00:00
}
2019-11-14 15:55:06 +00:00
#[ cfg(feature = " notmuch_backend " ) ]
{
2020-02-26 12:18:00 +00:00
if libloading ::Library ::new ( " libnotmuch.so.5 " ) . is_ok ( ) {
b . register (
" notmuch " . to_string ( ) ,
Backend {
create_fn : Box ::new ( | | Box ::new ( | f , i | NotmuchDb ::new ( f , i ) ) ) ,
validate_conf_fn : Box ::new ( NotmuchDb ::validate_config ) ,
} ,
) ;
}
2019-11-14 15:55:06 +00:00
}
2019-12-03 11:25:49 +00:00
#[ cfg(feature = " jmap_backend " ) ]
{
b . register (
" jmap " . to_string ( ) ,
Backend {
create_fn : Box ::new ( | | Box ::new ( | f , i | JmapType ::new ( f , i ) ) ) ,
validate_conf_fn : Box ::new ( JmapType ::validate_config ) ,
} ,
) ;
}
2017-09-30 17:53:14 +00:00
b
2017-09-30 17:02:22 +00:00
}
2018-08-11 15:00:21 +00:00
pub fn get ( & self , key : & str ) -> BackendCreator {
2017-09-30 17:02:22 +00:00
if ! self . map . contains_key ( key ) {
2020-02-26 12:18:00 +00:00
if key = = " notmuch " {
eprint! ( " {} " , NOTMUCH_ERROR_MSG ) ;
}
2017-09-30 17:53:14 +00:00
panic! ( " {} is not a valid mail backend " , key ) ;
2017-09-30 17:02:22 +00:00
}
2019-11-27 12:22:53 +00:00
( self . map [ key ] . create_fn ) ( )
2017-09-30 17:02:22 +00:00
}
2018-08-13 06:25:48 +00:00
2019-11-27 12:22:53 +00:00
pub fn register ( & mut self , key : String , backend : Backend ) {
2017-09-30 17:02:22 +00:00
if self . map . contains_key ( & key ) {
2017-09-30 17:53:14 +00:00
panic! ( " {} is an already registered backend " , key ) ;
2017-09-30 17:02:22 +00:00
}
self . map . insert ( key , backend ) ;
}
2019-11-27 12:22:53 +00:00
pub fn validate_config ( & self , key : & str , s : & AccountSettings ) -> Result < ( ) > {
( self
. map
. get ( key )
2020-02-26 12:18:00 +00:00
. ok_or_else ( | | {
MeliError ::new ( format! (
" {}{} is not a valid mail backend " ,
if key = = " notmuch " {
NOTMUCH_ERROR_MSG
} else {
" "
} ,
key
) )
} ) ?
2019-11-27 12:22:53 +00:00
. validate_conf_fn ) ( s )
}
2017-09-30 17:02:22 +00:00
}
2020-05-10 19:05:04 +00:00
#[ derive(Debug, Clone) ]
2018-09-05 13:08:11 +00:00
pub enum RefreshEventKind {
2018-09-12 12:10:19 +00:00
Update ( EnvelopeHash , Box < Envelope > ) ,
2018-10-14 16:49:16 +00:00
/// Rename(old_hash, new_hash)
Rename ( EnvelopeHash , EnvelopeHash ) ,
2018-09-12 12:10:19 +00:00
Create ( Box < Envelope > ) ,
2019-10-24 17:30:17 +00:00
Remove ( EnvelopeHash ) ,
2020-02-28 07:09:43 +00:00
NewFlags ( EnvelopeHash , ( Flag , Vec < String > ) ) ,
2018-09-05 13:08:11 +00:00
Rescan ,
2019-08-14 19:59:46 +00:00
Failure ( MeliError ) ,
2018-09-05 13:08:11 +00:00
}
2020-05-10 19:05:04 +00:00
#[ derive(Debug, Clone) ]
2017-09-28 15:06:35 +00:00
pub struct RefreshEvent {
2020-05-10 19:05:04 +00:00
mailbox_hash : MailboxHash ,
account_hash : AccountHash ,
2018-09-05 13:08:11 +00:00
kind : RefreshEventKind ,
2018-08-24 23:23:40 +00:00
}
impl RefreshEvent {
2020-05-10 19:05:04 +00:00
pub fn mailbox_hash ( & self ) -> MailboxHash {
self . mailbox_hash
2018-08-24 23:23:40 +00:00
}
2020-05-10 19:05:04 +00:00
pub fn account_hash ( & self ) -> AccountHash {
self . account_hash
}
2018-09-05 13:08:11 +00:00
pub fn kind ( self ) -> RefreshEventKind {
/* consumes self! */
self . kind
2018-08-24 23:23:40 +00:00
}
2017-09-05 13:41:29 +00:00
}
2017-09-14 15:08:14 +00:00
2017-09-30 17:02:22 +00:00
/// A `RefreshEventConsumer` is a boxed closure that must be used to consume a `RefreshEvent` and
/// send it to a UI provided channel. We need this level of abstraction to provide an interface for
/// all users of mailbox refresh events.
2019-09-09 08:54:47 +00:00
pub struct RefreshEventConsumer ( Box < dyn Fn ( RefreshEvent ) -> ( ) + Send + Sync > ) ;
2017-09-28 15:06:35 +00:00
impl RefreshEventConsumer {
2019-09-09 08:54:47 +00:00
pub fn new ( b : Box < dyn Fn ( RefreshEvent ) -> ( ) + Send + Sync > ) -> Self {
2017-09-28 15:06:35 +00:00
RefreshEventConsumer ( b )
}
2019-03-03 20:11:15 +00:00
pub fn send ( & self , r : RefreshEvent ) {
2017-09-28 15:06:35 +00:00
self . 0 ( r ) ;
}
}
2018-09-07 12:36:42 +00:00
2020-05-10 19:05:04 +00:00
impl fmt ::Debug for RefreshEventConsumer {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
write! ( f , " RefreshEventConsumer " )
}
}
2020-02-26 08:54:10 +00:00
pub struct NotifyFn ( Box < dyn Fn ( MailboxHash ) -> ( ) + Send + Sync > ) ;
2018-09-07 12:36:42 +00:00
impl fmt ::Debug for NotifyFn {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
write! ( f , " NotifyFn Box " )
}
}
2020-02-26 08:54:10 +00:00
impl From < Box < dyn Fn ( MailboxHash ) -> ( ) + Send + Sync > > for NotifyFn {
fn from ( kind : Box < dyn Fn ( MailboxHash ) -> ( ) + Send + Sync > ) -> Self {
2018-09-07 12:36:42 +00:00
NotifyFn ( kind )
}
}
impl NotifyFn {
2020-02-26 08:54:10 +00:00
pub fn new ( b : Box < dyn Fn ( MailboxHash ) -> ( ) + Send + Sync > ) -> Self {
2018-09-07 12:36:42 +00:00
NotifyFn ( b )
}
2020-02-26 08:54:10 +00:00
pub fn notify ( & self , f : MailboxHash ) {
2019-03-30 11:41:32 +00:00
self . 0 ( f ) ;
2018-09-07 12:36:42 +00:00
}
}
2019-08-26 16:44:05 +00:00
2019-11-03 11:12:28 +00:00
pub trait MailBackend : ::std ::fmt ::Debug + Send + Sync {
2019-12-14 16:46:12 +00:00
fn is_online ( & self ) -> Result < ( ) > ;
2020-06-27 18:40:46 +00:00
fn is_online_async (
& self ,
) -> Result < Pin < Box < dyn Future < Output = Result < ( ) > > + Send + 'static > > > {
Err ( MeliError ::new ( " Unimplemented. " ) )
}
2019-12-14 16:55:08 +00:00
fn connect ( & mut self ) { }
2020-02-26 08:54:10 +00:00
fn get ( & mut self , mailbox : & Mailbox ) -> Async < Result < Vec < Envelope > > > ;
2020-06-22 08:29:36 +00:00
fn get_async (
& mut self ,
mailbox : & Mailbox ,
2020-06-27 18:40:46 +00:00
) -> Result < Pin < Box < dyn Future < Output = Result < Vec < Envelope > > > + Send + 'static > > > {
2020-06-22 08:29:36 +00:00
Err ( MeliError ::new ( " Unimplemented. " ) )
}
2019-12-14 16:55:46 +00:00
fn refresh (
& mut self ,
2020-02-26 08:54:10 +00:00
_mailbox_hash : MailboxHash ,
2019-12-15 17:47:42 +00:00
_sender : RefreshEventConsumer ,
2020-02-22 09:24:36 +00:00
) -> Result < Async < ( ) > > {
2019-12-15 06:52:22 +00:00
Err ( MeliError ::new ( " Unimplemented. " ) )
2019-12-14 16:55:46 +00:00
}
2020-06-27 18:40:46 +00:00
fn refresh_async (
& mut self ,
_mailbox_hash : MailboxHash ,
_sender : RefreshEventConsumer ,
) -> Result < Pin < Box < dyn Future < Output = Result < ( ) > > + Send + 'static > > > {
Err ( MeliError ::new ( " Unimplemented. " ) )
}
2019-09-11 14:57:55 +00:00
fn watch (
& self ,
sender : RefreshEventConsumer ,
work_context : WorkContext ,
) -> Result < std ::thread ::ThreadId > ;
2020-05-10 18:14:49 +00:00
fn mailboxes ( & self ) -> Result < HashMap < MailboxHash , Mailbox > > ;
2020-06-23 14:21:50 +00:00
fn operation ( & self , hash : EnvelopeHash ) -> Result < Box < dyn BackendOp > > ;
2019-02-16 14:37:14 +00:00
2020-06-08 19:08:10 +00:00
fn save ( & self , bytes : & [ u8 ] , mailbox_hash : MailboxHash , flags : Option < Flag > ) -> Result < ( ) > ;
fn delete ( & self , _env_hash : EnvelopeHash , _mailbox_hash : MailboxHash ) -> Result < ( ) > {
2020-03-01 15:47:23 +00:00
Err ( MeliError ::new ( " Unimplemented. " ) )
}
2019-11-30 15:37:00 +00:00
fn tags ( & self ) -> Option < Arc < RwLock < BTreeMap < u64 , String > > > > {
None
}
2019-11-06 12:53:12 +00:00
fn as_any ( & self ) -> & dyn Any ;
2019-12-10 22:07:47 +00:00
fn as_any_mut ( & mut self ) -> & mut dyn Any {
unimplemented! ( )
}
2020-02-05 23:49:18 +00:00
2020-02-26 08:54:10 +00:00
fn create_mailbox (
2020-02-22 08:57:59 +00:00
& mut self ,
_path : String ,
2020-05-10 18:14:49 +00:00
) -> Result < ( MailboxHash , HashMap < MailboxHash , Mailbox > ) > {
2020-02-05 23:49:18 +00:00
Err ( MeliError ::new ( " Unimplemented. " ) )
}
2020-02-26 08:54:10 +00:00
fn delete_mailbox (
2020-02-22 08:57:59 +00:00
& mut self ,
2020-02-26 08:54:10 +00:00
_mailbox_hash : MailboxHash ,
2020-05-10 18:14:49 +00:00
) -> Result < HashMap < MailboxHash , Mailbox > > {
2020-02-05 23:49:18 +00:00
Err ( MeliError ::new ( " Unimplemented. " ) )
}
2020-02-26 08:54:10 +00:00
fn set_mailbox_subscription ( & mut self , _mailbox_hash : MailboxHash , _val : bool ) -> Result < ( ) > {
2020-02-05 23:49:18 +00:00
Err ( MeliError ::new ( " Unimplemented. " ) )
}
2020-02-26 08:54:10 +00:00
fn rename_mailbox ( & mut self , _mailbox_hash : MailboxHash , _new_path : String ) -> Result < Mailbox > {
2020-02-05 23:49:18 +00:00
Err ( MeliError ::new ( " Unimplemented. " ) )
}
2020-02-26 08:54:10 +00:00
fn set_mailbox_permissions (
2020-02-05 23:49:18 +00:00
& mut self ,
2020-02-26 08:54:10 +00:00
_mailbox_hash : MailboxHash ,
_val : MailboxPermissions ,
2020-02-05 23:49:18 +00:00
) -> Result < ( ) > {
Err ( MeliError ::new ( " Unimplemented. " ) )
2020-04-04 17:09:51 +00:00
}
fn search (
& self ,
_query : crate ::search ::Query ,
_mailbox_hash : Option < MailboxHash > ,
) -> Result < SmallVec < [ EnvelopeHash ; 512 ] > > {
Err ( MeliError ::new ( " Unimplemented. " ) )
2020-02-05 23:49:18 +00:00
}
2017-09-28 15:06:35 +00:00
}
2017-09-14 15:08:14 +00:00
2017-09-16 11:14:08 +00:00
/// A `BackendOp` manages common operations for the various mail backends. They only live for the
2019-07-18 17:14:14 +00:00
/// duration of the operation. They are generated by the `operation` method of `Mailbackend` trait.
2017-09-16 10:32:56 +00:00
///
/// # Motivation
///
/// We need a way to do various operations on individual mails regardless of what backend they come
/// from (eg local or imap).
///
2019-03-26 13:27:02 +00:00
/// # Creation
2019-12-11 14:07:08 +00:00
/// ```ignore
2019-03-26 13:27:02 +00:00
/// /* Create operation from Backend */
///
2020-02-26 08:54:10 +00:00
/// let op = backend.operation(message.hash(), mailbox.hash());
2019-03-26 13:27:02 +00:00
/// ```
///
2017-09-16 10:32:56 +00:00
/// # Example
2019-12-11 14:07:08 +00:00
/// ```ignore
/// use melib::backends::{BackendOp};
2017-10-01 14:31:20 +00:00
/// use melib::Result;
/// use melib::{Envelope, Flag};
2017-09-16 10:32:56 +00:00
///
/// #[derive(Debug)]
/// struct FooOp {}
///
/// impl BackendOp for FooOp {
/// fn description(&self) -> String {
/// "Foobar".to_string()
/// }
/// fn as_bytes(&mut self) -> Result<&[u8]> {
/// unimplemented!()
/// }
2017-10-01 14:31:20 +00:00
/// fn fetch_flags(&self) -> Flag {
2017-09-16 16:15:51 +00:00
/// unimplemented!()
/// }
2017-09-16 10:32:56 +00:00
/// }
///
2019-07-18 17:14:14 +00:00
/// let operation = Box::new(FooOp {});
2017-09-16 10:32:56 +00:00
/// assert_eq!("Foobar", &operation.description());
/// ```
2017-09-14 15:08:14 +00:00
pub trait BackendOp : ::std ::fmt ::Debug + ::std ::marker ::Send {
fn description ( & self ) -> String ;
fn as_bytes ( & mut self ) -> Result < & [ u8 ] > ;
2017-09-16 16:15:51 +00:00
fn fetch_flags ( & self ) -> Flag ;
2019-11-15 18:28:03 +00:00
fn set_flag ( & mut self , envelope : & mut Envelope , flag : Flag , value : bool ) -> Result < ( ) > ;
2019-12-08 08:57:36 +00:00
fn set_tag ( & mut self , envelope : & mut Envelope , tag : String , value : bool ) -> Result < ( ) > ;
2017-09-14 15:08:14 +00:00
}
2019-07-18 17:16:51 +00:00
/// Wrapper for BackendOps that are to be set read-only.
///
/// Warning: Backend implementations may still cause side-effects (for example IMAP can set the
/// Seen flag when fetching an envelope)
#[ derive(Debug) ]
pub struct ReadOnlyOp {
2019-09-09 08:54:47 +00:00
op : Box < dyn BackendOp > ,
2019-07-18 17:16:51 +00:00
}
impl ReadOnlyOp {
2019-09-09 08:54:47 +00:00
pub fn new ( op : Box < dyn BackendOp > ) -> Box < dyn BackendOp > {
2019-07-18 17:16:51 +00:00
Box ::new ( ReadOnlyOp { op } )
}
}
impl BackendOp for ReadOnlyOp {
fn description ( & self ) -> String {
format! ( " read-only: {} " , self . op . description ( ) )
}
fn as_bytes ( & mut self ) -> Result < & [ u8 ] > {
self . op . as_bytes ( )
}
fn fetch_flags ( & self ) -> Flag {
self . op . fetch_flags ( )
}
2019-11-15 18:28:03 +00:00
fn set_flag ( & mut self , _envelope : & mut Envelope , _flag : Flag , _value : bool ) -> Result < ( ) > {
2019-07-18 17:16:51 +00:00
Err ( MeliError ::new ( " read-only set. " ) )
2017-09-14 15:08:14 +00:00
}
2019-12-08 08:57:36 +00:00
fn set_tag ( & mut self , _envelope : & mut Envelope , _tag : String , _value : bool ) -> Result < ( ) > {
Err ( MeliError ::new ( " read-only set. " ) )
}
2017-09-14 15:08:14 +00:00
}
2018-08-11 15:00:21 +00:00
2019-08-25 18:44:19 +00:00
#[ derive(Debug, Copy, Hash, Eq, Clone, Serialize, Deserialize, PartialEq) ]
2019-12-10 22:15:36 +00:00
pub enum SpecialUsageMailbox {
2019-08-23 18:58:41 +00:00
Normal ,
Inbox ,
Archive ,
Drafts ,
Flagged ,
Junk ,
Sent ,
Trash ,
}
2019-12-17 12:12:41 +00:00
impl std ::fmt ::Display for SpecialUsageMailbox {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
use SpecialUsageMailbox ::* ;
write! (
f ,
" {} " ,
match self {
Normal = > " Normal " ,
Inbox = > " Inbox " ,
Archive = > " Archive " ,
Drafts = > " Drafts " ,
Flagged = > " Flagged " ,
Junk = > " Junk " ,
Sent = > " Sent " ,
Trash = > " Trash " ,
}
)
}
}
2019-12-10 22:15:36 +00:00
impl Default for SpecialUsageMailbox {
fn default ( ) -> Self {
SpecialUsageMailbox ::Normal
}
}
2019-12-07 12:04:25 +00:00
impl SpecialUsageMailbox {
pub fn detect_usage ( name : & str ) -> Option < SpecialUsageMailbox > {
if name . eq_ignore_ascii_case ( " inbox " ) {
Some ( SpecialUsageMailbox ::Inbox )
} else if name . eq_ignore_ascii_case ( " archive " ) {
Some ( SpecialUsageMailbox ::Archive )
} else if name . eq_ignore_ascii_case ( " drafts " ) {
Some ( SpecialUsageMailbox ::Drafts )
} else if name . eq_ignore_ascii_case ( " junk " ) {
Some ( SpecialUsageMailbox ::Junk )
} else if name . eq_ignore_ascii_case ( " spam " ) {
Some ( SpecialUsageMailbox ::Junk )
} else if name . eq_ignore_ascii_case ( " sent " ) {
Some ( SpecialUsageMailbox ::Sent )
} else if name . eq_ignore_ascii_case ( " trash " ) {
Some ( SpecialUsageMailbox ::Trash )
} else {
Some ( SpecialUsageMailbox ::Normal )
}
}
}
2020-02-26 08:54:10 +00:00
pub trait BackendMailbox : Debug {
fn hash ( & self ) -> MailboxHash ;
2018-08-11 15:00:21 +00:00
fn name ( & self ) -> & str ;
2020-02-26 08:54:10 +00:00
/// Path of mailbox within the mailbox hierarchy, with `/` as separator.
2019-08-23 18:32:32 +00:00
fn path ( & self ) -> & str ;
2019-04-04 11:21:52 +00:00
fn change_name ( & mut self , new_name : & str ) ;
2020-02-26 08:54:10 +00:00
fn clone ( & self ) -> Mailbox ;
fn children ( & self ) -> & [ MailboxHash ] ;
fn parent ( & self ) -> Option < MailboxHash > ;
2019-12-17 12:12:41 +00:00
fn is_subscribed ( & self ) -> bool ;
fn set_is_subscribed ( & mut self , new_val : bool ) -> Result < ( ) > ;
fn set_special_usage ( & mut self , new_val : SpecialUsageMailbox ) -> Result < ( ) > ;
2019-12-10 22:15:36 +00:00
fn special_usage ( & self ) -> SpecialUsageMailbox ;
2020-02-26 08:54:10 +00:00
fn permissions ( & self ) -> MailboxPermissions ;
2019-12-17 12:12:41 +00:00
fn count ( & self ) -> Result < ( usize , usize ) > ;
2018-08-11 15:00:21 +00:00
}
#[ derive(Debug) ]
2020-02-26 08:54:10 +00:00
struct DummyMailbox {
v : Vec < MailboxHash > ,
2018-08-11 15:00:21 +00:00
}
2020-02-26 08:54:10 +00:00
impl BackendMailbox for DummyMailbox {
fn hash ( & self ) -> MailboxHash {
2018-08-11 15:00:21 +00:00
0
}
2018-09-17 04:53:16 +00:00
2018-08-11 15:00:21 +00:00
fn name ( & self ) -> & str {
" "
}
2018-09-17 04:53:16 +00:00
2019-08-23 18:32:32 +00:00
fn path ( & self ) -> & str {
" "
}
2018-08-19 11:54:32 +00:00
fn change_name ( & mut self , _s : & str ) { }
2018-09-17 04:53:16 +00:00
2020-02-26 08:54:10 +00:00
fn clone ( & self ) -> Mailbox {
mailbox_default ( )
2018-08-11 15:00:21 +00:00
}
2018-09-17 04:53:16 +00:00
2019-12-10 22:15:36 +00:00
fn special_usage ( & self ) -> SpecialUsageMailbox {
SpecialUsageMailbox ::Normal
}
2020-02-26 08:54:10 +00:00
fn children ( & self ) -> & [ MailboxHash ] {
2018-08-11 15:00:21 +00:00
& self . v
}
2019-04-26 08:04:30 +00:00
2020-02-26 08:54:10 +00:00
fn parent ( & self ) -> Option < MailboxHash > {
2019-04-26 08:04:30 +00:00
None
}
2019-11-10 22:47:23 +00:00
2020-02-26 08:54:10 +00:00
fn permissions ( & self ) -> MailboxPermissions {
MailboxPermissions ::default ( )
2019-11-10 22:47:23 +00:00
}
2019-12-17 12:12:41 +00:00
fn is_subscribed ( & self ) -> bool {
true
}
fn set_is_subscribed ( & mut self , _new_val : bool ) -> Result < ( ) > {
Ok ( ( ) )
}
fn set_special_usage ( & mut self , _new_val : SpecialUsageMailbox ) -> Result < ( ) > {
Ok ( ( ) )
}
fn count ( & self ) -> Result < ( usize , usize ) > {
Ok ( ( 0 , 0 ) )
}
2018-08-11 15:00:21 +00:00
}
2018-09-17 04:53:16 +00:00
2020-02-26 08:54:10 +00:00
pub fn mailbox_default ( ) -> Mailbox {
Box ::new ( DummyMailbox {
2018-08-11 15:00:21 +00:00
v : Vec ::with_capacity ( 0 ) ,
} )
}
2020-05-10 19:05:04 +00:00
pub type AccountHash = u64 ;
2020-02-26 08:54:10 +00:00
pub type MailboxHash = u64 ;
pub type Mailbox = Box < dyn BackendMailbox + Send + Sync > ;
2018-09-23 16:55:29 +00:00
2020-02-26 08:54:10 +00:00
impl Clone for Mailbox {
2018-09-23 16:55:29 +00:00
fn clone ( & self ) -> Self {
2020-02-26 08:54:10 +00:00
BackendMailbox ::clone ( self . deref ( ) )
2018-09-23 16:55:29 +00:00
}
}
2020-02-26 08:54:10 +00:00
impl Default for Mailbox {
2018-09-23 16:55:29 +00:00
fn default ( ) -> Self {
2020-02-26 08:54:10 +00:00
mailbox_default ( )
2018-09-23 16:55:29 +00:00
}
}
2019-11-10 22:47:23 +00:00
#[ derive(Debug, PartialEq, Eq, Hash, Clone, Copy) ]
2020-02-26 08:54:10 +00:00
pub struct MailboxPermissions {
2019-11-10 22:47:23 +00:00
pub create_messages : bool ,
pub remove_messages : bool ,
pub set_flags : bool ,
pub create_child : bool ,
pub rename_messages : bool ,
pub delete_messages : bool ,
pub delete_mailbox : bool ,
pub change_permissions : bool ,
}
2020-02-26 08:54:10 +00:00
impl Default for MailboxPermissions {
2019-11-10 22:47:23 +00:00
fn default ( ) -> Self {
2020-02-26 08:54:10 +00:00
MailboxPermissions {
2019-11-10 22:47:23 +00:00
create_messages : false ,
remove_messages : false ,
set_flags : false ,
create_child : false ,
rename_messages : false ,
delete_messages : false ,
2020-02-26 08:54:10 +00:00
delete_mailbox : true ,
2019-11-10 22:47:23 +00:00
change_permissions : false ,
}
}
}
2020-02-05 23:49:18 +00:00
2020-02-26 08:54:10 +00:00
impl std ::fmt ::Display for MailboxPermissions {
2020-02-05 23:49:18 +00:00
fn fmt ( & self , fmt : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
write! ( fmt , " {:#?} " , self )
}
}