From c5dbf4e9ae4e6239759891b16a51aeea34994114 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sat, 30 Sep 2017 20:02:22 +0300 Subject: [PATCH] Move all backends to Backends structure --- src/bin.rs | 9 ++++++- src/conf/mod.rs | 25 +++++++------------ src/lib.rs | 3 ++- src/mailbox/accounts.rs | 15 ++++++----- src/mailbox/backends/maildir.rs | 10 ++++---- src/mailbox/backends/mod.rs | 44 ++++++++++++++++++++++++++++++--- src/mailbox/mod.rs | 7 ++---- 7 files changed, 74 insertions(+), 39 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index 4565e317..3fd83050 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -36,6 +36,13 @@ fn main() { ncurses::setlocale(locale_conf, "en_US.UTF-8"); let set = Settings::new(); let ui = ui::TUI::initialize(); + let mut backends = Backends::new(); + backends + .register( + "maildir".to_string(), + Box::new(|| Box::new(MaildirType::new(""))), + ) + .unwrap(); let (sender, receiver): (SyncSender, Receiver) = sync_channel(::std::mem::size_of::()); @@ -55,7 +62,7 @@ fn main() { let mut j = 0; let folder_length = set.accounts["norn"].folders.len(); - let mut account = Account::new("norn".to_string(), set.accounts["norn"].clone()); + let mut account = Account::new("norn".to_string(), set.accounts["norn"].clone(), backends); { let sender = sender.clone(); account.watch(RefreshEventConsumer::new(Box::new(move |r| { diff --git a/src/conf/mod.rs b/src/conf/mod.rs index f6efe97a..aea74940 100644 --- a/src/conf/mod.rs +++ b/src/conf/mod.rs @@ -26,20 +26,6 @@ use std::io; use std::fs; use std::path::{Path, PathBuf}; -#[derive(Debug, Clone)] -pub enum MailFormat { - Maildir, -} - -impl MailFormat { - pub fn from_str(x: &str) -> MailFormat { - match x.to_lowercase().as_ref() { - "maildir" => MailFormat::Maildir, - _ => panic!("Unrecognizable mail format"), - } - } -} - #[derive(Debug, Deserialize)] struct FileAccount { folders: String, @@ -56,10 +42,17 @@ struct FileSettings { #[derive(Debug, Clone)] pub struct AccountSettings { pub folders: Vec, - format: MailFormat, + format: String, pub sent_folder: String, threaded: bool, } + +impl AccountSettings { + pub fn get_format(&self) -> &str { + &self.format + } +} + #[derive(Debug)] pub struct Settings { pub accounts: HashMap, @@ -126,7 +119,7 @@ impl Settings { id.clone(), AccountSettings { folders: folders, - format: MailFormat::from_str(&x.format), + format: x.format.to_lowercase(), sent_folder: x.sent_folder.clone(), threaded: x.threaded, }, diff --git a/src/lib.rs b/src/lib.rs index d80ec37b..83461738 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,4 +39,5 @@ extern crate bitflags; pub use mailbox::*; pub use conf::*; -pub use mailbox::backends::RefreshEventConsumer; +pub use mailbox::backends::{RefreshEventConsumer, Backends}; +pub use mailbox::backends::maildir::MaildirType; diff --git a/src/mailbox/accounts.rs b/src/mailbox/accounts.rs index 1f2972fc..54f382c2 100644 --- a/src/mailbox/accounts.rs +++ b/src/mailbox/accounts.rs @@ -20,7 +20,7 @@ */ use mailbox::*; -use mailbox::backends::RefreshEventConsumer; +use mailbox::backends::{RefreshEventConsumer, Backends}; use conf::AccountSettings; use std::ops::{Index, IndexMut}; #[derive(Debug)] @@ -35,9 +35,8 @@ pub struct Account { } -use mailbox::backends::maildir::MaildirType; impl Account { - pub fn new(name: String, settings: AccountSettings) -> Self { + pub fn new(name: String, settings: AccountSettings, backends: Backends) -> Self { eprintln!("new acc"); let sent_folder = settings .folders @@ -47,7 +46,7 @@ impl Account { for _ in 0..settings.folders.len() { folders.push(None); } - let backend = Box::new(MaildirType::new("")); + let backend = backends.get(settings.get_format()).unwrap(); Account { name: name, folders: folders, @@ -79,7 +78,7 @@ impl IndexMut for Account { let id = self.sent_folder.unwrap(); if id == index { eprintln!("building sent_folder.."); - self.folders[index] = Some(Mailbox::new(&path, &None)); + self.folders[index] = Some(Mailbox::new(&path, &None, self.backend.get(&path))); eprintln!("Done!"); } else { eprintln!( @@ -99,10 +98,10 @@ impl IndexMut for Account { let sent_path = self.settings.folders[id].clone(); if sent[0].is_none() { eprintln!("\tbuilding sent_folder.."); - sent[0] = Some(Mailbox::new(&sent_path, &None)); + sent[0] = Some(Mailbox::new(&sent_path, &None, self.backend.get(&path))); eprintln!("\tDone!"); } - cur[0] = Some(Mailbox::new(&path, &sent[0])); + cur[0] = Some(Mailbox::new(&path, &sent[0],self.backend.get(&path))); eprintln!("Done!"); } } else { @@ -110,7 +109,7 @@ impl IndexMut for Account { "Now building folder {:?} without sent_folder", self.settings.folders[index] ); - self.folders[index] = Some(Mailbox::new(&path, &None)); + self.folders[index] = Some(Mailbox::new(&path, &None,self.backend.get(&path))); eprintln!("Done!"); }; } diff --git a/src/mailbox/backends/maildir.rs b/src/mailbox/backends/maildir.rs index e14ee584..f655bb47 100644 --- a/src/mailbox/backends/maildir.rs +++ b/src/mailbox/backends/maildir.rs @@ -120,8 +120,8 @@ pub struct MaildirType { impl MailBackend for MaildirType { - fn get(&self) -> Result> { - self.get_multicore(4) + fn get(&self, path: &str) -> Result> { + self.get_multicore(4, path) /* MaildirType::is_valid(&self.path)?; @@ -193,9 +193,9 @@ impl MaildirType { } Ok(()) } - pub fn get_multicore(&self, cores: usize) -> Result> { - MaildirType::is_valid(&self.path)?; - let mut path = PathBuf::from(&self.path); + pub fn get_multicore(&self, cores: usize, path: &str) -> Result> { + MaildirType::is_valid(path)?; + let mut path = PathBuf::from(path); path.push("cur"); let iter = path.read_dir()?; let count = path.read_dir()?.count(); diff --git a/src/mailbox/backends/mod.rs b/src/mailbox/backends/mod.rs index d83a8676..c87494a3 100644 --- a/src/mailbox/backends/mod.rs +++ b/src/mailbox/backends/mod.rs @@ -21,14 +21,51 @@ pub mod maildir; use mailbox::email::{Envelope, Flag}; -use error::Result; - +use error::{MeliError, Result}; use std::fmt; + +extern crate fnv; +use self::fnv::FnvHashMap; +use std; +pub struct Backends { + map: FnvHashMap Box>>, +} + +impl Backends { + pub fn new() -> Self { + Backends { + map: FnvHashMap::with_capacity_and_hasher(1, Default::default()) + } + } + + pub fn get(&self, key: &str) -> Result> { + if !self.map.contains_key(key) { + return Err(MeliError::new( + format!("{} is not a valid mail backend", key), + )); + } + Ok(self.map[key]()) + } + pub fn register(&mut self, key: String, backend: Box Box>) -> Result<()> { + if self.map.contains_key(&key) { + return Err(MeliError::new( + format!("{} is an already registered backend", key), + )); + } + self.map.insert(key, backend); + Ok(()) + } +} + + pub struct RefreshEvent { pub folder: String, } +/// 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. pub struct RefreshEventConsumer(Box ()>); unsafe impl Send for RefreshEventConsumer {} unsafe impl Sync for RefreshEventConsumer {} @@ -41,9 +78,10 @@ impl RefreshEventConsumer { } } pub trait MailBackend: ::std::fmt::Debug { - fn get(&self) -> Result>; + fn get(&self, path: &str) -> Result>; fn watch(&self, sender:RefreshEventConsumer, folders: &[String]) -> (); //fn new(folders: &Vec) -> Box; + //login function } /// A `BackendOp` manages common operations for the various mail backends. They only live for the diff --git a/src/mailbox/mod.rs b/src/mailbox/mod.rs index f22849e8..f91a2513 100644 --- a/src/mailbox/mod.rs +++ b/src/mailbox/mod.rs @@ -24,7 +24,6 @@ pub use self::email::*; /* Mail backends. Currently only maildir is supported */ pub mod backends; use mailbox::backends::MailBackend; -use mailbox::backends::maildir; use error::Result; pub mod accounts; pub use mailbox::accounts::Account; @@ -45,12 +44,10 @@ pub struct Mailbox { impl Mailbox { - pub fn new(path: &str, sent_folder: &Option>) -> Result { - let mut collection: Vec = maildir::MaildirType::new(path).get()?; + pub fn new(path: &str, sent_folder: &Option>, collection: Result>) -> Result { + let mut collection: Vec = collection?; collection.sort_by(|a, b| a.get_date().cmp(&b.get_date())); let (threads, threaded_collection) = build_threads(&mut collection, sent_folder); - - Ok(Mailbox { path: path.to_string(), collection: collection,