BackendOp: change fetch_flags retval to Result<Flag>
parent
ee10cdbcd5
commit
8c1fc031e5
|
@ -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<()> {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<()> {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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…
Reference in New Issue