diff options
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | src/mailcache.rs | 88 | ||||
-rw-r--r-- | src/mailstore.rs | 5 | ||||
-rw-r--r-- | src/main.rs | 1 |
4 files changed, 97 insertions, 0 deletions
@@ -18,4 +18,7 @@ cursive = "0.15" git = "https://github.com/matthiasbeyer/cursive_tree_view" branch = "update-deps" +[dependencies.async-std] +version = "1.6" +features = ["unstable"] diff --git a/src/mailcache.rs b/src/mailcache.rs new file mode 100644 index 0000000..1bb8f6f --- /dev/null +++ b/src/mailcache.rs @@ -0,0 +1,88 @@ +use std::path::PathBuf; +use std::path::Path; +use std::sync::Arc; +use std::sync::RwLock; +use anyhow::Result; +use anyhow::Error; +use async_std::sync::{Sender, Receiver}; +use async_std::sync::TryRecvError; +use async_std::sync::channel; +use async_std::task; + +use crate::mailstore::MailStore; + +struct Cache { + cache: Vec<MailStore>, + receiver: Receiver<Result<MailStore>>, +} + +impl Cache { + fn find(&self, path: &Path) -> Option<&MailStore> { + self.cache.iter().find(|e| e.path() == path) + } + + fn update(&mut self) -> Result<()> { + loop { + match self.receiver.try_recv() { + Ok(queued) => { + self.cache.push(queued?); + } + Err(TryRecvError::Empty) => break, + Err(other) => { + return Err(other).map_err(Error::from) + }, + } + } + + Ok(()) + } +} + +#[derive(Clone)] +pub struct MailCache { + cache: Arc<RwLock<Cache>>, + sender: Sender<Result<MailStore>>, +} + +impl MailCache { + + pub fn new(buffer_cap: usize) -> Self { + let (s, r) = channel(buffer_cap); + MailCache { + cache: Arc::new(RwLock::new(Cache { + cache: Vec::new(), + receiver: r, + })), + sender: s + } + } + + pub fn load_background(&self, path: PathBuf) { + let sender = self.sender.clone(); + task::spawn(async move { + let mut ms = MailStore::from_path(path); + let r = ms.load().map(|_| ms); + + sender.send(r).await + }); + } + + pub fn exec_on<F, T>(&self, path: &Path, f: F) -> Result<T> + where T: Sized, + F: FnOnce(Option<&MailStore>) -> Result<T>, + { + self.cache + .read() + .map_err(|_| anyhow!("RWLock possibly poisened")) + .and_then(|cache| f(cache.find(path))) + } + + pub fn update_cache(&mut self) -> Result<()> { + self.cache + .write() + .map_err(|_| anyhow!("Possibly poisened RWLock")) + .and_then(|mut cache| cache.update()) + } + +} + diff --git a/src/mailstore.rs b/src/mailstore.rs index 3f1d299..cbb59fd 100644 --- a/src/mailstore.rs +++ b/src/mailstore.rs @@ -1,4 +1,5 @@ use std::path::PathBuf; +use std::path::Path; use anyhow::Error; use anyhow::Result; use maildir::Maildir; @@ -33,6 +34,10 @@ impl MailStore { pub fn cur_mail(&self) -> &Vec<Mail> { &self.cur } + + pub fn path(&self) -> &Path { + self.dir.path() + } } pub struct Mail { diff --git a/src/main.rs b/src/main.rs index 04f041d..232f834 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use mailparse::MailHeaderMap; use mailparse::ParsedMail; mod mailstore; +mod mailcache; mod sidebar; mod main_view; |