summaryrefslogtreecommitdiff
path: root/src/cmd/list.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/list.rs')
-rw-r--r--src/cmd/list.rs116
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())
}