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");
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<ThreadEvent>, Receiver<ThreadEvent>) =
sync_channel(::std::mem::size_of::<ThreadEvent>());
@ -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| {

View File

@ -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<String>,
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<String, AccountSettings>,
@ -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,
},

View File

@ -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;

View File

@ -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<usize> 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<usize> 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<usize> 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!");
};
}

View File

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

View File

@ -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<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 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) -> ()>);
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<Vec<Envelope>>;
fn get(&self, path: &str) -> Result<Vec<Envelope>>;
fn watch(&self, sender:RefreshEventConsumer, folders: &[String]) -> ();
//fn new(folders: &Vec<String>) -> Box<Self>;
//login function
}
/// 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 */
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<Mailbox>>) -> Result<Mailbox> {
let mut collection: Vec<Envelope> = maildir::MaildirType::new(path).get()?;
pub fn new(path: &str, sent_folder: &Option<Result<Mailbox>>, collection: Result<Vec<Envelope>>) -> Result<Mailbox> {
let mut collection: Vec<Envelope> = 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,