diff options
Diffstat (limited to 'src/cmd/list.rs')
-rw-r--r-- | src/cmd/list.rs | 116 |
1 files changed, 64 insertions, 52 deletions
diff --git a/src/cmd/list.rs b/src/cmd/list.rs index b77a311..65f128f 100644 --- a/src/cmd/list.rs +++ b/src/cmd/list.rs @@ -1,19 +1,21 @@ use std::cmp::Reverse; +use std::path::PathBuf; use log::warn; -use maildir::Maildir; +use protobuf::Message as _; -use crate::arguments::{SortInfo, SortKey, SortOrder}; +use crate::cmd::open_submaildir; use crate::error::Result; -use crate::rfc822::{MailHeader, TopMailHeader}; +use crate::pb3::jwebmail::{ListMailHeader, ListReq, ListResp, MailHeader}; +use crate::rfc822::me_to_lmh; fn from_or_sender<'a>(mh: &'a MailHeader) -> &'a str { - if mh.from.len() == 0 { + if mh.written_from.len() == 0 { warn!("mail without from"); panic!() } - if mh.from.len() == 1 { - &mh.from[0].address + if mh.written_from.len() == 1 { + &mh.written_from[0].address } else { &mh.sender.as_ref().unwrap().address } @@ -32,72 +34,79 @@ fn mid_to_rec_time(mid: &str) -> f64 { fn sort_by_and_take( mut entries: Vec<maildir::MailEntry>, - sortby: &SortInfo, + sortby: &str, s: usize, e: usize, -) -> Vec<TopMailHeader> { - match sortby.key { - SortKey::Date => { - match sortby.order { - SortOrder::Ascending => entries.sort_by(|a, b| { - mid_to_rec_time(a.id()) - .partial_cmp(&mid_to_rec_time(b.id())) - .unwrap() - }), - SortOrder::Descending => entries.sort_by(|b, a| { - mid_to_rec_time(a.id()) - .partial_cmp(&mid_to_rec_time(b.id())) - .unwrap() - }), - } +) -> 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.try_into().map_err(|e| warn!("{}", e)).ok()) + .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) .collect() } - SortKey::Size => { - match sortby.order { - SortOrder::Ascending => { - entries.sort_by_cached_key(|a| a.path().metadata().map_or(0, |m| m.len())) - } - SortOrder::Descending => entries - .sort_by_cached_key(|a| Reverse(a.path().metadata().map_or(0, |m| m.len()))), - } + "!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.try_into().map_err(|e| warn!("{}", e)).ok()) + .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) .collect() } - SortKey::Subject => { - let mut x: Vec<TopMailHeader> = entries + "!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" => { + let mut x: Vec<ListMailHeader> = entries .drain(..) - .filter_map(|me| me.try_into().map_err(|e| warn!("{}", e)).ok()) + .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) .collect(); - match sortby.order { - SortOrder::Ascending => x.sort_by(|a, b| a.head.subject.cmp(&b.head.subject)), - SortOrder::Descending => x.sort_by(|b, a| a.head.subject.cmp(&b.head.subject)), + if sortby.bytes().nth(0) == 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)) } x.drain(s..e).collect() } - SortKey::Sender => { - let mut x: Vec<TopMailHeader> = entries + "sender" | "!sender" => { + let mut x: Vec<ListMailHeader> = entries .drain(..) - .filter_map(|me| me.try_into().map_err(|e| warn!("{}", e)).ok()) + .filter_map(|me| me_to_lmh(me).map_err(|e| warn!("{}", e)).ok()) .collect(); - match sortby.order { - SortOrder::Ascending => { - x.sort_by(|a, b| from_or_sender(&a.head).cmp(from_or_sender(&b.head))) - } - SortOrder::Descending => { - x.sort_by(|b, a| from_or_sender(&a.head).cmp(from_or_sender(&b.head))) - } + if sortby.bytes().nth(0) != 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))) } x.drain(s..e).collect() } + _ => todo!(), } } -pub fn list(md: &Maildir, i: usize, j: usize, sortby: &SortInfo) -> Result<Vec<TopMailHeader>> { +pub fn list(path: PathBuf, req: &[u8]) -> Result<Vec<u8>> { + let r = ListReq::parse_from_bytes(req)?; + let md = open_submaildir(path, &r.folder); + for r in md.list_new() { match r { Err(e) => warn!("{}", e), @@ -110,7 +119,10 @@ pub fn list(md: &Maildir, i: usize, j: usize, sortby: &SortInfo) -> Result<Vec<T } let a: Vec<_> = md.list_cur().filter_map(std::result::Result::ok).collect(); - let start = std::cmp::min(a.len(), i); - let end = std::cmp::min(a.len(), j); - Ok(sort_by_and_take(a, sortby, start, end)) + let start = std::cmp::min(a.len(), r.start as usize); + let end = std::cmp::min(a.len(), r.end as usize); + + 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()) } |