diff --git a/melib/src/backends.rs b/melib/src/backends.rs index 52d5edb3..df5d56b2 100644 --- a/melib/src/backends.rs +++ b/melib/src/backends.rs @@ -415,7 +415,7 @@ pub trait MailBackend: ::std::fmt::Debug + Send + Sync { /// fn as_bytes(&mut self) -> Result<&[u8]> { /// unimplemented!() /// } -/// fn fetch_flags(&self) -> Flag { +/// fn fetch_flags(&self) -> Result { /// unimplemented!() /// } /// } @@ -426,7 +426,7 @@ pub trait MailBackend: ::std::fmt::Debug + Send + Sync { pub trait BackendOp: ::std::fmt::Debug + ::std::marker::Send { fn description(&self) -> String; fn as_bytes(&mut self) -> Result<&[u8]>; - fn fetch_flags(&self) -> Flag; + fn fetch_flags(&self) -> Result; fn set_flag(&mut self, envelope: &mut Envelope, flag: Flag, value: bool) -> Result<()>; fn set_tag(&mut self, envelope: &mut Envelope, tag: String, value: bool) -> Result<()>; } @@ -453,7 +453,7 @@ impl BackendOp for ReadOnlyOp { fn as_bytes(&mut self) -> Result<&[u8]> { self.op.as_bytes() } - fn fetch_flags(&self) -> Flag { + fn fetch_flags(&self) -> Result { self.op.fetch_flags() } fn set_flag(&mut self, _envelope: &mut Envelope, _flag: Flag, _value: bool) -> Result<()> { diff --git a/melib/src/backends/imap/operations.rs b/melib/src/backends/imap/operations.rs index a344dca6..8b6c6b03 100644 --- a/melib/src/backends/imap/operations.rs +++ b/melib/src/backends/imap/operations.rs @@ -109,63 +109,48 @@ impl BackendOp for ImapOp { Ok(self.bytes.as_ref().unwrap().as_bytes()) } - fn fetch_flags(&self) -> Flag { - macro_rules! or_return_default { - ($expr:expr) => { - match $expr { - Ok(ok) => ok, - Err(_) => return Default::default(), - } - }; - } + fn fetch_flags(&self) -> Result { if self.flags.get().is_some() { - return self.flags.get().unwrap(); + return Ok(self.flags.get().unwrap()); } - let mut bytes_cache = or_return_default!(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(); if cache.flags.is_some() { self.flags.set(cache.flags); } else { let mut response = String::with_capacity(8 * 1024); - let mut conn = or_return_default!(try_lock( - &self.connection, - Some(std::time::Duration::new(2, 0)) - )); - or_return_default!(conn.examine_mailbox(self.mailbox_hash, &mut response, false)); - or_return_default!( - conn.send_command(format!("UID FETCH {} FLAGS", self.uid).as_bytes()) - ); - or_return_default!(conn.read_response(&mut response, RequiredResponses::FETCH_REQUIRED)); + 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", self.uid).as_bytes())?; + conn.read_response(&mut response, RequiredResponses::FETCH_REQUIRED)?; debug!( "fetch response is {} bytes and {} lines", response.len(), response.lines().collect::>().len() ); - match protocol_parser::uid_fetch_flags_response(response.as_bytes()) + let v = protocol_parser::uid_fetch_flags_response(response.as_bytes()) .map(|(_, v)| v) - .map_err(MeliError::from) - { - Ok(v) => { - if v.len() != 1 { - debug!("responses len is {}", v.len()); - debug!(response); - /* TODO: Trigger cache invalidation here. */ - debug!(format!("message with UID {} was not found", self.uid)); - return Flag::default(); - } - let (uid, (flags, _)) = v[0]; - assert_eq!(uid, self.uid); - cache.flags = Some(flags); - self.flags.set(Some(flags)); - } - Err(e) => or_return_default!(Err(e)), + .map_err(MeliError::from)?; + if v.len() != 1 { + debug!("responses len is {}", v.len()); + debug!(&response); + /* TODO: Trigger cache invalidation here. */ + debug!(format!("message with UID {} was not found", self.uid)); + return Err( + MeliError::new(format!("Invalid/unexpected response: {:?}", response)) + .set_summary(format!("message with UID {} was not found?", self.uid)), + ); } + let (uid, (flags, _)) = v[0]; + assert_eq!(uid, self.uid); + cache.flags = Some(flags); + self.flags.set(Some(flags)); } - self.flags.get().unwrap() + Ok(self.flags.get().unwrap()) } fn set_flag(&mut self, _envelope: &mut Envelope, f: Flag, value: bool) -> Result<()> { - let mut flags = self.fetch_flags(); + let mut flags = self.fetch_flags()?; flags.set(f, value); let mut response = String::with_capacity(8 * 1024); diff --git a/melib/src/backends/jmap/operations.rs b/melib/src/backends/jmap/operations.rs index 79d904f1..d51758e0 100644 --- a/melib/src/backends/jmap/operations.rs +++ b/melib/src/backends/jmap/operations.rs @@ -97,8 +97,8 @@ impl BackendOp for JmapOp { Ok(&self.bytes.as_ref().unwrap().as_bytes()) } - fn fetch_flags(&self) -> Flag { - Flag::default() + fn fetch_flags(&self) -> Result { + Ok(Flag::default()) } fn set_flag(&mut self, _envelope: &mut Envelope, _f: Flag, _value: bool) -> Result<()> { diff --git a/melib/src/backends/maildir.rs b/melib/src/backends/maildir.rs index cb234199..0516bf31 100644 --- a/melib/src/backends/maildir.rs +++ b/melib/src/backends/maildir.rs @@ -101,9 +101,9 @@ impl<'a> BackendOp for MaildirOp { Ok(unsafe { self.slice.as_ref().unwrap().as_slice() }) } - fn fetch_flags(&self) -> Flag { + fn fetch_flags(&self) -> Result { let path = self.path(); - path.flags() + Ok(path.flags()) } fn set_flag(&mut self, envelope: &mut Envelope, f: Flag, value: bool) -> Result<()> { @@ -114,7 +114,7 @@ impl<'a> BackendOp for MaildirOp { .ok_or_else(|| MeliError::new(format!("Invalid email filename: {:?}", self)))? + 3; let mut new_name: String = path[..idx].to_string(); - let mut flags = self.fetch_flags(); + let mut flags = self.fetch_flags()?; flags.set(f, value); if !(flags & Flag::DRAFT).is_empty() { diff --git a/melib/src/backends/mbox.rs b/melib/src/backends/mbox.rs index 039e5715..2c4eea95 100644 --- a/melib/src/backends/mbox.rs +++ b/melib/src/backends/mbox.rs @@ -201,72 +201,60 @@ impl BackendOp for MboxOp { }) } - fn fetch_flags(&self) -> Flag { + fn fetch_flags(&self) -> Result { let mut flags = Flag::empty(); - let file = match std::fs::OpenOptions::new() + let file = std::fs::OpenOptions::new() .read(true) .write(true) - .open(&self.path) - { - Ok(f) => f, - Err(e) => { - debug!(e); - return flags; - } - }; + .open(&self.path)?; get_rw_lock_blocking(&file); let mut buf_reader = BufReader::new(file); let mut contents = Vec::new(); - if let Err(e) = buf_reader.read_to_end(&mut contents) { - debug!(e); - return flags; - }; - - if let Ok((_, headers)) = parser::headers::headers_raw(contents.as_slice()) { - if let Some(start) = headers.find(b"Status:") { - if let Some(end) = headers[start..].find(b"\n") { - let start = start + b"Status:".len(); - let status = headers[start..start + end].trim(); - if status.contains(&b'F') { - flags.set(Flag::FLAGGED, true); - } - if status.contains(&b'A') { - flags.set(Flag::REPLIED, true); - } - if status.contains(&b'R') { - flags.set(Flag::SEEN, true); - } - if status.contains(&b'D') { - flags.set(Flag::TRASHED, true); - } - if status.contains(&b'T') { - flags.set(Flag::DRAFT, true); - } + buf_reader.read_to_end(&mut contents)?; + let (_, headers) = parser::headers::headers_raw(contents.as_slice())?; + if let Some(start) = headers.find(b"Status:") { + if let Some(end) = headers[start..].find(b"\n") { + let start = start + b"Status:".len(); + let status = headers[start..start + end].trim(); + if status.contains(&b'F') { + flags.set(Flag::FLAGGED, true); } - } - if let Some(start) = headers.find(b"X-Status:") { - let start = start + b"X-Status:".len(); - if let Some(end) = headers[start..].find(b"\n") { - let status = headers[start..start + end].trim(); - if status.contains(&b'F') { - flags.set(Flag::FLAGGED, true); - } - if status.contains(&b'A') { - flags.set(Flag::REPLIED, true); - } - if status.contains(&b'R') { - flags.set(Flag::SEEN, true); - } - if status.contains(&b'D') { - flags.set(Flag::TRASHED, true); - } - if status.contains(&b'T') { - flags.set(Flag::DRAFT, true); - } + if status.contains(&b'A') { + flags.set(Flag::REPLIED, true); + } + if status.contains(&b'R') { + flags.set(Flag::SEEN, true); + } + if status.contains(&b'D') { + flags.set(Flag::TRASHED, true); + } + if status.contains(&b'T') { + flags.set(Flag::DRAFT, true); } } } - flags + if let Some(start) = headers.find(b"X-Status:") { + let start = start + b"X-Status:".len(); + if let Some(end) = headers[start..].find(b"\n") { + let status = headers[start..start + end].trim(); + if status.contains(&b'F') { + flags.set(Flag::FLAGGED, true); + } + if status.contains(&b'A') { + flags.set(Flag::REPLIED, true); + } + if status.contains(&b'R') { + flags.set(Flag::SEEN, true); + } + if status.contains(&b'D') { + flags.set(Flag::TRASHED, true); + } + if status.contains(&b'T') { + flags.set(Flag::DRAFT, true); + } + } + } + Ok(flags) } fn set_flag(&mut self, _envelope: &mut Envelope, _flag: Flag, _value: bool) -> Result<()> { @@ -915,7 +903,7 @@ impl MailBackend for MboxType { Err(MeliError::new("Unimplemented.")) } - fn as_any(&self) -> &dyn::std::any::Any { + fn as_any(&self) -> &dyn ::std::any::Any { self } } diff --git a/melib/src/backends/notmuch.rs b/melib/src/backends/notmuch.rs index 2d90d629..9e2a806f 100644 --- a/melib/src/backends/notmuch.rs +++ b/melib/src/backends/notmuch.rs @@ -624,7 +624,7 @@ impl MailBackend for NotmuchDb { crate::backends::MaildirType::save_to_mailbox(path, bytes, flags) } - fn as_any(&self) -> &dyn::std::any::Any { + fn as_any(&self) -> &dyn ::std::any::Any { self } @@ -667,7 +667,7 @@ impl BackendOp for NotmuchOp { Ok(self.bytes.as_ref().unwrap().as_bytes()) } - fn fetch_flags(&self) -> Flag { + fn fetch_flags(&self) -> Result { let mut message: *mut notmuch_message_t = std::ptr::null_mut(); let index_lck = self.index.write().unwrap(); unsafe { @@ -678,11 +678,11 @@ impl BackendOp for NotmuchOp { ) }; let (flags, _tags) = TagIterator::new(self.lib.clone(), message).collect_flags_and_tags(); - flags + Ok(flags) } fn set_flag(&mut self, envelope: &mut Envelope, f: Flag, value: bool) -> Result<()> { - let mut flags = self.fetch_flags(); + let mut flags = self.fetch_flags()?; flags.set(f, value); envelope.set_flags(flags); let mut message: *mut notmuch_message_t = std::ptr::null_mut(); diff --git a/melib/src/email.rs b/melib/src/email.rs index 05dc7a25..ec164424 100644 --- a/melib/src/email.rs +++ b/melib/src/email.rs @@ -225,7 +225,7 @@ impl Envelope { } pub fn from_token(mut operation: Box, hash: EnvelopeHash) -> Option { let mut e = Envelope::new(hash); - e.flags = operation.fetch_flags(); + e.flags = operation.fetch_flags().unwrap_or_default(); if let Ok(bytes) = operation.as_bytes() { let res = e.populate_headers(bytes).ok(); if res.is_some() { diff --git a/src/plugins/backend.rs b/src/plugins/backend.rs index 56ebdc3e..5fd3042f 100644 --- a/src/plugins/backend.rs +++ b/src/plugins/backend.rs @@ -225,7 +225,7 @@ impl MailBackend for PluginBackend { fn tags(&self) -> Option>>> { self.tag_index.clone() } - fn as_any(&self) -> &dyn::std::any::Any { + fn as_any(&self) -> &dyn ::std::any::Any { self } } @@ -314,10 +314,8 @@ impl BackendOp for PluginOp { } } - fn fetch_flags(&self) -> Flag { - let flag = Flag::default(); - - flag + fn fetch_flags(&self) -> Result { + Err(MeliError::new("Unimplemented.")) } fn set_flag(&mut self, __envelope: &mut Envelope, _f: Flag, _value: bool) -> Result<()> {