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]> {
|
/// fn as_bytes(&mut self) -> Result<&[u8]> {
|
||||||
/// unimplemented!()
|
/// unimplemented!()
|
||||||
/// }
|
/// }
|
||||||
/// fn fetch_flags(&self) -> Flag {
|
/// fn fetch_flags(&self) -> Result<Flag> {
|
||||||
/// unimplemented!()
|
/// unimplemented!()
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
@ -426,7 +426,7 @@ pub trait MailBackend: ::std::fmt::Debug + Send + Sync {
|
||||||
pub trait BackendOp: ::std::fmt::Debug + ::std::marker::Send {
|
pub trait BackendOp: ::std::fmt::Debug + ::std::marker::Send {
|
||||||
fn description(&self) -> String;
|
fn description(&self) -> String;
|
||||||
fn as_bytes(&mut self) -> Result<&[u8]>;
|
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_flag(&mut self, envelope: &mut Envelope, flag: Flag, value: bool) -> Result<()>;
|
||||||
fn set_tag(&mut self, envelope: &mut Envelope, tag: String, 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]> {
|
fn as_bytes(&mut self) -> Result<&[u8]> {
|
||||||
self.op.as_bytes()
|
self.op.as_bytes()
|
||||||
}
|
}
|
||||||
fn fetch_flags(&self) -> Flag {
|
fn fetch_flags(&self) -> Result<Flag> {
|
||||||
self.op.fetch_flags()
|
self.op.fetch_flags()
|
||||||
}
|
}
|
||||||
fn set_flag(&mut self, _envelope: &mut Envelope, _flag: Flag, _value: bool) -> Result<()> {
|
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())
|
Ok(self.bytes.as_ref().unwrap().as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_flags(&self) -> Flag {
|
fn fetch_flags(&self) -> Result<Flag> {
|
||||||
macro_rules! or_return_default {
|
|
||||||
($expr:expr) => {
|
|
||||||
match $expr {
|
|
||||||
Ok(ok) => ok,
|
|
||||||
Err(_) => return Default::default(),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if self.flags.get().is_some() {
|
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();
|
let cache = bytes_cache.entry(self.uid).or_default();
|
||||||
if cache.flags.is_some() {
|
if cache.flags.is_some() {
|
||||||
self.flags.set(cache.flags);
|
self.flags.set(cache.flags);
|
||||||
} else {
|
} else {
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
let mut conn = or_return_default!(try_lock(
|
let mut conn = try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
||||||
&self.connection,
|
conn.examine_mailbox(self.mailbox_hash, &mut response, false)?;
|
||||||
Some(std::time::Duration::new(2, 0))
|
conn.send_command(format!("UID FETCH {} FLAGS", self.uid).as_bytes())?;
|
||||||
));
|
conn.read_response(&mut response, RequiredResponses::FETCH_REQUIRED)?;
|
||||||
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));
|
|
||||||
debug!(
|
debug!(
|
||||||
"fetch response is {} bytes and {} lines",
|
"fetch response is {} bytes and {} lines",
|
||||||
response.len(),
|
response.len(),
|
||||||
response.lines().collect::<Vec<&str>>().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(|(_, v)| v)
|
||||||
.map_err(MeliError::from)
|
.map_err(MeliError::from)?;
|
||||||
{
|
if v.len() != 1 {
|
||||||
Ok(v) => {
|
debug!("responses len is {}", v.len());
|
||||||
if v.len() != 1 {
|
debug!(&response);
|
||||||
debug!("responses len is {}", v.len());
|
/* TODO: Trigger cache invalidation here. */
|
||||||
debug!(response);
|
debug!(format!("message with UID {} was not found", self.uid));
|
||||||
/* TODO: Trigger cache invalidation here. */
|
return Err(
|
||||||
debug!(format!("message with UID {} was not found", self.uid));
|
MeliError::new(format!("Invalid/unexpected response: {:?}", response))
|
||||||
return Flag::default();
|
.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));
|
|
||||||
}
|
|
||||||
Err(e) => or_return_default!(Err(e)),
|
|
||||||
}
|
}
|
||||||
|
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<()> {
|
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);
|
flags.set(f, value);
|
||||||
|
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
|
|
|
@ -97,8 +97,8 @@ impl BackendOp for JmapOp {
|
||||||
Ok(&self.bytes.as_ref().unwrap().as_bytes())
|
Ok(&self.bytes.as_ref().unwrap().as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_flags(&self) -> Flag {
|
fn fetch_flags(&self) -> Result<Flag> {
|
||||||
Flag::default()
|
Ok(Flag::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_flag(&mut self, _envelope: &mut Envelope, _f: Flag, _value: bool) -> Result<()> {
|
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() })
|
Ok(unsafe { self.slice.as_ref().unwrap().as_slice() })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_flags(&self) -> Flag {
|
fn fetch_flags(&self) -> Result<Flag> {
|
||||||
let path = self.path();
|
let path = self.path();
|
||||||
path.flags()
|
Ok(path.flags())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_flag(&mut self, envelope: &mut Envelope, f: Flag, value: bool) -> Result<()> {
|
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)))?
|
.ok_or_else(|| MeliError::new(format!("Invalid email filename: {:?}", self)))?
|
||||||
+ 3;
|
+ 3;
|
||||||
let mut new_name: String = path[..idx].to_string();
|
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);
|
flags.set(f, value);
|
||||||
|
|
||||||
if !(flags & Flag::DRAFT).is_empty() {
|
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 mut flags = Flag::empty();
|
||||||
let file = match std::fs::OpenOptions::new()
|
let file = std::fs::OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.open(&self.path)
|
.open(&self.path)?;
|
||||||
{
|
|
||||||
Ok(f) => f,
|
|
||||||
Err(e) => {
|
|
||||||
debug!(e);
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
get_rw_lock_blocking(&file);
|
get_rw_lock_blocking(&file);
|
||||||
let mut buf_reader = BufReader::new(file);
|
let mut buf_reader = BufReader::new(file);
|
||||||
let mut contents = Vec::new();
|
let mut contents = Vec::new();
|
||||||
if let Err(e) = buf_reader.read_to_end(&mut contents) {
|
buf_reader.read_to_end(&mut contents)?;
|
||||||
debug!(e);
|
let (_, headers) = parser::headers::headers_raw(contents.as_slice())?;
|
||||||
return flags;
|
if let Some(start) = headers.find(b"Status:") {
|
||||||
};
|
if let Some(end) = headers[start..].find(b"\n") {
|
||||||
|
let start = start + b"Status:".len();
|
||||||
if let Ok((_, headers)) = parser::headers::headers_raw(contents.as_slice()) {
|
let status = headers[start..start + end].trim();
|
||||||
if let Some(start) = headers.find(b"Status:") {
|
if status.contains(&b'F') {
|
||||||
if let Some(end) = headers[start..].find(b"\n") {
|
flags.set(Flag::FLAGGED, true);
|
||||||
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 status.contains(&b'A') {
|
||||||
if let Some(start) = headers.find(b"X-Status:") {
|
flags.set(Flag::REPLIED, true);
|
||||||
let start = start + b"X-Status:".len();
|
}
|
||||||
if let Some(end) = headers[start..].find(b"\n") {
|
if status.contains(&b'R') {
|
||||||
let status = headers[start..start + end].trim();
|
flags.set(Flag::SEEN, true);
|
||||||
if status.contains(&b'F') {
|
}
|
||||||
flags.set(Flag::FLAGGED, true);
|
if status.contains(&b'D') {
|
||||||
}
|
flags.set(Flag::TRASHED, true);
|
||||||
if status.contains(&b'A') {
|
}
|
||||||
flags.set(Flag::REPLIED, true);
|
if status.contains(&b'T') {
|
||||||
}
|
flags.set(Flag::DRAFT, 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<()> {
|
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."))
|
Err(MeliError::new("Unimplemented."))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn::std::any::Any {
|
fn as_any(&self) -> &dyn ::std::any::Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -624,7 +624,7 @@ impl MailBackend for NotmuchDb {
|
||||||
crate::backends::MaildirType::save_to_mailbox(path, bytes, flags)
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,7 +667,7 @@ impl BackendOp for NotmuchOp {
|
||||||
Ok(self.bytes.as_ref().unwrap().as_bytes())
|
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 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 {
|
||||||
|
@ -678,11 +678,11 @@ impl BackendOp for NotmuchOp {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let (flags, _tags) = TagIterator::new(self.lib.clone(), message).collect_flags_and_tags();
|
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<()> {
|
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);
|
flags.set(f, value);
|
||||||
envelope.set_flags(flags);
|
envelope.set_flags(flags);
|
||||||
let mut message: *mut notmuch_message_t = std::ptr::null_mut();
|
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> {
|
pub fn from_token(mut operation: Box<dyn BackendOp>, hash: EnvelopeHash) -> Option<Envelope> {
|
||||||
let mut e = Envelope::new(hash);
|
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() {
|
if let Ok(bytes) = operation.as_bytes() {
|
||||||
let res = e.populate_headers(bytes).ok();
|
let res = e.populate_headers(bytes).ok();
|
||||||
if res.is_some() {
|
if res.is_some() {
|
||||||
|
|
|
@ -225,7 +225,7 @@ impl MailBackend for PluginBackend {
|
||||||
fn tags(&self) -> Option<Arc<RwLock<BTreeMap<u64, String>>>> {
|
fn tags(&self) -> Option<Arc<RwLock<BTreeMap<u64, String>>>> {
|
||||||
self.tag_index.clone()
|
self.tag_index.clone()
|
||||||
}
|
}
|
||||||
fn as_any(&self) -> &dyn::std::any::Any {
|
fn as_any(&self) -> &dyn ::std::any::Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,10 +314,8 @@ impl BackendOp for PluginOp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_flags(&self) -> Flag {
|
fn fetch_flags(&self) -> Result<Flag> {
|
||||||
let flag = Flag::default();
|
Err(MeliError::new("Unimplemented."))
|
||||||
|
|
||||||
flag
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_flag(&mut self, __envelope: &mut Envelope, _f: Flag, _value: bool) -> Result<()> {
|
fn set_flag(&mut self, __envelope: &mut Envelope, _f: Flag, _value: bool) -> Result<()> {
|
||||||
|
|
Loading…
Reference in New Issue