Initial commit.
parent
41eac1224c
commit
1680fdcd30
|
@ -0,0 +1,24 @@
|
||||||
|
[package]
|
||||||
|
name = "jmap-client"
|
||||||
|
description = "JMAP client library for Rust"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
authors = [ "Stalwart Labs Ltd. <hello@stalw.art>"]
|
||||||
|
license = "Apache-2.0 OR MIT"
|
||||||
|
repository = "https://github.com/stalwartlabs/jmap-client"
|
||||||
|
homepage = "https://github.com/stalwartlabs/jmap-client"
|
||||||
|
keywords = ["jmap", "email", "mime", "mail", "e-mail"]
|
||||||
|
categories = ["email"]
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { version = "1.0", features = ["derive"]}
|
||||||
|
serde_json = "1.0"
|
||||||
|
chrono = { version = "0.4", features = ["serde"]}
|
||||||
|
reqwest = "0.11"
|
||||||
|
ece = "2.2"
|
||||||
|
|
||||||
|
#[dev-dependencies]
|
||||||
|
|
||||||
|
[profile.bench]
|
||||||
|
debug = true
|
|
@ -0,0 +1,27 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::core::set::SetError;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct CopyBlobRequest {
|
||||||
|
#[serde(rename = "fromAccountId")]
|
||||||
|
from_account_id: String,
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
#[serde(rename = "blobIds")]
|
||||||
|
blob_ids: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct CopyBlobResponse<U> {
|
||||||
|
#[serde(rename = "fromAccountId")]
|
||||||
|
from_account_id: String,
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
#[serde(rename = "copied")]
|
||||||
|
copied: Option<HashMap<String, String>>,
|
||||||
|
#[serde(rename = "notCopied")]
|
||||||
|
not_copied: Option<HashMap<String, SetError<U>>>,
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod copy;
|
|
@ -0,0 +1,26 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct ChangesRequest {
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
#[serde(rename = "sinceState")]
|
||||||
|
since_state: String,
|
||||||
|
#[serde(rename = "maxChanges")]
|
||||||
|
max_changes: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct ChangesResponse {
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
#[serde(rename = "oldState")]
|
||||||
|
old_state: String,
|
||||||
|
#[serde(rename = "newState")]
|
||||||
|
new_state: String,
|
||||||
|
#[serde(rename = "hasMoreChanges")]
|
||||||
|
has_more_changes: bool,
|
||||||
|
created: Vec<String>,
|
||||||
|
updated: Vec<String>,
|
||||||
|
destroyed: Vec<String>,
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::set::SetError;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct CopyRequest<T> {
|
||||||
|
#[serde(rename = "fromAccountId")]
|
||||||
|
from_account_id: String,
|
||||||
|
#[serde(rename = "ifFromInState")]
|
||||||
|
if_from_in_state: Option<String>,
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
#[serde(rename = "ifInState")]
|
||||||
|
if_in_state: Option<String>,
|
||||||
|
#[serde(rename = "create")]
|
||||||
|
create: HashMap<String, T>,
|
||||||
|
#[serde(rename = "onSuccessDestroyOriginal")]
|
||||||
|
on_success_destroy_original: bool,
|
||||||
|
#[serde(rename = "destroyFromIfInState")]
|
||||||
|
destroy_from_if_in_state: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct CopyResponse<T, U> {
|
||||||
|
#[serde(rename = "fromAccountId")]
|
||||||
|
from_account_id: String,
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
#[serde(rename = "oldState")]
|
||||||
|
old_state: Option<String>,
|
||||||
|
#[serde(rename = "newState")]
|
||||||
|
new_state: String,
|
||||||
|
#[serde(rename = "created")]
|
||||||
|
created: Option<HashMap<String, T>>,
|
||||||
|
#[serde(rename = "notCreated")]
|
||||||
|
not_created: Option<HashMap<String, SetError<U>>>,
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct ProblemDetails {
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
p_type: ProblemType,
|
||||||
|
status: Option<u32>,
|
||||||
|
title: Option<String>,
|
||||||
|
detail: Option<String>,
|
||||||
|
limit: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub enum ProblemType {
|
||||||
|
#[serde(rename = "urn:ietf:params:jmap:error:unknownCapability")]
|
||||||
|
UnknownCapability,
|
||||||
|
#[serde(rename = "urn:ietf:params:jmap:error:notJSON")]
|
||||||
|
NotJSON,
|
||||||
|
#[serde(rename = "urn:ietf:params:jmap:error:notRequest")]
|
||||||
|
NotRequest,
|
||||||
|
#[serde(rename = "urn:ietf:params:jmap:error:limit")]
|
||||||
|
Limit,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct MethodError {
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
p_type: MethodErrorType,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub enum MethodErrorType {
|
||||||
|
#[serde(rename = "serverUnavailable")]
|
||||||
|
ServerUnavailable,
|
||||||
|
#[serde(rename = "serverFail")]
|
||||||
|
ServerFail,
|
||||||
|
#[serde(rename = "serverPartialFail")]
|
||||||
|
ServerPartialFail,
|
||||||
|
#[serde(rename = "unknownMethod")]
|
||||||
|
UnknownMethod,
|
||||||
|
#[serde(rename = "invalidArguments")]
|
||||||
|
InvalidArguments,
|
||||||
|
#[serde(rename = "invalidResultReference")]
|
||||||
|
InvalidResultReference,
|
||||||
|
#[serde(rename = "forbidden")]
|
||||||
|
Forbidden,
|
||||||
|
#[serde(rename = "accountNotFound")]
|
||||||
|
AccountNotFound,
|
||||||
|
#[serde(rename = "accountNotSupportedByMethod")]
|
||||||
|
AccountNotSupportedByMethod,
|
||||||
|
#[serde(rename = "accountReadOnly")]
|
||||||
|
AccountReadOnly,
|
||||||
|
#[serde(rename = "requestTooLarge")]
|
||||||
|
RequestTooLarge,
|
||||||
|
#[serde(rename = "cannotCalculateChanges")]
|
||||||
|
CannotCalculateChanges,
|
||||||
|
#[serde(rename = "stateMismatch")]
|
||||||
|
StateMismatch,
|
||||||
|
#[serde(rename = "alreadyExists")]
|
||||||
|
AlreadyExists,
|
||||||
|
#[serde(rename = "fromAccountNotFound")]
|
||||||
|
FromAccountNotFound,
|
||||||
|
#[serde(rename = "fromAccountNotSupportedByMethod")]
|
||||||
|
FromAccountNotSupportedByMethod,
|
||||||
|
#[serde(rename = "anchorNotFound")]
|
||||||
|
AnchorNotFound,
|
||||||
|
#[serde(rename = "unsupportedSort")]
|
||||||
|
UnsupportedSort,
|
||||||
|
#[serde(rename = "unsupportedFilter")]
|
||||||
|
UnsupportedFilter,
|
||||||
|
#[serde(rename = "tooManyChanges")]
|
||||||
|
TooManyChanges,
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct GetRequest<T> {
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
ids: Option<Vec<String>>,
|
||||||
|
properties: Option<Vec<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct GetResponse<T> {
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
state: String,
|
||||||
|
list: Vec<T>,
|
||||||
|
#[serde(rename = "notFound")]
|
||||||
|
not_found: Vec<String>,
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
pub mod changes;
|
||||||
|
pub mod copy;
|
||||||
|
pub mod error;
|
||||||
|
pub mod get;
|
||||||
|
pub mod query;
|
||||||
|
pub mod query_changes;
|
||||||
|
pub mod request;
|
||||||
|
pub mod response;
|
||||||
|
pub mod session;
|
||||||
|
pub mod set;
|
|
@ -0,0 +1,70 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct QueryRequest<T, U> {
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
#[serde(rename = "filter")]
|
||||||
|
filter: Option<Filter<T>>,
|
||||||
|
#[serde(rename = "sort")]
|
||||||
|
sort: Option<Vec<U>>,
|
||||||
|
#[serde(rename = "position")]
|
||||||
|
position: i32,
|
||||||
|
#[serde(rename = "anchor")]
|
||||||
|
anchor: Option<String>,
|
||||||
|
#[serde(rename = "anchorOffset")]
|
||||||
|
anchor_offset: i32,
|
||||||
|
#[serde(rename = "limit")]
|
||||||
|
limit: Option<usize>,
|
||||||
|
#[serde(rename = "calculateTotal")]
|
||||||
|
calculate_total: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Filter<T> {
|
||||||
|
FilterOperator(FilterOperator<T>),
|
||||||
|
FilterCondition(T),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct FilterOperator<T> {
|
||||||
|
operator: Operator,
|
||||||
|
conditions: Vec<Filter<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub enum Operator {
|
||||||
|
#[serde(rename = "AND")]
|
||||||
|
And,
|
||||||
|
#[serde(rename = "OR")]
|
||||||
|
Or,
|
||||||
|
#[serde(rename = "NOT")]
|
||||||
|
Not,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct Comparator<T> {
|
||||||
|
property: T,
|
||||||
|
#[serde(rename = "isAscending")]
|
||||||
|
is_ascending: bool,
|
||||||
|
collation: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct QueryResponse {
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
#[serde(rename = "queryState")]
|
||||||
|
query_state: String,
|
||||||
|
#[serde(rename = "canCalculateChanges")]
|
||||||
|
can_calculate_changes: bool,
|
||||||
|
#[serde(rename = "position")]
|
||||||
|
position: i32,
|
||||||
|
#[serde(rename = "ids")]
|
||||||
|
ids: Vec<String>,
|
||||||
|
#[serde(rename = "total")]
|
||||||
|
total: Option<usize>,
|
||||||
|
#[serde(rename = "limit")]
|
||||||
|
limit: Option<usize>,
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::query::Filter;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct QueryChangesRequest<T, U> {
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
#[serde(rename = "filter")]
|
||||||
|
filter: Option<Filter<T>>,
|
||||||
|
#[serde(rename = "sort")]
|
||||||
|
sort: Option<Vec<U>>,
|
||||||
|
#[serde(rename = "sinceQueryState")]
|
||||||
|
since_query_state: String,
|
||||||
|
#[serde(rename = "maxChanges")]
|
||||||
|
max_changes: Option<usize>,
|
||||||
|
#[serde(rename = "upToId")]
|
||||||
|
up_to_id: Option<String>,
|
||||||
|
#[serde(rename = "calculateTotal")]
|
||||||
|
calculate_total: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct QueryChangesResponse {
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
#[serde(rename = "oldQueryState")]
|
||||||
|
old_query_state: String,
|
||||||
|
#[serde(rename = "newQueryState")]
|
||||||
|
new_query_state: String,
|
||||||
|
#[serde(rename = "total")]
|
||||||
|
total: Option<usize>,
|
||||||
|
#[serde(rename = "removed")]
|
||||||
|
removed: Vec<String>,
|
||||||
|
#[serde(rename = "added")]
|
||||||
|
added: Vec<AddedItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct AddedItem {
|
||||||
|
id: String,
|
||||||
|
index: usize,
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::{Method, URI};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct Request {
|
||||||
|
using: Vec<URI>,
|
||||||
|
#[serde(rename = "methodCalls")]
|
||||||
|
method_calls: Vec<(Method, Arguments, String)>,
|
||||||
|
#[serde(rename = "createdIds")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
created_ids: Option<HashMap<String, String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct ResultReference {
|
||||||
|
#[serde(rename = "resultOf")]
|
||||||
|
result_of: String,
|
||||||
|
name: String,
|
||||||
|
path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct Arguments {}
|
|
@ -0,0 +1,18 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
use crate::Method;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct Request {
|
||||||
|
#[serde(rename = "methodResponses")]
|
||||||
|
method_calls: Vec<(Method, Result, String)>,
|
||||||
|
#[serde(rename = "createdIds")]
|
||||||
|
created_ids: Option<HashMap<String, String>>,
|
||||||
|
#[serde(rename = "sessionState")]
|
||||||
|
session_state: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct Result {}
|
|
@ -0,0 +1,94 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct Session {
|
||||||
|
#[serde(rename = "capabilities")]
|
||||||
|
capabilities: HashMap<String, Capabilities>,
|
||||||
|
#[serde(rename = "accounts")]
|
||||||
|
accounts: HashMap<String, Account>,
|
||||||
|
#[serde(rename = "primaryAccounts")]
|
||||||
|
primary_accounts: HashMap<String, String>,
|
||||||
|
#[serde(rename = "username")]
|
||||||
|
username: String,
|
||||||
|
#[serde(rename = "apiUrl")]
|
||||||
|
api_url: String,
|
||||||
|
#[serde(rename = "downloadUrl")]
|
||||||
|
download_url: String,
|
||||||
|
#[serde(rename = "uploadUrl")]
|
||||||
|
upload_url: String,
|
||||||
|
#[serde(rename = "eventSourceUrl")]
|
||||||
|
event_source_url: String,
|
||||||
|
#[serde(rename = "state")]
|
||||||
|
state: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct Account {
|
||||||
|
#[serde(rename = "name")]
|
||||||
|
name: String,
|
||||||
|
#[serde(rename = "isPersonal")]
|
||||||
|
is_personal: bool,
|
||||||
|
#[serde(rename = "isReadOnly")]
|
||||||
|
is_read_only: bool,
|
||||||
|
#[serde(rename = "accountCapabilities")]
|
||||||
|
account_capabilities: HashMap<String, Capabilities>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum Capabilities {
|
||||||
|
Core(CoreCapabilities),
|
||||||
|
Mail(MailCapabilities),
|
||||||
|
Submission(SubmissionCapabilities),
|
||||||
|
EmptyCapabilities(EmptyCapabilities),
|
||||||
|
Other(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct CoreCapabilities {
|
||||||
|
#[serde(rename = "maxSizeUpload")]
|
||||||
|
max_size_upload: usize,
|
||||||
|
#[serde(rename = "maxConcurrentUpload")]
|
||||||
|
max_concurrent_upload: usize,
|
||||||
|
#[serde(rename = "maxSizeRequest")]
|
||||||
|
max_size_request: usize,
|
||||||
|
#[serde(rename = "maxConcurrentRequests")]
|
||||||
|
max_concurrent_requests: usize,
|
||||||
|
#[serde(rename = "maxCallsInRequest")]
|
||||||
|
max_calls_in_request: usize,
|
||||||
|
#[serde(rename = "maxObjectsInGet")]
|
||||||
|
max_objects_in_get: usize,
|
||||||
|
#[serde(rename = "maxObjectsInSet")]
|
||||||
|
max_objects_in_set: usize,
|
||||||
|
#[serde(rename = "collationAlgorithms")]
|
||||||
|
collation_algorithms: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct MailCapabilities {
|
||||||
|
#[serde(rename = "maxMailboxesPerEmail")]
|
||||||
|
max_mailboxes_per_email: Option<usize>,
|
||||||
|
#[serde(rename = "maxMailboxDepth")]
|
||||||
|
max_mailbox_depth: usize,
|
||||||
|
#[serde(rename = "maxSizeMailboxName")]
|
||||||
|
max_size_mailbox_name: usize,
|
||||||
|
#[serde(rename = "maxSizeAttachmentsPerEmail")]
|
||||||
|
max_size_attachments_per_email: usize,
|
||||||
|
#[serde(rename = "emailQuerySortOptions")]
|
||||||
|
email_query_sort_options: Vec<String>,
|
||||||
|
#[serde(rename = "mayCreateTopLevelMailbox")]
|
||||||
|
may_create_top_level_mailbox: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct SubmissionCapabilities {
|
||||||
|
#[serde(rename = "maxDelayedSend")]
|
||||||
|
max_delayed_send: usize,
|
||||||
|
#[serde(rename = "submissionExtensions")]
|
||||||
|
submission_extensions: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct EmptyCapabilities {}
|
|
@ -0,0 +1,69 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::hash::Hash;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct SetRequest<T, U>
|
||||||
|
where
|
||||||
|
U: Eq + Hash,
|
||||||
|
{
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
#[serde(rename = "ifInState")]
|
||||||
|
if_in_state: Option<String>,
|
||||||
|
create: Option<HashMap<String, T>>,
|
||||||
|
update: Option<HashMap<String, HashMap<U, serde_json::Value>>>,
|
||||||
|
destroy: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct SetResponse<T, U> {
|
||||||
|
#[serde(rename = "accountId")]
|
||||||
|
account_id: String,
|
||||||
|
#[serde(rename = "oldState")]
|
||||||
|
old_state: Option<String>,
|
||||||
|
#[serde(rename = "newState")]
|
||||||
|
new_state: String,
|
||||||
|
#[serde(rename = "created")]
|
||||||
|
created: Option<HashMap<String, T>>,
|
||||||
|
#[serde(rename = "updated")]
|
||||||
|
updated: Option<HashMap<String, Option<T>>>,
|
||||||
|
#[serde(rename = "destroyed")]
|
||||||
|
destroyed: Option<Vec<String>>,
|
||||||
|
#[serde(rename = "notCreated")]
|
||||||
|
not_created: Option<HashMap<String, SetError<U>>>,
|
||||||
|
#[serde(rename = "notUpdated")]
|
||||||
|
not_updated: Option<HashMap<String, SetError<U>>>,
|
||||||
|
#[serde(rename = "notDestroyed")]
|
||||||
|
not_destroyed: Option<HashMap<String, SetError<U>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct SetError<U> {
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
type_: SetErrorType,
|
||||||
|
description: Option<String>,
|
||||||
|
properties: Option<Vec<U>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub enum SetErrorType {
|
||||||
|
#[serde(rename = "forbidden")]
|
||||||
|
Forbidden,
|
||||||
|
#[serde(rename = "overQuota")]
|
||||||
|
OverQuota,
|
||||||
|
#[serde(rename = "tooLarge")]
|
||||||
|
TooLarge,
|
||||||
|
#[serde(rename = "rateLimit")]
|
||||||
|
RateLimit,
|
||||||
|
#[serde(rename = "notFound")]
|
||||||
|
NotFound,
|
||||||
|
#[serde(rename = "invalidPatch")]
|
||||||
|
InvalidPatch,
|
||||||
|
#[serde(rename = "willDestroy")]
|
||||||
|
WillDestroy,
|
||||||
|
#[serde(rename = "invalidProperties")]
|
||||||
|
InvalidProperties,
|
||||||
|
#[serde(rename = "singleton")]
|
||||||
|
Singleton,
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
pub mod blob;
|
||||||
|
pub mod core;
|
||||||
|
pub mod push_subscription;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
|
||||||
|
pub enum URI {
|
||||||
|
#[serde(rename = "urn:ietf:params:jmap:core")]
|
||||||
|
Core,
|
||||||
|
#[serde(rename = "urn:ietf:params:jmap:mail")]
|
||||||
|
Mail,
|
||||||
|
#[serde(rename = "urn:ietf:params:jmap:submission")]
|
||||||
|
Submission,
|
||||||
|
#[serde(rename = "urn:ietf:params:jmap:vacationresponse")]
|
||||||
|
VacationResponse,
|
||||||
|
#[serde(rename = "urn:ietf:params:jmap:contacts")]
|
||||||
|
Contacts,
|
||||||
|
#[serde(rename = "urn:ietf:params:jmap:calendars")]
|
||||||
|
Calendars,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
enum Method {
|
||||||
|
#[serde(rename = "Core/echo")]
|
||||||
|
Echo,
|
||||||
|
#[serde(rename = "Blob/copy")]
|
||||||
|
CopyBlob,
|
||||||
|
#[serde(rename = "PushSubscription/get")]
|
||||||
|
GetPushSubscription,
|
||||||
|
#[serde(rename = "PushSubscription/set")]
|
||||||
|
SetPushSubscription,
|
||||||
|
#[serde(rename = "Mailbox/get")]
|
||||||
|
GetMailbox,
|
||||||
|
#[serde(rename = "Mailbox/changes")]
|
||||||
|
ChangesMailbox,
|
||||||
|
#[serde(rename = "Mailbox/query")]
|
||||||
|
QueryMailbox,
|
||||||
|
#[serde(rename = "Mailbox/queryChanges")]
|
||||||
|
QueryChangesMailbox,
|
||||||
|
#[serde(rename = "Mailbox/set")]
|
||||||
|
SetMailbox,
|
||||||
|
#[serde(rename = "Thread/get")]
|
||||||
|
GetThread,
|
||||||
|
#[serde(rename = "Thread/changes")]
|
||||||
|
ChangesThread,
|
||||||
|
#[serde(rename = "Email/get")]
|
||||||
|
GetEmail,
|
||||||
|
#[serde(rename = "Email/changes")]
|
||||||
|
ChangesEmail,
|
||||||
|
#[serde(rename = "Email/query")]
|
||||||
|
QueryEmail,
|
||||||
|
#[serde(rename = "Email/queryChanges")]
|
||||||
|
QueryChangesEmail,
|
||||||
|
#[serde(rename = "Email/set")]
|
||||||
|
SetEmail,
|
||||||
|
#[serde(rename = "Email/copy")]
|
||||||
|
CopyEmail,
|
||||||
|
#[serde(rename = "Email/import")]
|
||||||
|
ImportEmail,
|
||||||
|
#[serde(rename = "Email/parse")]
|
||||||
|
ParseEmail,
|
||||||
|
#[serde(rename = "SearchSnippet/get")]
|
||||||
|
GetSearchSnippet,
|
||||||
|
#[serde(rename = "Identity/get")]
|
||||||
|
GetIdentity,
|
||||||
|
#[serde(rename = "Identity/changes")]
|
||||||
|
ChangesIdentity,
|
||||||
|
#[serde(rename = "Identity/set")]
|
||||||
|
SetIdentity,
|
||||||
|
#[serde(rename = "EmailSubmission/get")]
|
||||||
|
GetEmailSubmission,
|
||||||
|
#[serde(rename = "EmailSubmission/changes")]
|
||||||
|
ChangesEmailSubmission,
|
||||||
|
#[serde(rename = "EmailSubmission/query")]
|
||||||
|
QueryEmailSubmission,
|
||||||
|
#[serde(rename = "EmailSubmission/queryChanges")]
|
||||||
|
QueryChangesEmailSubmission,
|
||||||
|
#[serde(rename = "EmailSubmission/set")]
|
||||||
|
SetEmailSubmission,
|
||||||
|
#[serde(rename = "VacationResponse/get")]
|
||||||
|
GetVacationResponse,
|
||||||
|
#[serde(rename = "VacationResponse/set")]
|
||||||
|
SetVacationResponse,
|
||||||
|
#[serde(rename = "error")]
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Hash, Clone)]
|
||||||
|
pub enum Object {
|
||||||
|
Core,
|
||||||
|
Mailbox,
|
||||||
|
Thread,
|
||||||
|
Email,
|
||||||
|
SearchSnippet,
|
||||||
|
Identity,
|
||||||
|
EmailSubmission,
|
||||||
|
VacationResponse,
|
||||||
|
PushSubscription,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub enum StateChangeType {
|
||||||
|
StateChange,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct StateChange {
|
||||||
|
#[serde(rename(serialize = "@type"))]
|
||||||
|
pub type_: StateChangeType,
|
||||||
|
pub changed: HashMap<String, HashMap<Object, String>>,
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::Object;
|
||||||
|
|
||||||
|
pub mod get;
|
||||||
|
pub mod set;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct PushSubscription {
|
||||||
|
#[serde(rename = "id")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
id: Option<String>,
|
||||||
|
|
||||||
|
#[serde(rename = "deviceClientId")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
device_client_id: Option<String>,
|
||||||
|
|
||||||
|
#[serde(rename = "url")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
url: Option<String>,
|
||||||
|
|
||||||
|
#[serde(rename = "keys")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
keys: Option<Keys>,
|
||||||
|
|
||||||
|
#[serde(rename = "verificationCode")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
verification_code: Option<String>,
|
||||||
|
|
||||||
|
#[serde(rename = "expires")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
expires: Option<DateTime<Utc>>,
|
||||||
|
|
||||||
|
#[serde(rename = "types")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
types: Option<Vec<Object>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum PushSubscriptionProperty {
|
||||||
|
#[serde(rename = "id")]
|
||||||
|
Id,
|
||||||
|
#[serde(rename = "deviceClientId")]
|
||||||
|
DeviceClientId,
|
||||||
|
#[serde(rename = "url")]
|
||||||
|
Url,
|
||||||
|
#[serde(rename = "keys")]
|
||||||
|
Keys,
|
||||||
|
#[serde(rename = "verificationCode")]
|
||||||
|
VerificationCode,
|
||||||
|
#[serde(rename = "expires")]
|
||||||
|
Expires,
|
||||||
|
#[serde(rename = "types")]
|
||||||
|
Types,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Keys {
|
||||||
|
p256dh: String,
|
||||||
|
auth: String,
|
||||||
|
}
|
Loading…
Reference in New Issue