Move all backends to Backends structure

master
Manos Pitsidianakis 2017-09-30 20:02:22 +03:00
parent 577889f7da
commit c5dbf4e9ae
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
7 changed files with 74 additions and 39 deletions

View File

@ -36,6 +36,13 @@ fn main() {
ncurses::setlocale(locale_conf, "en_US.UTF-8"); ncurses::setlocale(locale_conf, "en_US.UTF-8");
let set = Settings::new(); let set = Settings::new();
let ui = ui::TUI::initialize(); 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<ThreadEvent>, Receiver<ThreadEvent>) = let (sender, receiver): (SyncSender<ThreadEvent>, Receiver<ThreadEvent>) =
sync_channel(::std::mem::size_of::<ThreadEvent>()); sync_channel(::std::mem::size_of::<ThreadEvent>());
@ -55,7 +62,7 @@ fn main() {
let mut j = 0; let mut j = 0;
let folder_length = set.accounts["norn"].folders.len(); 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(); let sender = sender.clone();
account.watch(RefreshEventConsumer::new(Box::new(move |r| { account.watch(RefreshEventConsumer::new(Box::new(move |r| {

View File

@ -26,20 +26,6 @@ use std::io;
use std::fs; use std::fs;
use std::path::{Path, PathBuf}; 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)] #[derive(Debug, Deserialize)]
struct FileAccount { struct FileAccount {
folders: String, folders: String,
@ -56,10 +42,17 @@ struct FileSettings {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct AccountSettings { pub struct AccountSettings {
pub folders: Vec<String>, pub folders: Vec<String>,
format: MailFormat, format: String,
pub sent_folder: String, pub sent_folder: String,
threaded: bool, threaded: bool,
} }
impl AccountSettings {
pub fn get_format(&self) -> &str {
&self.format
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct Settings { pub struct Settings {
pub accounts: HashMap<String, AccountSettings>, pub accounts: HashMap<String, AccountSettings>,
@ -126,7 +119,7 @@ impl Settings {
id.clone(), id.clone(),
AccountSettings { AccountSettings {
folders: folders, folders: folders,
format: MailFormat::from_str(&x.format), format: x.format.to_lowercase(),
sent_folder: x.sent_folder.clone(), sent_folder: x.sent_folder.clone(),
threaded: x.threaded, threaded: x.threaded,
}, },

View File

@ -39,4 +39,5 @@ extern crate bitflags;
pub use mailbox::*; pub use mailbox::*;
pub use conf::*; pub use conf::*;
pub use mailbox::backends::RefreshEventConsumer; pub use mailbox::backends::{RefreshEventConsumer, Backends};
pub use mailbox::backends::maildir::MaildirType;

View File

@ -20,7 +20,7 @@
*/ */
use mailbox::*; use mailbox::*;
use mailbox::backends::RefreshEventConsumer; use mailbox::backends::{RefreshEventConsumer, Backends};
use conf::AccountSettings; use conf::AccountSettings;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
#[derive(Debug)] #[derive(Debug)]
@ -35,9 +35,8 @@ pub struct Account {
} }
use mailbox::backends::maildir::MaildirType;
impl Account { impl Account {
pub fn new(name: String, settings: AccountSettings) -> Self { pub fn new(name: String, settings: AccountSettings, backends: Backends) -> Self {
eprintln!("new acc"); eprintln!("new acc");
let sent_folder = settings let sent_folder = settings
.folders .folders
@ -47,7 +46,7 @@ impl Account {
for _ in 0..settings.folders.len() { for _ in 0..settings.folders.len() {
folders.push(None); folders.push(None);
} }
let backend = Box::new(MaildirType::new("")); let backend = backends.get(settings.get_format()).unwrap();
Account { Account {
name: name, name: name,
folders: folders, folders: folders,
@ -79,7 +78,7 @@ impl IndexMut<usize> for Account {
let id = self.sent_folder.unwrap(); let id = self.sent_folder.unwrap();
if id == index { if id == index {
eprintln!("building sent_folder.."); 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!"); eprintln!("Done!");
} else { } else {
eprintln!( eprintln!(
@ -99,10 +98,10 @@ impl IndexMut<usize> for Account {
let sent_path = self.settings.folders[id].clone(); let sent_path = self.settings.folders[id].clone();
if sent[0].is_none() { if sent[0].is_none() {
eprintln!("\tbuilding sent_folder.."); 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!"); eprintln!("\tDone!");
} }
cur[0] = Some(Mailbox::new(&path, &sent[0])); cur[0] = Some(Mailbox::new(&path, &sent[0],self.backend.get(&path)));
eprintln!("Done!"); eprintln!("Done!");
} }
} else { } else {
@ -110,7 +109,7 @@ impl IndexMut<usize> for Account {
"Now building folder {:?} without sent_folder", "Now building folder {:?} without sent_folder",
self.settings.folders[index] 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!"); eprintln!("Done!");
}; };
} }

View File

@ -120,8 +120,8 @@ pub struct MaildirType {
impl MailBackend for MaildirType { impl MailBackend for MaildirType {
fn get(&self) -> Result<Vec<Envelope>> { fn get(&self, path: &str) -> Result<Vec<Envelope>> {
self.get_multicore(4) self.get_multicore(4, path)
/* /*
MaildirType::is_valid(&self.path)?; MaildirType::is_valid(&self.path)?;
@ -193,9 +193,9 @@ impl MaildirType {
} }
Ok(()) Ok(())
} }
pub fn get_multicore(&self, cores: usize) -> Result<Vec<Envelope>> { pub fn get_multicore(&self, cores: usize, path: &str) -> Result<Vec<Envelope>> {
MaildirType::is_valid(&self.path)?; MaildirType::is_valid(path)?;
let mut path = PathBuf::from(&self.path); let mut path = PathBuf::from(path);
path.push("cur"); path.push("cur");
let iter = path.read_dir()?; let iter = path.read_dir()?;
let count = path.read_dir()?.count(); let count = path.read_dir()?.count();

View File

@ -21,14 +21,51 @@
pub mod maildir; pub mod maildir;
use mailbox::email::{Envelope, Flag}; use mailbox::email::{Envelope, Flag};
use error::Result; use error::{MeliError, Result};
use std::fmt; use std::fmt;
extern crate fnv;
use self::fnv::FnvHashMap;
use std;
pub struct Backends {
map: FnvHashMap<std::string::String, Box<Fn() -> Box<MailBackend>>>,
}
impl Backends {
pub fn new() -> Self {
Backends {
map: FnvHashMap::with_capacity_and_hasher(1, Default::default())
}
}
pub fn get(&self, key: &str) -> Result<Box<MailBackend>> {
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<Fn() -> Box<MailBackend>>) -> 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 struct RefreshEvent {
pub folder: String, 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<Fn(RefreshEvent) -> ()>); pub struct RefreshEventConsumer(Box<Fn(RefreshEvent) -> ()>);
unsafe impl Send for RefreshEventConsumer {} unsafe impl Send for RefreshEventConsumer {}
unsafe impl Sync for RefreshEventConsumer {} unsafe impl Sync for RefreshEventConsumer {}
@ -41,9 +78,10 @@ impl RefreshEventConsumer {
} }
} }
pub trait MailBackend: ::std::fmt::Debug { pub trait MailBackend: ::std::fmt::Debug {
fn get(&self) -> Result<Vec<Envelope>>; fn get(&self, path: &str) -> Result<Vec<Envelope>>;
fn watch(&self, sender:RefreshEventConsumer, folders: &[String]) -> (); fn watch(&self, sender:RefreshEventConsumer, folders: &[String]) -> ();
//fn new(folders: &Vec<String>) -> Box<Self>; //fn new(folders: &Vec<String>) -> Box<Self>;
//login function
} }
/// A `BackendOp` manages common operations for the various mail backends. They only live for the /// A `BackendOp` manages common operations for the various mail backends. They only live for the

View File

@ -24,7 +24,6 @@ pub use self::email::*;
/* Mail backends. Currently only maildir is supported */ /* Mail backends. Currently only maildir is supported */
pub mod backends; pub mod backends;
use mailbox::backends::MailBackend; use mailbox::backends::MailBackend;
use mailbox::backends::maildir;
use error::Result; use error::Result;
pub mod accounts; pub mod accounts;
pub use mailbox::accounts::Account; pub use mailbox::accounts::Account;
@ -45,12 +44,10 @@ pub struct Mailbox {
impl Mailbox { impl Mailbox {
pub fn new(path: &str, sent_folder: &Option<Result<Mailbox>>) -> Result<Mailbox> { pub fn new(path: &str, sent_folder: &Option<Result<Mailbox>>, collection: Result<Vec<Envelope>>) -> Result<Mailbox> {
let mut collection: Vec<Envelope> = maildir::MaildirType::new(path).get()?; let mut collection: Vec<Envelope> = collection?;
collection.sort_by(|a, b| a.get_date().cmp(&b.get_date())); collection.sort_by(|a, b| a.get_date().cmp(&b.get_date()));
let (threads, threaded_collection) = build_threads(&mut collection, sent_folder); let (threads, threaded_collection) = build_threads(&mut collection, sent_folder);
Ok(Mailbox { Ok(Mailbox {
path: path.to_string(), path: path.to_string(),
collection: collection, collection: collection,