Browse Source

BackendOp: change fetch_flags retval to Result<Flag>

tags/alpha-0.6.0
Manos Pitsidianakis 10 months ago
parent
commit
8c1fc031e5
Signed by: epilys GPG Key ID: 73627C2F690DF710
8 changed files with 84 additions and 113 deletions
  1. +3
    -3
      melib/src/backends.rs
  2. +24
    -39
      melib/src/backends/imap/operations.rs
  3. +2
    -2
      melib/src/backends/jmap/operations.rs
  4. +3
    -3
      melib/src/backends/maildir.rs
  5. +44
    -56
      melib/src/backends/mbox.rs
  6. +4
    -4
      melib/src/backends/notmuch.rs
  7. +1
    -1
      melib/src/email.rs
  8. +3
    -5
      src/plugins/backend.rs

+ 3
- 3
melib/src/backends.rs View File

@ -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<Flag> {
/// 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<Flag>;
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<Flag> {
self.op.fetch_flags()
}
fn set_flag(&mut self, _envelope: &mut Envelope, _flag: Flag, _value: bool) -> Result<()> {

+ 24
- 39
melib/src/backends/imap/operations.rs View File

@ -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<Flag> {
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::<Vec<&str>>().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);

+ 2
- 2
melib/src/backends/jmap/operations.rs View File

@ -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<Flag> {
Ok(Flag::default())
}
fn set_flag(&mut self, _envelope: &mut Envelope, _f: Flag, _value: bool) -> Result<()> {

+ 3
- 3
melib/src/backends/maildir.rs View File

@ -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<Flag> {
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() {

+ 44
- 56
melib/src/backends/mbox.rs View File

@ -201,72 +201,60 @@ impl BackendOp for MboxOp {
})
}
fn fetch_flags(&self) -> Flag {
fn fetch_flags(&self) -> Result<Flag> {
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 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 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 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);
}
}
}
flags
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
}
}

+ 4
- 4
melib/src/backends/notmuch.rs View File

@ -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<Flag> {
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();

+ 1
- 1
melib/src/email.rs View File

@ -225,7 +225,7 @@ impl Envelope {
}
pub fn from_token(mut operation: Box<dyn BackendOp>, hash: EnvelopeHash) -> Option<Envelope> {
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() {

+ 3
- 5
src/plugins/backend.rs View File

@ -225,7 +225,7 @@ impl MailBackend for PluginBackend {
fn tags(&self) -> Option<Arc<RwLock<BTreeMap<u64, String>>>> {
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<Flag> {
Err(MeliError::new("Unimplemented."))
}
fn set_flag(&mut self, __envelope: &mut Envelope, _f: Flag, _value: bool) -> Result<()> {

Loading…
Cancel
Save