diff options
author | Jannis M. Hoffmann <jannis@fehcom.de> | 2024-11-21 21:14:40 +0100 |
---|---|---|
committer | Jannis M. Hoffmann <jannis@fehcom.de> | 2024-11-21 21:14:40 +0100 |
commit | 48c2945172b88c35c187d298a35bf26716af4e91 (patch) | |
tree | 2af21ddb4dcacd191e07fef156609b7c1488ebaf /src/cmd/list.rs | |
parent | 6ed535387df0dffa72a10e601b8ea37c99345d84 (diff) |
Switch to varlink as IPC protocol
This is a lot! Whole new design on top of a statefult varlink interface.
You can now handle multiple request response cycles over a single
connection.
The error responses are lot more refined than just status codes with
optional messages and finally part of the protocol.
TODO: A lot of error handling needs to be improved.
Diffstat (limited to 'src/cmd/list.rs')
-rw-r--r-- | src/cmd/list.rs | 158 |
1 files changed, 86 insertions, 72 deletions
diff --git a/src/cmd/list.rs b/src/cmd/list.rs index 3c2d42a..8aeaf97 100644 --- a/src/cmd/list.rs +++ b/src/cmd/list.rs @@ -1,12 +1,11 @@ use std::cmp::Reverse; -use std::path::PathBuf; use log::warn; -use protobuf::Message as _; -use crate::cmd::open_submaildir; -use crate::error::Result; -use crate::pb3::jwebmail::{ListMailHeader, ListReq, ListResp, MailHeader}; +use crate::cmd::{open_submaildir, MailStorage}; +use crate::de_jmhoffmann_jwebmail_mailstorage::{ + Call_List, ListMailHeader, MailHeader, Sort, Sort_direction, Sort_parameter, +}; use crate::rfc822::me_to_lmh; fn from_or_sender(mh: &MailHeader) -> &str { @@ -37,95 +36,110 @@ fn mid_to_rec_time(mid: &str) -> f64 { fn sort_by_and_take( mut entries: Vec<maildir::MailEntry>, - sortby: &str, + sortby: Sort, s: usize, e: usize, ) -> Vec<ListMailHeader> { - match sortby { - "date" => { - entries.sort_by(|a, b| { - mid_to_rec_time(a.id()) - .partial_cmp(&mid_to_rec_time(b.id())) - .unwrap() - }); - entries - .drain(s..e) - .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) - .collect() - } - "!date" => { - entries.sort_by(|b, a| { - mid_to_rec_time(a.id()) - .partial_cmp(&mid_to_rec_time(b.id())) - .unwrap() - }); - entries - .drain(s..e) - .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) - .collect() - } - "size" => { - entries.sort_by_cached_key(|a| a.path().metadata().map_or(0, |m| m.len())); - entries - .drain(s..e) - .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) - .collect() - } - "!size" => { - entries.sort_by_cached_key(|a| Reverse(a.path().metadata().map_or(0, |m| m.len()))); - entries - .drain(s..e) - .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) - .collect() - } - "subject" | "!subject" => { + match sortby.parameter { + Sort_parameter::date => match sortby.direction { + Sort_direction::asc => { + entries.sort_by(|a, b| { + mid_to_rec_time(a.id()) + .partial_cmp(&mid_to_rec_time(b.id())) + .unwrap() + }); + entries + .drain(s..e) + .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) + .collect() + } + Sort_direction::desc => { + entries.sort_by(|b, a| { + mid_to_rec_time(a.id()) + .partial_cmp(&mid_to_rec_time(b.id())) + .unwrap() + }); + entries + .drain(s..e) + .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) + .collect() + } + }, + Sort_parameter::size => match sortby.direction { + Sort_direction::asc => { + entries.sort_by_cached_key(|a| a.path().metadata().map_or(0, |m| m.len())); + entries + .drain(s..e) + .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) + .collect() + } + Sort_direction::desc => { + entries.sort_by_cached_key(|a| Reverse(a.path().metadata().map_or(0, |m| m.len()))); + entries + .drain(s..e) + .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) + .collect() + } + }, + Sort_parameter::subject => { let mut x: Vec<ListMailHeader> = entries .drain(..) .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) .collect(); - if sortby.as_bytes().first().copied() == Some(b'!') { - x.sort_by(|a, b| a.header.subject.cmp(&b.header.subject)) - } else { - x.sort_by(|b, a| a.header.subject.cmp(&b.header.subject)) + match sortby.direction { + Sort_direction::asc => x.sort_by(|a, b| a.header.subject.cmp(&b.header.subject)), + Sort_direction::desc => x.sort_by(|b, a| a.header.subject.cmp(&b.header.subject)), } x.drain(s..e).collect() } - "sender" | "!sender" => { + Sort_parameter::sender => { let mut x: Vec<ListMailHeader> = entries .drain(..) .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) .collect(); - if sortby.as_bytes().first().copied() != Some(b'!') { - x.sort_by(|a, b| from_or_sender(&a.header).cmp(from_or_sender(&b.header))) - } else { - x.sort_by(|b, a| from_or_sender(&a.header).cmp(from_or_sender(&b.header))) + match sortby.direction { + Sort_direction::asc => { + x.sort_by(|a, b| from_or_sender(&a.header).cmp(from_or_sender(&b.header))) + } + Sort_direction::desc => { + x.sort_by(|b, a| from_or_sender(&a.header).cmp(from_or_sender(&b.header))) + } } x.drain(s..e).collect() } - _ => todo!(), } } -pub fn list(path: PathBuf, req: &[u8]) -> Result<Vec<u8>> { - let r = ListReq::parse_from_bytes(req)?; - let md = open_submaildir(path, &r.folder); +pub fn list( + ms: &MailStorage, + call: &mut dyn Call_List, + folder: String, + start: i64, + end: i64, + sort: Sort, +) -> varlink::Result<()> { + if let Some(path) = ms.maildir_path.read().unwrap().clone() { + let md = open_submaildir(path, &folder); - for r in md.list_new() { - match r { - Err(e) => warn!("{}", e), - Ok(me) => { - if let Err(e) = md.move_new_to_cur(me.id()) { - warn!("{}", e); + for r in md.list_new() { + match r { + Err(e) => warn!("{}", e), + Ok(me) => { + if let Err(e) = md.move_new_to_cur(me.id()) { + warn!("{}", e); + } } - } - }; - } + }; + } + + let a: Vec<_> = md.list_cur().filter_map(std::result::Result::ok).collect(); + let start = std::cmp::min(a.len(), start as usize); + let end = std::cmp::min(a.len(), end as usize); - let a: Vec<_> = md.list_cur().filter_map(std::result::Result::ok).collect(); - let start = std::cmp::min(a.len(), r.start as usize); - let end = std::cmp::min(a.len(), r.end as usize); + let mail_heads = sort_by_and_take(a, sort, start, end); - let mut resp = ListResp::new(); - resp.mail_heads = sort_by_and_take(a, &r.sort, start, end); - resp.write_to_bytes().map_err(|e| e.into()) + call.reply(mail_heads) + } else { + call.reply_not_initialized() + } } |