BackendOp: return future in as_bytes()
parent
4721073bc3
commit
b3876113aa
|
@ -436,7 +436,7 @@ pub trait MailBackend: ::std::fmt::Debug + Send + Sync {
|
||||||
/// let operation = Box::new(FooOp {});
|
/// let operation = Box::new(FooOp {});
|
||||||
/// ```
|
/// ```
|
||||||
pub trait BackendOp: ::std::fmt::Debug + ::std::marker::Send {
|
pub trait BackendOp: ::std::fmt::Debug + ::std::marker::Send {
|
||||||
fn as_bytes(&mut self) -> Result<&[u8]>;
|
fn as_bytes(&mut self) -> ResultFuture<Vec<u8>>;
|
||||||
fn fetch_flags(&self) -> ResultFuture<Flag>;
|
fn fetch_flags(&self) -> ResultFuture<Flag>;
|
||||||
fn set_flag(&mut self, flag: Flag, value: bool) -> ResultFuture<()>;
|
fn set_flag(&mut self, flag: Flag, value: bool) -> ResultFuture<()>;
|
||||||
fn set_tag(&mut self, tag: String, value: bool) -> ResultFuture<()>;
|
fn set_tag(&mut self, tag: String, value: bool) -> ResultFuture<()>;
|
||||||
|
@ -458,7 +458,7 @@ impl ReadOnlyOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackendOp for ReadOnlyOp {
|
impl BackendOp for ReadOnlyOp {
|
||||||
fn as_bytes(&mut self) -> Result<&[u8]> {
|
fn as_bytes(&mut self) -> ResultFuture<Vec<u8>> {
|
||||||
self.op.as_bytes()
|
self.op.as_bytes()
|
||||||
}
|
}
|
||||||
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
||||||
|
|
|
@ -31,12 +31,7 @@ use std::sync::{Arc, Mutex};
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ImapOp {
|
pub struct ImapOp {
|
||||||
uid: usize,
|
uid: usize,
|
||||||
bytes: Option<String>,
|
|
||||||
headers: Option<String>,
|
|
||||||
body: Option<String>,
|
|
||||||
mailbox_path: String,
|
|
||||||
mailbox_hash: MailboxHash,
|
mailbox_hash: MailboxHash,
|
||||||
flags: Arc<FutureMutex<Option<Flag>>>,
|
|
||||||
connection: Arc<Mutex<ImapConnection>>,
|
connection: Arc<Mutex<ImapConnection>>,
|
||||||
uid_store: Arc<UIDStore>,
|
uid_store: Arc<UIDStore>,
|
||||||
}
|
}
|
||||||
|
@ -52,56 +47,43 @@ impl ImapOp {
|
||||||
ImapOp {
|
ImapOp {
|
||||||
uid,
|
uid,
|
||||||
connection,
|
connection,
|
||||||
bytes: None,
|
|
||||||
headers: None,
|
|
||||||
body: None,
|
|
||||||
mailbox_path,
|
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
flags: Arc::new(FutureMutex::new(None)),
|
|
||||||
uid_store,
|
uid_store,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackendOp for ImapOp {
|
impl BackendOp for ImapOp {
|
||||||
fn as_bytes(&mut self) -> Result<&[u8]> {
|
fn as_bytes(&mut self) -> ResultFuture<Vec<u8>> {
|
||||||
if self.bytes.is_none() {
|
let mut bytes_cache = self.uid_store.byte_cache.lock()?;
|
||||||
|
let cache = bytes_cache.entry(self.uid).or_default();
|
||||||
|
if cache.bytes.is_none() {
|
||||||
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
|
{
|
||||||
|
let mut conn = try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
||||||
|
conn.examine_mailbox(self.mailbox_hash, &mut response)?;
|
||||||
|
conn.send_command(format!("UID FETCH {} (FLAGS RFC822)", self.uid).as_bytes())?;
|
||||||
|
conn.read_response(&mut response, RequiredResponses::FETCH_REQUIRED)?;
|
||||||
|
}
|
||||||
|
debug!(
|
||||||
|
"fetch response is {} bytes and {} lines",
|
||||||
|
response.len(),
|
||||||
|
response.lines().collect::<Vec<&str>>().len()
|
||||||
|
);
|
||||||
|
let UidFetchResponse {
|
||||||
|
uid, flags, body, ..
|
||||||
|
} = protocol_parser::uid_fetch_response(&response)?.1;
|
||||||
|
assert_eq!(uid, self.uid);
|
||||||
|
assert!(body.is_some());
|
||||||
let mut bytes_cache = self.uid_store.byte_cache.lock()?;
|
let mut bytes_cache = self.uid_store.byte_cache.lock()?;
|
||||||
let cache = bytes_cache.entry(self.uid).or_default();
|
let cache = bytes_cache.entry(self.uid).or_default();
|
||||||
if cache.bytes.is_some() {
|
if let Some((flags, _)) = flags {
|
||||||
self.bytes = cache.bytes.clone();
|
cache.flags = Some(flags);
|
||||||
} else {
|
|
||||||
drop(cache);
|
|
||||||
drop(bytes_cache);
|
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
|
||||||
{
|
|
||||||
let mut conn =
|
|
||||||
try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
|
||||||
conn.examine_mailbox(self.mailbox_hash, &mut response, false)?;
|
|
||||||
conn.send_command(format!("UID FETCH {} (FLAGS RFC822)", self.uid).as_bytes())?;
|
|
||||||
conn.read_response(&mut response, RequiredResponses::FETCH_REQUIRED)?;
|
|
||||||
}
|
|
||||||
debug!(
|
|
||||||
"fetch response is {} bytes and {} lines",
|
|
||||||
response.len(),
|
|
||||||
response.lines().collect::<Vec<&str>>().len()
|
|
||||||
);
|
|
||||||
let UidFetchResponse {
|
|
||||||
uid, flags, body, ..
|
|
||||||
} = protocol_parser::uid_fetch_response(&response)?.1;
|
|
||||||
assert_eq!(uid, self.uid);
|
|
||||||
assert!(body.is_some());
|
|
||||||
let mut bytes_cache = self.uid_store.byte_cache.lock()?;
|
|
||||||
let cache = bytes_cache.entry(self.uid).or_default();
|
|
||||||
if let Some((flags, _)) = flags {
|
|
||||||
cache.flags = Some(flags);
|
|
||||||
}
|
|
||||||
cache.bytes =
|
|
||||||
Some(unsafe { std::str::from_utf8_unchecked(body.unwrap()).to_string() });
|
|
||||||
self.bytes = cache.bytes.clone();
|
|
||||||
}
|
}
|
||||||
|
cache.bytes = Some(unsafe { std::str::from_utf8_unchecked(body.unwrap()).to_string() });
|
||||||
}
|
}
|
||||||
Ok(self.bytes.as_ref().unwrap().as_bytes())
|
let ret = cache.bytes.clone().unwrap().into_bytes();
|
||||||
|
Ok(Box::pin(async move { Ok(ret) }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
||||||
|
@ -109,13 +91,9 @@ impl BackendOp for ImapOp {
|
||||||
let mailbox_hash = self.mailbox_hash;
|
let mailbox_hash = self.mailbox_hash;
|
||||||
let uid = self.uid;
|
let uid = self.uid;
|
||||||
let uid_store = self.uid_store.clone();
|
let uid_store = self.uid_store.clone();
|
||||||
let flags = self.flags.clone();
|
|
||||||
|
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
Ok(Box::pin(async move {
|
Ok(Box::pin(async move {
|
||||||
if let Some(val) = *flags.lock().await {
|
|
||||||
return Ok(val);
|
|
||||||
}
|
|
||||||
let exists_in_cache = {
|
let exists_in_cache = {
|
||||||
let mut bytes_cache = uid_store.byte_cache.lock()?;
|
let mut bytes_cache = uid_store.byte_cache.lock()?;
|
||||||
let cache = bytes_cache.entry(uid).or_default();
|
let cache = bytes_cache.entry(uid).or_default();
|
||||||
|
@ -158,8 +136,6 @@ impl BackendOp for ImapOp {
|
||||||
let val = cache.flags;
|
let val = cache.flags;
|
||||||
val
|
val
|
||||||
};
|
};
|
||||||
let mut f = flags.lock().await;
|
|
||||||
*f = val;
|
|
||||||
Ok(val.unwrap())
|
Ok(val.unwrap())
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -376,9 +376,6 @@ impl MailBackend for ImapType {
|
||||||
};
|
};
|
||||||
Ok(Box::new(ImapOp::new(
|
Ok(Box::new(ImapOp::new(
|
||||||
uid,
|
uid,
|
||||||
self.uid_store.mailboxes.read().unwrap()[&mailbox_hash]
|
|
||||||
.imap_path()
|
|
||||||
.to_string(),
|
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
self.connection.clone(),
|
self.connection.clone(),
|
||||||
self.uid_store.clone(),
|
self.uid_store.clone(),
|
||||||
|
|
|
@ -30,12 +30,7 @@ use std::sync::Arc;
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ImapOp {
|
pub struct ImapOp {
|
||||||
uid: usize,
|
uid: usize,
|
||||||
bytes: Option<String>,
|
|
||||||
headers: Option<String>,
|
|
||||||
body: Option<String>,
|
|
||||||
mailbox_path: String,
|
|
||||||
mailbox_hash: MailboxHash,
|
mailbox_hash: MailboxHash,
|
||||||
flags: Arc<FutureMutex<Option<Flag>>>,
|
|
||||||
connection: Arc<FutureMutex<ImapConnection>>,
|
connection: Arc<FutureMutex<ImapConnection>>,
|
||||||
uid_store: Arc<UIDStore>,
|
uid_store: Arc<UIDStore>,
|
||||||
}
|
}
|
||||||
|
@ -43,7 +38,6 @@ pub struct ImapOp {
|
||||||
impl ImapOp {
|
impl ImapOp {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
uid: usize,
|
uid: usize,
|
||||||
mailbox_path: String,
|
|
||||||
mailbox_hash: MailboxHash,
|
mailbox_hash: MailboxHash,
|
||||||
connection: Arc<FutureMutex<ImapConnection>>,
|
connection: Arc<FutureMutex<ImapConnection>>,
|
||||||
uid_store: Arc<UIDStore>,
|
uid_store: Arc<UIDStore>,
|
||||||
|
@ -51,65 +45,63 @@ impl ImapOp {
|
||||||
ImapOp {
|
ImapOp {
|
||||||
uid,
|
uid,
|
||||||
connection,
|
connection,
|
||||||
bytes: None,
|
|
||||||
headers: None,
|
|
||||||
body: None,
|
|
||||||
mailbox_path,
|
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
flags: Arc::new(FutureMutex::new(None)),
|
|
||||||
uid_store,
|
uid_store,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackendOp for ImapOp {
|
impl BackendOp for ImapOp {
|
||||||
fn as_bytes(&mut self) -> Result<&[u8]> {
|
fn as_bytes(&mut self) -> ResultFuture<Vec<u8>> {
|
||||||
if self.bytes.is_none() {
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
let mut bytes_cache = self.uid_store.byte_cache.lock()?;
|
let connection = self.connection.clone();
|
||||||
let cache = bytes_cache.entry(self.uid).or_default();
|
let mailbox_hash = self.mailbox_hash;
|
||||||
if cache.bytes.is_some() {
|
let uid = self.uid;
|
||||||
self.bytes = cache.bytes.clone();
|
let uid_store = self.uid_store.clone();
|
||||||
} else {
|
Ok(Box::pin(async move {
|
||||||
drop(cache);
|
let exists_in_cache = {
|
||||||
drop(bytes_cache);
|
let mut bytes_cache = uid_store.byte_cache.lock()?;
|
||||||
let ret: Result<()> = futures::executor::block_on(async {
|
let cache = bytes_cache.entry(uid).or_default();
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
cache.bytes.is_some()
|
||||||
{
|
};
|
||||||
let mut conn = self.connection.lock().await;
|
if !exists_in_cache {
|
||||||
conn.examine_mailbox(self.mailbox_hash, &mut response, false)
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
.await?;
|
{
|
||||||
conn.send_command(
|
let mut conn = connection.lock().await;
|
||||||
format!("UID FETCH {} (FLAGS RFC822)", self.uid).as_bytes(),
|
conn.examine_mailbox(mailbox_hash, &mut response, false)
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
conn.read_response(&mut response, RequiredResponses::FETCH_REQUIRED)
|
conn.send_command(format!("UID FETCH {} (FLAGS RFC822)", uid).as_bytes())
|
||||||
.await?;
|
.await?;
|
||||||
}
|
conn.read_response(&mut response, RequiredResponses::FETCH_REQUIRED)
|
||||||
debug!(
|
.await?;
|
||||||
"fetch response is {} bytes and {} lines",
|
}
|
||||||
response.len(),
|
debug!(
|
||||||
response.lines().collect::<Vec<&str>>().len()
|
"fetch response is {} bytes and {} lines",
|
||||||
);
|
response.len(),
|
||||||
let UidFetchResponse {
|
response.lines().collect::<Vec<&str>>().len()
|
||||||
uid, flags, body, ..
|
);
|
||||||
} = protocol_parser::uid_fetch_response(&response)?.1;
|
let UidFetchResponse {
|
||||||
assert_eq!(uid, self.uid);
|
uid: _uid,
|
||||||
assert!(body.is_some());
|
flags: _flags,
|
||||||
let mut bytes_cache = self.uid_store.byte_cache.lock()?;
|
body,
|
||||||
let cache = bytes_cache.entry(self.uid).or_default();
|
..
|
||||||
if let Some((flags, _)) = flags {
|
} = protocol_parser::uid_fetch_response(&response)?.1;
|
||||||
//self.flags.set(Some(flags));
|
assert_eq!(_uid, uid);
|
||||||
cache.flags = Some(flags);
|
assert!(body.is_some());
|
||||||
}
|
let mut bytes_cache = uid_store.byte_cache.lock()?;
|
||||||
cache.bytes =
|
let cache = bytes_cache.entry(uid).or_default();
|
||||||
Some(unsafe { std::str::from_utf8_unchecked(body.unwrap()).to_string() });
|
if let Some((_flags, _)) = _flags {
|
||||||
self.bytes = cache.bytes.clone();
|
//flags.lock().await.set(Some(_flags));
|
||||||
Ok(())
|
cache.flags = Some(_flags);
|
||||||
});
|
}
|
||||||
ret?;
|
cache.bytes =
|
||||||
|
Some(unsafe { std::str::from_utf8_unchecked(body.unwrap()).to_string() });
|
||||||
}
|
}
|
||||||
}
|
let mut bytes_cache = uid_store.byte_cache.lock()?;
|
||||||
Ok(self.bytes.as_ref().unwrap().as_bytes())
|
let cache = bytes_cache.entry(uid).or_default();
|
||||||
|
let ret = cache.bytes.clone().unwrap().into_bytes();
|
||||||
|
Ok(ret)
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
||||||
|
@ -118,12 +110,8 @@ impl BackendOp for ImapOp {
|
||||||
let mailbox_hash = self.mailbox_hash;
|
let mailbox_hash = self.mailbox_hash;
|
||||||
let uid = self.uid;
|
let uid = self.uid;
|
||||||
let uid_store = self.uid_store.clone();
|
let uid_store = self.uid_store.clone();
|
||||||
let flags = self.flags.clone();
|
|
||||||
|
|
||||||
Ok(Box::pin(async move {
|
Ok(Box::pin(async move {
|
||||||
if let Some(val) = *flags.lock().await {
|
|
||||||
return Ok(val);
|
|
||||||
}
|
|
||||||
let exists_in_cache = {
|
let exists_in_cache = {
|
||||||
let mut bytes_cache = uid_store.byte_cache.lock()?;
|
let mut bytes_cache = uid_store.byte_cache.lock()?;
|
||||||
let cache = bytes_cache.entry(uid).or_default();
|
let cache = bytes_cache.entry(uid).or_default();
|
||||||
|
@ -158,7 +146,6 @@ impl BackendOp for ImapOp {
|
||||||
}
|
}
|
||||||
let (_uid, (_flags, _)) = v[0];
|
let (_uid, (_flags, _)) = v[0];
|
||||||
assert_eq!(uid, uid);
|
assert_eq!(uid, uid);
|
||||||
*flags.lock().await = Some(_flags);
|
|
||||||
let mut bytes_cache = uid_store.byte_cache.lock()?;
|
let mut bytes_cache = uid_store.byte_cache.lock()?;
|
||||||
let cache = bytes_cache.entry(uid).or_default();
|
let cache = bytes_cache.entry(uid).or_default();
|
||||||
cache.flags = Some(_flags);
|
cache.flags = Some(_flags);
|
||||||
|
@ -170,8 +157,6 @@ impl BackendOp for ImapOp {
|
||||||
let val = cache.flags;
|
let val = cache.flags;
|
||||||
val
|
val
|
||||||
};
|
};
|
||||||
let mut f = flags.lock().await;
|
|
||||||
*f = val;
|
|
||||||
Ok(val.unwrap())
|
Ok(val.unwrap())
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl JmapOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackendOp for JmapOp {
|
impl BackendOp for JmapOp {
|
||||||
fn as_bytes(&mut self) -> Result<&[u8]> {
|
fn as_bytes(&mut self) -> ResultFuture<Vec<u8>> {
|
||||||
if self.bytes.is_none() {
|
if self.bytes.is_none() {
|
||||||
let mut store_lck = self.store.write().unwrap();
|
let mut store_lck = self.store.write().unwrap();
|
||||||
if !(store_lck.byte_cache.contains_key(&self.hash)
|
if !(store_lck.byte_cache.contains_key(&self.hash)
|
||||||
|
@ -86,7 +86,8 @@ impl BackendOp for JmapOp {
|
||||||
}
|
}
|
||||||
self.bytes = store_lck.byte_cache[&self.hash].bytes.clone();
|
self.bytes = store_lck.byte_cache[&self.hash].bytes.clone();
|
||||||
}
|
}
|
||||||
Ok(&self.bytes.as_ref().unwrap().as_bytes())
|
let ret = self.bytes.as_ref().unwrap().as_bytes().to_vec();
|
||||||
|
Ok(Box::pin(async move { Ok(ret) }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
||||||
|
|
|
@ -90,12 +90,13 @@ impl MaildirOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> BackendOp for MaildirOp {
|
impl<'a> BackendOp for MaildirOp {
|
||||||
fn as_bytes(&mut self) -> Result<&[u8]> {
|
fn as_bytes(&mut self) -> ResultFuture<Vec<u8>> {
|
||||||
if self.slice.is_none() {
|
if self.slice.is_none() {
|
||||||
self.slice = Some(Mmap::open_path(self.path(), Protection::Read)?);
|
self.slice = Some(Mmap::open_path(self.path(), Protection::Read)?);
|
||||||
}
|
}
|
||||||
/* Unwrap is safe since we use ? above. */
|
/* Unwrap is safe since we use ? above. */
|
||||||
Ok(unsafe { self.slice.as_ref().unwrap().as_slice() })
|
let ret = Ok((unsafe { self.slice.as_ref().unwrap().as_slice() }).to_vec());
|
||||||
|
Ok(Box::pin(async move { ret }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
||||||
|
|
|
@ -182,14 +182,16 @@ impl MboxOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackendOp for MboxOp {
|
impl BackendOp for MboxOp {
|
||||||
fn as_bytes(&mut self) -> Result<&[u8]> {
|
fn as_bytes(&mut self) -> ResultFuture<Vec<u8>> {
|
||||||
if self.slice.is_none() {
|
if self.slice.is_none() {
|
||||||
self.slice = Some(Mmap::open_path(&self.path, Protection::Read)?);
|
self.slice = Some(Mmap::open_path(&self.path, Protection::Read)?);
|
||||||
}
|
}
|
||||||
/* Unwrap is safe since we use ? above. */
|
/* Unwrap is safe since we use ? above. */
|
||||||
Ok(unsafe {
|
let ret = Ok((unsafe {
|
||||||
&self.slice.as_ref().unwrap().as_slice()[self.offset..self.offset + self.length]
|
&self.slice.as_ref().unwrap().as_slice()[self.offset..self.offset + self.length]
|
||||||
})
|
})
|
||||||
|
.to_vec());
|
||||||
|
Ok(Box::pin(async move { ret }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
||||||
|
|
|
@ -646,7 +646,7 @@ struct NotmuchOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackendOp for NotmuchOp {
|
impl BackendOp for NotmuchOp {
|
||||||
fn as_bytes(&mut self) -> Result<&[u8]> {
|
fn as_bytes(&mut self) -> ResultFuture<Vec<u8>> {
|
||||||
let mut message: *mut notmuch_message_t = std::ptr::null_mut();
|
let mut message: *mut notmuch_message_t = std::ptr::null_mut();
|
||||||
let index_lck = self.index.write().unwrap();
|
let index_lck = self.index.write().unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -662,7 +662,8 @@ impl BackendOp for NotmuchOp {
|
||||||
let mut response = String::new();
|
let mut response = String::new();
|
||||||
f.read_to_string(&mut response)?;
|
f.read_to_string(&mut response)?;
|
||||||
self.bytes = Some(response);
|
self.bytes = Some(response);
|
||||||
Ok(self.bytes.as_ref().unwrap().as_bytes())
|
let ret = Ok(self.bytes.as_ref().unwrap().as_bytes().to_vec());
|
||||||
|
Ok(Box::pin(async move { ret }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
||||||
|
|
|
@ -229,8 +229,8 @@ impl Envelope {
|
||||||
pub fn from_token(mut operation: Box<dyn BackendOp>, hash: EnvelopeHash) -> Result<Envelope> {
|
pub fn from_token(mut operation: Box<dyn BackendOp>, hash: EnvelopeHash) -> Result<Envelope> {
|
||||||
let mut e = Envelope::new(hash);
|
let mut e = Envelope::new(hash);
|
||||||
e.flags = futures::executor::block_on(operation.fetch_flags()?)?;
|
e.flags = futures::executor::block_on(operation.fetch_flags()?)?;
|
||||||
let bytes = operation.as_bytes()?;
|
let bytes = futures::executor::block_on(operation.as_bytes()?)?;
|
||||||
e.populate_headers(bytes)?;
|
e.populate_headers(&bytes)?;
|
||||||
Ok(e)
|
Ok(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,11 +413,6 @@ impl Envelope {
|
||||||
_strings.join(", ")
|
_strings.join(", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Requests bytes from backend and thus can fail
|
|
||||||
pub fn bytes(&self, mut operation: Box<dyn BackendOp>) -> Result<Vec<u8>> {
|
|
||||||
operation.as_bytes().map(|v| v.to_vec())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn body_bytes(&self, bytes: &[u8]) -> Attachment {
|
pub fn body_bytes(&self, bytes: &[u8]) -> Attachment {
|
||||||
let builder = AttachmentBuilder::new(bytes);
|
let builder = AttachmentBuilder::new(bytes);
|
||||||
builder.build()
|
builder.build()
|
||||||
|
@ -439,8 +434,8 @@ impl Envelope {
|
||||||
/// Requests bytes from backend and thus can fail
|
/// Requests bytes from backend and thus can fail
|
||||||
pub fn body(&self, mut operation: Box<dyn BackendOp>) -> Result<Attachment> {
|
pub fn body(&self, mut operation: Box<dyn BackendOp>) -> Result<Attachment> {
|
||||||
debug!("searching body for {:?}", self.message_id_display());
|
debug!("searching body for {:?}", self.message_id_display());
|
||||||
let file = operation.as_bytes()?;
|
let bytes = futures::executor::block_on(operation.as_bytes()?)?;
|
||||||
Ok(self.body_bytes(file))
|
Ok(self.body_bytes(&bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subject(&self) -> Cow<str> {
|
pub fn subject(&self) -> Cow<str> {
|
||||||
|
|
|
@ -138,8 +138,8 @@ impl Draft {
|
||||||
let mut ret = Draft::default();
|
let mut ret = Draft::default();
|
||||||
//TODO: Inform user if error
|
//TODO: Inform user if error
|
||||||
{
|
{
|
||||||
let bytes = op.as_bytes().unwrap_or(&[]);
|
let bytes = futures::executor::block_on(op.as_bytes()?)?;
|
||||||
for (k, v) in envelope.headers(bytes).unwrap_or_else(|_| Vec::new()) {
|
for (k, v) in envelope.headers(&bytes).unwrap_or_else(|_| Vec::new()) {
|
||||||
if ignore_header(k.as_bytes()) {
|
if ignore_header(k.as_bytes()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,9 +238,10 @@ impl Composer {
|
||||||
Some(NotificationType::ERROR),
|
Some(NotificationType::ERROR),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(mut op) => {
|
Ok(op) => {
|
||||||
let parent_bytes = op.as_bytes();
|
//FIXME
|
||||||
ret.draft = Draft::new_reply(&parent_message, parent_bytes.unwrap());
|
//let parent_bytes = op.as_bytes();
|
||||||
|
//ret.draft = Draft::new_reply(&parent_message, parent_bytes.unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let subject = parent_message.subject();
|
let subject = parent_message.subject();
|
||||||
|
|
|
@ -203,6 +203,8 @@ pub trait MailListingTrait: ListingTrait {
|
||||||
}
|
}
|
||||||
ListingAction::CopyTo(ref mailbox_path) => {
|
ListingAction::CopyTo(ref mailbox_path) => {
|
||||||
drop(envelope);
|
drop(envelope);
|
||||||
|
/*
|
||||||
|
* FIXME
|
||||||
match account
|
match account
|
||||||
.mailbox_by_path(mailbox_path)
|
.mailbox_by_path(mailbox_path)
|
||||||
.and_then(|mailbox_hash| {
|
.and_then(|mailbox_hash| {
|
||||||
|
@ -219,10 +221,13 @@ pub trait MailListingTrait: ListingTrait {
|
||||||
}
|
}
|
||||||
Ok(fut) => {}
|
Ok(fut) => {}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ListingAction::CopyToOtherAccount(ref account_name, ref mailbox_path) => {
|
ListingAction::CopyToOtherAccount(ref account_name, ref mailbox_path) => {
|
||||||
drop(envelope);
|
drop(envelope);
|
||||||
|
/*
|
||||||
|
* FIXME
|
||||||
if let Err(err) = op.as_bytes().map(|b| b.to_vec()).and_then(|bytes| {
|
if let Err(err) = op.as_bytes().map(|b| b.to_vec()).and_then(|bytes| {
|
||||||
let account_pos = context
|
let account_pos = context
|
||||||
.accounts
|
.accounts
|
||||||
|
@ -245,10 +250,13 @@ pub trait MailListingTrait: ListingTrait {
|
||||||
));
|
));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ListingAction::MoveTo(ref mailbox_path) => {
|
ListingAction::MoveTo(ref mailbox_path) => {
|
||||||
drop(envelope);
|
drop(envelope);
|
||||||
|
/*
|
||||||
|
* FIXME
|
||||||
if let Err(err) =
|
if let Err(err) =
|
||||||
account
|
account
|
||||||
.mailbox_by_path(mailbox_path)
|
.mailbox_by_path(mailbox_path)
|
||||||
|
@ -264,10 +272,12 @@ pub trait MailListingTrait: ListingTrait {
|
||||||
));
|
));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ListingAction::MoveToOtherAccount(ref account_name, ref mailbox_path) => {
|
ListingAction::MoveToOtherAccount(ref account_name, ref mailbox_path) => {
|
||||||
drop(envelope);
|
drop(envelope);
|
||||||
|
/* FIXME
|
||||||
if let Err(err) = op
|
if let Err(err) = op
|
||||||
.as_bytes()
|
.as_bytes()
|
||||||
.map(|b| b.to_vec())
|
.map(|b| b.to_vec())
|
||||||
|
@ -302,26 +312,37 @@ pub trait MailListingTrait: ListingTrait {
|
||||||
));
|
));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ListingAction::Tag(Remove(ref tag_str)) => {
|
ListingAction::Tag(Remove(ref tag_str)) => {
|
||||||
if let Err(err) = op.set_tag(tag_str.to_string(), false) {
|
match op.set_tag(tag_str.to_string(), false) {
|
||||||
context.replies.push_back(UIEvent::Notification(
|
Err(err) => {
|
||||||
Some("Could not set tag.".to_string()),
|
context.replies.push_back(UIEvent::Notification(
|
||||||
err.to_string(),
|
Some("Could not set tag.".to_string()),
|
||||||
Some(NotificationType::ERROR),
|
err.to_string(),
|
||||||
));
|
Some(NotificationType::ERROR),
|
||||||
return;
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Ok(fut) => {
|
||||||
|
//FIXME
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ListingAction::Tag(Add(ref tag_str)) => {
|
ListingAction::Tag(Add(ref tag_str)) => {
|
||||||
if let Err(err) = op.set_tag(tag_str.to_string(), true) {
|
match op.set_tag(tag_str.to_string(), true) {
|
||||||
context.replies.push_back(UIEvent::Notification(
|
Err(err) => {
|
||||||
Some("Could not set tag.".to_string()),
|
context.replies.push_back(UIEvent::Notification(
|
||||||
err.to_string(),
|
Some("Could not set tag.".to_string()),
|
||||||
Some(NotificationType::ERROR),
|
err.to_string(),
|
||||||
));
|
Some(NotificationType::ERROR),
|
||||||
return;
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Ok(fut) => {
|
||||||
|
// FIXME
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
|
@ -214,7 +214,7 @@ impl MailListingTrait for PlainListing {
|
||||||
let env_hash = self.get_env_under_cursor(self.cursor_pos.2, context);
|
let env_hash = self.get_env_under_cursor(self.cursor_pos.2, context);
|
||||||
let temp = (self.new_cursor_pos.0, self.new_cursor_pos.1, env_hash);
|
let temp = (self.new_cursor_pos.0, self.new_cursor_pos.1, env_hash);
|
||||||
if !force && old_cursor_pos == self.new_cursor_pos {
|
if !force && old_cursor_pos == self.new_cursor_pos {
|
||||||
self.view.update(temp);
|
self.view.update(temp, context);
|
||||||
} else if self.unfocused {
|
} else if self.unfocused {
|
||||||
self.view = MailView::new(temp, None, None, context);
|
self.view = MailView::new(temp, None, None, context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -632,7 +632,7 @@ impl Component for ThreadListing {
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(ref mut v) = self.view {
|
if let Some(ref mut v) = self.view {
|
||||||
v.update(coordinates);
|
v.update(coordinates, context);
|
||||||
} else {
|
} else {
|
||||||
self.view = Some(MailView::new(coordinates, None, None, context));
|
self.view = Some(MailView::new(coordinates, None, None, context));
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -95,7 +95,6 @@ impl EnvelopeView {
|
||||||
&body,
|
&body,
|
||||||
Some(Box::new(|a: &Attachment, v: &mut Vec<u8>| {
|
Some(Box::new(|a: &Attachment, v: &mut Vec<u8>| {
|
||||||
if a.content_type().is_text_html() {
|
if a.content_type().is_text_html() {
|
||||||
use std::io::Write;
|
|
||||||
let settings = &context.settings;
|
let settings = &context.settings;
|
||||||
if let Some(filter_invocation) = settings.pager.html_filter.as_ref() {
|
if let Some(filter_invocation) = settings.pager.html_filter.as_ref() {
|
||||||
let command_obj = Command::new("sh")
|
let command_obj = Command::new("sh")
|
||||||
|
|
|
@ -961,7 +961,7 @@ impl Component for ThreadView {
|
||||||
self.coordinates.1,
|
self.coordinates.1,
|
||||||
self.entries[self.current_pos()].msg_hash,
|
self.entries[self.current_pos()].msg_hash,
|
||||||
);
|
);
|
||||||
self.mailview.update(coordinates);
|
self.mailview.update(coordinates, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.entries.len() == 1 {
|
if self.entries.len() == 1 {
|
||||||
|
|
|
@ -156,6 +156,7 @@ pub enum JobRequest {
|
||||||
DeleteMailbox(oneshot::Receiver<Result<HashMap<MailboxHash, Mailbox>>>),
|
DeleteMailbox(oneshot::Receiver<Result<HashMap<MailboxHash, Mailbox>>>),
|
||||||
//RenameMailbox,
|
//RenameMailbox,
|
||||||
Search,
|
Search,
|
||||||
|
AsBytes,
|
||||||
SetMailboxPermissions(MailboxHash, oneshot::Receiver<Result<()>>),
|
SetMailboxPermissions(MailboxHash, oneshot::Receiver<Result<()>>),
|
||||||
SetMailboxSubscription(MailboxHash, oneshot::Receiver<Result<()>>),
|
SetMailboxSubscription(MailboxHash, oneshot::Receiver<Result<()>>),
|
||||||
Watch(JoinHandle),
|
Watch(JoinHandle),
|
||||||
|
@ -175,6 +176,7 @@ impl core::fmt::Debug for JobRequest {
|
||||||
JobRequest::DeleteMailbox(_) => write!(f, "{}", "JobRequest::DeleteMailbox"),
|
JobRequest::DeleteMailbox(_) => write!(f, "{}", "JobRequest::DeleteMailbox"),
|
||||||
//JobRequest::RenameMailbox,
|
//JobRequest::RenameMailbox,
|
||||||
JobRequest::Search => write!(f, "{}", "JobRequest::Search"),
|
JobRequest::Search => write!(f, "{}", "JobRequest::Search"),
|
||||||
|
JobRequest::AsBytes => write!(f, "{}", "JobRequest::AsBytes"),
|
||||||
JobRequest::SetMailboxPermissions(_, _) => {
|
JobRequest::SetMailboxPermissions(_, _) => {
|
||||||
write!(f, "{}", "JobRequest::SetMailboxPermissions")
|
write!(f, "{}", "JobRequest::SetMailboxPermissions")
|
||||||
}
|
}
|
||||||
|
@ -1599,7 +1601,7 @@ impl Account {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//JobRequest::RenameMailbox,
|
//JobRequest::RenameMailbox,
|
||||||
JobRequest::Search => {
|
JobRequest::Search | JobRequest::AsBytes => {
|
||||||
self.sender
|
self.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::StatusEvent(
|
.send(ThreadEvent::UIEvent(UIEvent::StatusEvent(
|
||||||
StatusEvent::JobFinished(job_id.clone()),
|
StatusEvent::JobFinished(job_id.clone()),
|
||||||
|
|
|
@ -296,22 +296,24 @@ struct PluginOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackendOp for PluginOp {
|
impl BackendOp for PluginOp {
|
||||||
fn as_bytes(&mut self) -> Result<&[u8]> {
|
fn as_bytes(&mut self) -> ResultFuture<Vec<u8>> {
|
||||||
if let Some(ref bytes) = self.bytes {
|
let hash = self.hash;
|
||||||
return Ok(bytes.as_bytes());
|
let channel = self.channel.clone();
|
||||||
}
|
Ok(Box::pin(async move {
|
||||||
|
if let Ok(mut channel) = channel.try_lock() {
|
||||||
if let Ok(mut channel) = self.channel.try_lock() {
|
channel.write_ref(&rmpv::ValueRef::Ext(BACKEND_OP_FN, b"as_bytes"))?;
|
||||||
channel.write_ref(&rmpv::ValueRef::Ext(BACKEND_OP_FN, b"as_bytes"))?;
|
debug!(channel.expect_ack())?;
|
||||||
debug!(channel.expect_ack())?;
|
channel.write_ref(&rmpv::ValueRef::Integer(hash.into()))?;
|
||||||
channel.write_ref(&rmpv::ValueRef::Integer(self.hash.into()))?;
|
debug!(channel.expect_ack())?;
|
||||||
debug!(channel.expect_ack())?;
|
let bytes: Result<PluginResult<String>> = channel.from_read();
|
||||||
let bytes: Result<PluginResult<String>> = channel.from_read();
|
Ok(bytes
|
||||||
self.bytes = Some(bytes.map(Into::into).and_then(std::convert::identity)?);
|
.map(Into::into)
|
||||||
Ok(self.bytes.as_ref().map(String::as_bytes).unwrap())
|
.and_then(std::convert::identity)?
|
||||||
} else {
|
.into_bytes())
|
||||||
Err(MeliError::new("busy"))
|
} else {
|
||||||
}
|
Err(MeliError::new("busy"))
|
||||||
|
}
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
fn fetch_flags(&self) -> ResultFuture<Flag> {
|
||||||
|
|
Loading…
Reference in New Issue