jmap: imports cleanup in all modules

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
pull/405/head
Manos Pitsidianakis 4 months ago
parent dce3852fe5
commit 7ba7dc70c5
No known key found for this signature in database
GPG Key ID: 7729C7707F7E09D0

@ -19,13 +19,39 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use std::convert::TryFrom;
use isahc::config::Configurable;
use super::*;
use crate::error::NetworkErrorKind;
use crate::jmap::{protocol::JmapMailCapability, rfc8620::capabilities::*};
use std::{convert::TryFrom, sync::Arc, time::Instant};
use futures::lock::{MappedMutexGuard as FutureMappedMutexGuard, Mutex as FutureMutex};
use isahc::{
config::{Configurable, RedirectPolicy},
AsyncReadResponseExt, HttpClient,
};
use smallvec::SmallVec;
use url::Url;
use crate::{
error::{Error, NetworkErrorKind, Result},
jmap::{
deserialize_from_str,
objects::{
email::{
EmailChanges, EmailFilterCondition, EmailGet, EmailObject, EmailQueryChanges,
EmailQueryChangesResponse,
},
identity::{IdentityGet, IdentityObject, IdentitySet},
mailbox::MailboxObject,
},
protocol::{self, JmapMailCapability, Request},
rfc8620::{
argument::Argument, capabilities::*, filters::Filter, AddedItem, Changes,
ChangesResponse, Get, GetResponse, Id, MethodResponse, QueryChanges,
QueryChangesResponse, ResultField, Set, State,
},
session::Session,
JmapServerConf, Store,
},
BackendEvent, Flag, MailboxHash, RefreshEvent, RefreshEventKind,
};
#[derive(Debug)]
pub struct JmapConnection {

@ -21,8 +21,18 @@
use std::sync::{Arc, Mutex, RwLock};
use super::*;
use crate::backends::{LazyCountSet, MailboxPermissions, SpecialUsageMailbox};
use crate::{
backends::{BackendMailbox, LazyCountSet, MailboxPermissions, SpecialUsageMailbox},
error::Result,
jmap::{
objects::{
email::EmailObject,
mailbox::{JmapRights, MailboxObject},
},
rfc8620::{Id, State},
},
Mailbox, MailboxHash,
};
#[derive(Clone, Debug)]
pub struct JmapMailbox {

@ -23,7 +23,7 @@
#![deny(unused_must_use)]
use std::{
collections::{BTreeSet, HashMap, HashSet},
collections::{HashMap, HashSet},
convert::TryFrom,
pin::Pin,
str::FromStr,
@ -39,7 +39,7 @@ use futures::{
Stream,
};
use indexmap::{IndexMap, IndexSet};
use isahc::{config::RedirectPolicy, AsyncReadResponseExt, HttpClient};
use isahc::AsyncReadResponseExt;
use serde_json::{json, Value};
use smallvec::SmallVec;
use url::Url;
@ -89,13 +89,15 @@ pub mod session;
use session::*;
pub mod rfc8620;
use rfc8620::*;
pub mod objects;
use objects::*;
use rfc8620::{
argument::Argument, capabilities::JmapCoreCapability, download_request_format, filters::Filter,
upload_request_format, BlobObject, Get, GetResponse, Id, MethodResponse, Object, Query,
QueryResponse, Set, SetResponse, State, UploadResponse,
};
pub mod mailbox;
use mailbox::*;
pub mod objects;
use mailbox::JmapMailbox;
pub fn deserialize_from_str<'de, T: serde::de::Deserialize<'de>>(s: &'de str) -> Result<T> {
let jd = &mut serde_json::Deserializer::from_str(s);
@ -256,13 +258,13 @@ pub struct Store {
pub main_identity: String,
pub extra_identities: Vec<String>,
pub byte_cache: Arc<FutureMutex<HashMap<EnvelopeHash, EnvelopeCache>>>,
pub id_store: Arc<FutureMutex<HashMap<EnvelopeHash, Id<EmailObject>>>>,
pub reverse_id_store: Arc<FutureMutex<HashMap<Id<EmailObject>, EnvelopeHash>>>,
pub id_store: Arc<FutureMutex<HashMap<EnvelopeHash, Id<objects::email::EmailObject>>>>,
pub reverse_id_store: Arc<FutureMutex<HashMap<Id<objects::email::EmailObject>, EnvelopeHash>>>,
pub blob_id_store: Arc<FutureMutex<HashMap<EnvelopeHash, Id<BlobObject>>>>,
pub collection: Collection,
pub mailboxes: Arc<RwLock<HashMap<MailboxHash, JmapMailbox>>>,
pub mailboxes_index: Arc<RwLock<HashMap<MailboxHash, HashSet<EnvelopeHash>>>>,
pub mailbox_state: Arc<FutureMutex<State<MailboxObject>>>,
pub mailbox_state: Arc<FutureMutex<State<objects::mailbox::MailboxObject>>>,
pub online_status: OnlineStatus,
pub is_subscribed: Arc<IsSubscribedFn>,
pub core_capabilities: Arc<Mutex<IndexMap<String, CapabilitiesObject>>>,
@ -270,7 +272,7 @@ pub struct Store {
}
impl Store {
pub async fn add_envelope(&self, obj: EmailObject) -> Envelope {
pub async fn add_envelope(&self, obj: objects::email::EmailObject) -> Envelope {
let mut flags = Flag::default();
let mut labels: IndexSet<TagHash> = IndexSet::new();
let id;
@ -331,7 +333,7 @@ impl Store {
pub async fn remove_envelope(
&self,
obj_id: Id<EmailObject>,
obj_id: Id<objects::email::EmailObject>,
) -> Option<(EnvelopeHash, SmallVec<[MailboxHash; 8]>)> {
let env_hash = self.reverse_id_store.lock().await.remove(&obj_id)?;
self.id_store.lock().await.remove(&env_hash);
@ -513,7 +515,7 @@ impl MailBackend for JmapType {
)
.await?;
let mailbox_id: Id<MailboxObject> = {
let mailbox_id: Id<objects::mailbox::MailboxObject> = {
let mailboxes_lck = store.mailboxes.read().unwrap();
if let Some(mailbox) = mailboxes_lck.get(&mailbox_hash) {
mailbox.id.clone()
@ -534,18 +536,17 @@ impl MailBackend for JmapType {
Ok(s) => s,
};
let mut req = Request::new(conn.request_no.clone());
let creation_id: Id<EmailObject> = "1".to_string().into();
let import_call: EmailImport =
EmailImport::new()
.account_id(mail_account_id)
.emails(indexmap! {
creation_id.clone() => EmailImportObject::new()
.blob_id(upload_response.blob_id)
.mailbox_ids(indexmap! {
mailbox_id => true
})
});
let creation_id: Id<objects::email::EmailObject> = "1".to_string().into();
let import_call: objects::email::EmailImport = objects::email::EmailImport::new()
.account_id(mail_account_id)
.emails(indexmap! {
creation_id.clone() => objects::email::EmailImportObject::new()
.blob_id(upload_response.blob_id)
.mailbox_ids(indexmap! {
mailbox_id => true
})
});
req.add_call(&import_call).await;
let mut res = conn.post_async(None, serde_json::to_string(&req)?).await?;
@ -558,14 +559,16 @@ impl MailBackend for JmapType {
}
Ok(s) => s,
};
let m = EmailImportResponse::try_from(v.method_responses.remove(0)).map_err(|err| {
let ierr: Result<EmailImportError> = deserialize_from_str(&res_text);
if let Ok(err) = ierr {
Error::new(format!("Could not save message: {:?}", err))
} else {
err
}
})?;
let m = objects::email::EmailImportResponse::try_from(v.method_responses.remove(0))
.map_err(|err| {
let ierr: Result<objects::email::EmailImportError> =
deserialize_from_str(&res_text);
if let Ok(err) = ierr {
Error::new(format!("Could not save message: {:?}", err))
} else {
err
}
})?;
if let Some(err) = m.not_created.and_then(|m| m.get(&creation_id).cloned()) {
return Err(Error::new(format!("Could not save message: {:?}", err)));
@ -599,21 +602,23 @@ impl MailBackend for JmapType {
.clone();
let mut f = Filter::Condition(
EmailFilterCondition::new()
objects::email::EmailFilterCondition::new()
.in_mailbox(Some(mailbox_id))
.into(),
);
f &= Filter::<EmailFilterCondition, EmailObject>::from(q);
f &= Filter::<objects::email::EmailFilterCondition, objects::email::EmailObject>::from(
q,
);
f
} else {
Filter::<EmailFilterCondition, EmailObject>::from(q)
Filter::<objects::email::EmailFilterCondition, objects::email::EmailObject>::from(q)
};
Ok(Box::pin(async move {
let mut conn = connection.lock().await;
conn.connect().await?;
let mail_account_id = conn.session_guard().await?.mail_account_id();
let email_call: EmailQuery = EmailQuery::new(
let email_call = objects::email::EmailQuery::new(
Query::new()
.account_id(mail_account_id)
.filter(Some(filter))
@ -635,8 +640,10 @@ impl MailBackend for JmapType {
Ok(s) => s,
};
store.online_status.update_timestamp(None).await;
let m = QueryResponse::<EmailObject>::try_from(v.method_responses.remove(0))?;
let QueryResponse::<EmailObject> { ids, .. } = m;
let m = QueryResponse::<objects::email::EmailObject>::try_from(
v.method_responses.remove(0),
)?;
let QueryResponse::<objects::email::EmailObject> { ids, .. } = m;
let ret = ids.into_iter().map(|id| id.into_hash()).collect();
Ok(ret)
}))
@ -661,16 +668,16 @@ impl MailBackend for JmapType {
Ok(Box::pin(async move {
let mut conn = connection.lock().await;
let mail_account_id = conn.session_guard().await?.mail_account_id();
let mailbox_set_call: MailboxSet = MailboxSet::new(
Set::<MailboxObject>::new()
let mailbox_set_call = objects::mailbox::MailboxSet::new(
Set::<objects::mailbox::MailboxObject>::new()
.account_id(mail_account_id)
.create(Some({
let id: Id<MailboxObject> = path.as_str().into();
let id: Id<objects::mailbox::MailboxObject> = path.as_str().into();
indexmap! {
id.clone().into() => MailboxObject {
id.clone().into() => objects::mailbox::MailboxObject {
id,
name: path.clone(),
..MailboxObject::default()
..objects::mailbox::MailboxObject::default()
}
}
})),
@ -758,7 +765,8 @@ impl MailBackend for JmapType {
mailboxes_lck[&destination_mailbox_hash].id.clone(),
)
};
let mut update_map: IndexMap<Argument<Id<EmailObject>>, Value> = IndexMap::default();
let mut update_map: IndexMap<Argument<Id<objects::email::EmailObject>>, Value> =
IndexMap::default();
let mut update_keywords: IndexMap<String, Value> = IndexMap::default();
update_keywords.insert(
format!("mailboxIds/{}", &destination_mailbox_id),
@ -785,8 +793,8 @@ impl MailBackend for JmapType {
let conn = connection.lock().await;
let mail_account_id = conn.session_guard().await?.mail_account_id();
let email_set_call: EmailSet = EmailSet::new(
Set::<EmailObject>::new()
let email_set_call = objects::email::EmailSet::new(
Set::<objects::email::EmailObject>::new()
.account_id(mail_account_id)
.update(Some(update_map)),
);
@ -806,7 +814,8 @@ impl MailBackend for JmapType {
Ok(s) => s,
};
store.online_status.update_timestamp(None).await;
let m = SetResponse::<EmailObject>::try_from(v.method_responses.remove(0))?;
let m =
SetResponse::<objects::email::EmailObject>::try_from(v.method_responses.remove(0))?;
if let Some(ids) = m.not_updated {
if !ids.is_empty() {
return Err(Error::new(format!(
@ -831,9 +840,12 @@ impl MailBackend for JmapType {
let store = self.store.clone();
let connection = self.connection.clone();
Ok(Box::pin(async move {
let mut update_map: IndexMap<Argument<Id<EmailObject>>, Value> = IndexMap::default();
let mut ids: Vec<Id<EmailObject>> = Vec::with_capacity(env_hashes.rest.len() + 1);
let mut id_map: IndexMap<Id<EmailObject>, EnvelopeHash> = IndexMap::default();
let mut update_map: IndexMap<Argument<Id<objects::email::EmailObject>>, Value> =
IndexMap::default();
let mut ids: Vec<Id<objects::email::EmailObject>> =
Vec::with_capacity(env_hashes.rest.len() + 1);
let mut id_map: IndexMap<Id<objects::email::EmailObject>, EnvelopeHash> =
IndexMap::default();
let mut update_keywords: IndexMap<String, Value> = IndexMap::default();
for op in flags.iter() {
match op {
@ -894,15 +906,15 @@ impl MailBackend for JmapType {
let conn = connection.lock().await;
let mail_account_id = conn.session_guard().await?.mail_account_id();
let email_set_call: EmailSet = EmailSet::new(
Set::<EmailObject>::new()
let email_set_call = objects::email::EmailSet::new(
Set::<objects::email::EmailObject>::new()
.account_id(mail_account_id.clone())
.update(Some(update_map)),
);
let mut req = Request::new(conn.request_no.clone());
req.add_call(&email_set_call).await;
let email_call: EmailGet = EmailGet::new(
let email_call = objects::email::EmailGet::new(
Get::new()
.ids(Some(Argument::Value(ids)))
.account_id(mail_account_id)
@ -930,7 +942,8 @@ impl MailBackend for JmapType {
Ok(s) => s,
};
store.online_status.update_timestamp(None).await;
let m = SetResponse::<EmailObject>::try_from(v.method_responses.remove(0))?;
let m =
SetResponse::<objects::email::EmailObject>::try_from(v.method_responses.remove(0))?;
if let Some(ids) = m.not_updated {
return Err(Error::new(
ids.into_iter()
@ -949,8 +962,10 @@ impl MailBackend for JmapType {
}
drop(tag_index_lck);
}
let e = GetResponse::<EmailObject>::try_from(v.method_responses.pop().unwrap())?;
let GetResponse::<EmailObject> { list, state, .. } = e;
let e = GetResponse::<objects::email::EmailObject>::try_from(
v.method_responses.pop().unwrap(),
)?;
let GetResponse::<objects::email::EmailObject> { list, state, .. } = e;
{
let (is_empty, is_equal) = {
let mailboxes_lck = conn.store.mailboxes.read().unwrap();
@ -967,7 +982,11 @@ impl MailBackend for JmapType {
};
if is_empty {
let mut mailboxes_lck = conn.store.mailboxes.write().unwrap();
debug!("{:?}: inserting state {}", EmailObject::NAME, &state);
debug!(
"{:?}: inserting state {}",
objects::email::EmailObject::NAME,
&state
);
mailboxes_lck.entry(mailbox_hash).and_modify(|mbox| {
*mbox.email_state.lock().unwrap() = Some(state);
});
@ -1019,30 +1038,31 @@ impl MailBackend for JmapType {
// "$draft" flag and moves it from the Drafts folder to the Sent folder.
let (draft_mailbox_id, sent_mailbox_id) = {
let mailboxes_lck = store.mailboxes.read().unwrap();
let find_fn = |usage: SpecialUsageMailbox| -> Result<Id<MailboxObject>> {
if let Some(sent_folder) =
mailboxes_lck.values().find(|m| m.special_usage() == usage)
{
Ok(sent_folder.id.clone())
} else if let Some(sent_folder) = mailboxes_lck
.values()
.find(|m| m.special_usage() == SpecialUsageMailbox::Inbox)
{
Ok(sent_folder.id.clone())
} else {
Ok(mailboxes_lck
let find_fn =
|usage: SpecialUsageMailbox| -> Result<Id<objects::mailbox::MailboxObject>> {
if let Some(sent_folder) =
mailboxes_lck.values().find(|m| m.special_usage() == usage)
{
Ok(sent_folder.id.clone())
} else if let Some(sent_folder) = mailboxes_lck
.values()
.next()
.ok_or_else(|| {
Error::new(format!(
"Account `{}` has no mailboxes.",
store.account_name
))
})?
.id
.clone())
}
};
.find(|m| m.special_usage() == SpecialUsageMailbox::Inbox)
{
Ok(sent_folder.id.clone())
} else {
Ok(mailboxes_lck
.values()
.next()
.ok_or_else(|| {
Error::new(format!(
"Account `{}` has no mailboxes.",
store.account_name
))
})?
.id
.clone())
}
};
(find_fn(SpecialUsageMailbox::Drafts)?, {
if let Some(h) = mailbox_hash {
@ -1085,11 +1105,11 @@ impl MailBackend for JmapType {
};
{
let mut req = Request::new(conn.request_no.clone());
let creation_id: Id<EmailObject> = "newid".into();
let import_call: EmailImport = EmailImport::new()
let creation_id: Id<objects::email::EmailObject> = "newid".into();
let import_call: objects::email::EmailImport = objects::email::EmailImport::new()
.account_id(mail_account_id.clone())
.emails(indexmap! {
creation_id => EmailImportObject::new()
creation_id => objects::email::EmailImportObject::new()
.blob_id(upload_response.blob_id)
.keywords(indexmap! {
"$draft".to_string() => true,
@ -1125,11 +1145,11 @@ impl MailBackend for JmapType {
);
let mut req = Request::new(conn.request_no.clone());
let subm_set_call: EmailSubmissionSet = EmailSubmissionSet::new(
Set::<EmailSubmissionObject>::new()
let subm_set_call = objects::submission::EmailSubmissionSet::new(
Set::<objects::submission::EmailSubmissionObject>::new()
.account_id(mail_account_id.clone())
.create(Some(indexmap! {
Argument::from(Id::from("k1490")) => EmailSubmissionObject::new(
Argument::from(Id::from("k1490")) => objects::submission::EmailSubmissionObject::new(
/* account_id: */ mail_account_id,
/* identity_id: */ identity_id,
/* email_id: */ email_id,

@ -19,22 +19,11 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use super::*;
mod email;
pub use email::*;
mod mailbox;
pub use mailbox::*;
mod thread;
pub use thread::*;
mod identity;
pub use identity::*;
mod submission;
pub use submission::*;
pub mod email;
pub mod identity;
pub mod mailbox;
pub mod submission;
pub mod thread;
#[cfg(test)]
mod tests;

@ -24,12 +24,24 @@ use std::marker::PhantomData;
use indexmap::IndexMap;
use serde::de::{Deserialize, Deserializer};
use serde_json::{value::RawValue, Value};
use smallvec::SmallVec;
use super::*;
use crate::{
email::address::{Address, MailboxAddress},
jmap::rfc8620::bool_false,
jmap::{
deserialize_from_str,
objects::{mailbox::MailboxObject, thread::ThreadObject},
protocol::Method,
rfc8620::{
bool_false,
filters::{Filter, FilterCondition, FilterTrait},
u64_zero, BlobObject, Changes, Get, Id, Object, Query, QueryChanges,
QueryChangesResponse, ResultField, Set,
},
UtcDate,
},
utils::datetime,
EnvelopeHash, StrBuilder,
};
mod import;

@ -22,9 +22,17 @@
use indexmap::IndexMap;
use serde_json::value::RawValue;
use super::*;
use crate::{
error::Result,
jmap::{
deserialize_from_str,
objects::{email::EmailObject, mailbox::MailboxObject, thread::ThreadObject},
protocol::Method,
rfc8620::{Account, BlobObject, Id, State},
},
};
/// #`import`
/// # `import`
///
/// Objects of type `Foo` are imported via a call to `Foo/import`.
///

@ -19,7 +19,11 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use super::*;
use crate::jmap::{
objects::email::EmailAddress,
protocol::Method,
rfc8620::{Changes, Get, Id, Object, Set},
};
/// # Identity
///

@ -19,7 +19,13 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use super::*;
use crate::{
jmap::{
protocol::Method,
rfc8620::{Get, Id, Object, Set},
},
MailboxHash,
};
impl Id<MailboxObject> {
pub fn into_hash(&self) -> MailboxHash {

@ -21,8 +21,13 @@
use indexmap::IndexMap;
use serde::ser::{Serialize, SerializeStruct, Serializer};
use serde_json::Value;
use super::*;
use crate::jmap::{
objects::{email::EmailObject, identity::IdentityObject, thread::ThreadObject},
protocol::Method,
rfc8620::{argument::Argument, Account, BlobObject, Id, Object, PatchObject, Set},
};
/// `UndoStatus`
///

@ -20,12 +20,17 @@
//
// SPDX-License-Identifier: EUPL-1.2 OR GPL-3.0-or-later
use serde_json::json;
use super::*;
#[test]
fn test_jmap_query() {
use std::sync::Arc;
use futures::lock::Mutex as FutureMutex;
use crate::jmap::{
objects::email::{EmailFilterCondition, EmailObject, EmailQuery},
protocol::Request,
rfc8620::{filters::Filter, Query},
};
let q: crate::search::Query = crate::search::Query::try_from(
"subject:wah or (from:Manos and (subject:foo or subject:bar))",
)
@ -68,6 +73,16 @@ fn test_jmap_query() {
#[test]
fn test_jmap_undo_status() {
use serde_json::json;
use crate::jmap::{
objects::{
email::EmailObject,
identity::IdentityObject,
submission::{EmailSubmissionObject, UndoStatus},
},
rfc8620::{Account, Id},
};
let account_id: Id<Account> = "blahblah".into();
let ident_id: Id<IdentityObject> = "sdusssssss".into();
let email_id: Id<EmailObject> = Id::from("683f9246-56d4-4d7d-bd0c-3d4de6db7cbf");
@ -123,6 +138,16 @@ fn test_jmap_undo_status() {
#[test]
fn test_jmap_email_submission_object() {
use serde_json::json;
use crate::jmap::{
objects::{
email::{EmailImport, EmailObject},
identity::IdentityObject,
submission::{EmailSubmissionObject, UndoStatus},
},
rfc8620::{argument::Argument, Account, Id, ResultField},
};
let account_id: Id<Account> = "blahblah".into();
let ident_id: Id<IdentityObject> = "sdusssssss".into();
let email_id: Id<EmailObject> = Id::from("683f9246-56d4-4d7d-bd0c-3d4de6db7cbf");
@ -173,6 +198,16 @@ fn test_jmap_email_submission_object() {
#[test]
fn test_jmap_identity_methods() {
use std::sync::Arc;
use futures::lock::Mutex as FutureMutex;
use serde_json::json;
use crate::jmap::{
objects::identity::{IdentityGet, IdentityObject, IdentitySet},
protocol::Request,
rfc8620::{Id, Set},
};
let account_id = "blahblah";
let prev_seq = 33;
let main_identity = "user@example.com";

@ -21,7 +21,11 @@
use std::marker::PhantomData;
use super::*;
use crate::jmap::{
objects::email::{EmailGet, EmailObject},
protocol::Method,
rfc8620::{Changes, Get, Id, Object, ResultField},
};
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]

@ -21,9 +21,15 @@
use std::sync::Arc;
use super::*;
use futures::lock::Mutex as FutureMutex;
use isahc::AsyncReadResponseExt;
/// `BackendOp` implementor for Imap
use crate::{
jmap::{connection::JmapConnection, download_request_format, Store},
BackendOp, EnvelopeHash, ResultFuture,
};
/// `BackendOp` implementor for JMAP
#[derive(Clone, Debug)]
pub struct JmapOp {
hash: EnvelopeHash,

@ -19,16 +19,36 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use crate::jmap::{
mailbox::JmapMailbox,
rfc8620::{capabilities::*, Object, State},
*,
use std::{
collections::{BTreeSet, HashMap},
convert::{TryFrom, TryInto},
sync::{Arc, Mutex},
};
use std::convert::{TryFrom, TryInto};
use futures::lock::Mutex as FutureMutex;
use isahc::AsyncReadResponseExt;
use serde::Serialize;
use serde_json::Value;
use smallvec::SmallVec;
use crate::{
email::Envelope,
error::Result,
jmap::{
deserialize_from_str,
mailbox::JmapMailbox,
objects::{
email::{EmailFilterCondition, EmailGet, EmailObject, EmailQuery},
mailbox::{MailboxGet, MailboxObject},
},
rfc8620::{
argument::Argument, capabilities::*, filters::Filter, Get, GetResponse, Id,
MethodResponse, Object, Query, QueryResponse, State,
},
JmapConnection, Store,
},
Flag, LazyCountSet, MailboxHash,
};
pub type UtcDate = String;

@ -39,12 +39,12 @@ use crate::{
jmap::{deserialize_from_str, protocol::Method, session::Session},
};
mod filters;
pub use filters::*;
mod comparator;
pub use comparator::*;
mod argument;
pub use argument::*;
pub mod argument;
pub mod comparator;
pub mod filters;
use argument::Argument;
use comparator::Comparator;
#[cfg(test)]
mod tests;
@ -448,7 +448,7 @@ enum JmapError {
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Query<F: FilterTrait<OBJ>, OBJ>
pub struct Query<F: filters::FilterTrait<OBJ>, OBJ>
where
OBJ: Object + std::fmt::Debug + Serialize,
{
@ -470,7 +470,7 @@ where
_ph: PhantomData<fn() -> OBJ>,
}
impl<F: FilterTrait<OBJ>, OBJ> Query<F, OBJ>
impl<F: filters::FilterTrait<OBJ>, OBJ> Query<F, OBJ>
where
OBJ: Object + std::fmt::Debug + Serialize,
{
@ -498,7 +498,7 @@ where
_impl!(calculate_total: bool);
}
impl<F: FilterTrait<OBJ>, OBJ> Default for Query<F, OBJ>
impl<F: filters::FilterTrait<OBJ>, OBJ> Default for Query<F, OBJ>
where
OBJ: Object + std::fmt::Debug + Serialize,
{
@ -1141,7 +1141,7 @@ pub struct UploadResponse {
/// takes the following arguments:
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct QueryChanges<F: FilterTrait<OBJ>, OBJ>
pub struct QueryChanges<F: filters::FilterTrait<OBJ>, OBJ>
where
OBJ: Object + std::fmt::Debug + Serialize,
{
@ -1185,7 +1185,7 @@ where
_ph: PhantomData<fn() -> OBJ>,
}
impl<F: FilterTrait<OBJ>, OBJ> QueryChanges<F, OBJ>
impl<F: filters::FilterTrait<OBJ>, OBJ> QueryChanges<F, OBJ>
where
OBJ: Object + std::fmt::Debug + Serialize,
{

@ -19,7 +19,9 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use super::*;
use std::marker::PhantomData;
use crate::jmap::rfc8620::Object;
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]

@ -19,7 +19,9 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use super::*;
use std::marker::PhantomData;
use crate::jmap::rfc8620::Object;
pub trait FilterTrait<T>: Default + Send + Sync {}

@ -22,9 +22,18 @@
use std::sync::Arc;
use futures::lock::Mutex as FutureMutex;
use serde_json::json;
use crate::jmap::*;
use crate::jmap::{
objects::{
email::{EmailImport, EmailImportObject, EmailObject},
mailbox::MailboxObject,
submission::{EmailSubmissionObject, EmailSubmissionSet},
},
protocol::Request,
rfc8620::{argument::Argument, BlobObject, Id, ResultField, Set},
};
#[test]
fn test_jmap_argument_serde() {

@ -26,9 +26,9 @@ use serde_json::Value;
use url::Url;
use crate::jmap::{
objects::identity::IdentityObject,
protocol::JmapMailCapability,
rfc8620::{Account, Id, Object, State},
IdentityObject,
};
#[derive(Clone, Debug, Deserialize, Serialize)]

Loading…
Cancel
Save