Import upstream v0.16.22, stripped
Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use super::{
|
||||
Collation, Namespace,
|
||||
request::DavPropertyValue,
|
||||
response::{Ace, AclRestrictions, Href, List, Response, SupportedPrivilege},
|
||||
};
|
||||
use crate::{Depth, Timeout};
|
||||
use calcard::{
|
||||
icalendar::{ICalendar, ICalendarComponentType, ICalendarProperty},
|
||||
vcard::{VCard, VCardProperty, VCardVersion},
|
||||
};
|
||||
use types::{
|
||||
TimeRange,
|
||||
dead_property::{DeadElementTag, DeadProperty},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(test, serde(tag = "type", content = "data"))]
|
||||
pub enum DavProperty {
|
||||
WebDav(WebDavProperty),
|
||||
CardDav(CardDavProperty),
|
||||
CalDav(CalDavProperty),
|
||||
Principal(PrincipalProperty),
|
||||
DeadProperty(DeadElementTag),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(test, serde(tag = "type", content = "data"))]
|
||||
pub enum WebDavProperty {
|
||||
CreationDate,
|
||||
DisplayName,
|
||||
GetContentLanguage,
|
||||
GetContentLength,
|
||||
GetContentType,
|
||||
GetETag,
|
||||
GetLastModified,
|
||||
ResourceType,
|
||||
LockDiscovery,
|
||||
SupportedLock,
|
||||
SupportedReportSet,
|
||||
CurrentUserPrincipal,
|
||||
// Quota properties
|
||||
QuotaAvailableBytes,
|
||||
QuotaUsedBytes,
|
||||
// Sync properties
|
||||
SyncToken,
|
||||
// ACL properties (all protected)
|
||||
Owner,
|
||||
Group,
|
||||
SupportedPrivilegeSet,
|
||||
CurrentUserPrivilegeSet,
|
||||
Acl,
|
||||
AclRestrictions,
|
||||
InheritedAclSet,
|
||||
PrincipalCollectionSet,
|
||||
// Apple proprietary properties
|
||||
GetCTag,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(test, serde(tag = "type", content = "data"))]
|
||||
pub enum CardDavProperty {
|
||||
AddressbookDescription,
|
||||
SupportedAddressData,
|
||||
SupportedCollationSet,
|
||||
MaxResourceSize,
|
||||
AddressData {
|
||||
properties: Vec<CardDavPropertyName>,
|
||||
#[cfg_attr(test, serde(skip))]
|
||||
version: Option<VCardVersion>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct CardDavPropertyName {
|
||||
pub group: Option<String>,
|
||||
pub name: VCardProperty,
|
||||
pub no_value: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(test, serde(tag = "type", content = "data"))]
|
||||
pub enum CalDavProperty {
|
||||
CalendarDescription,
|
||||
CalendarTimezone,
|
||||
SupportedCalendarComponentSet,
|
||||
SupportedCalendarData,
|
||||
SupportedCollationSet,
|
||||
MaxResourceSize,
|
||||
MinDateTime,
|
||||
MaxDateTime,
|
||||
MaxInstances,
|
||||
MaxAttendeesPerInstance,
|
||||
CalendarData(CalendarData),
|
||||
TimezoneServiceSet,
|
||||
TimezoneId,
|
||||
ScheduleDefaultCalendarURL,
|
||||
ScheduleTag,
|
||||
ScheduleCalendarTransp,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(test, serde(tag = "type", content = "data"))]
|
||||
pub enum PrincipalProperty {
|
||||
AlternateURISet,
|
||||
PrincipalURL,
|
||||
GroupMemberSet,
|
||||
GroupMembership,
|
||||
CalendarHomeSet,
|
||||
AddressbookHomeSet,
|
||||
PrincipalAddress,
|
||||
CalendarUserAddressSet,
|
||||
CalendarUserType,
|
||||
ScheduleInboxURL,
|
||||
ScheduleOutboxURL,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct CalendarData {
|
||||
pub properties: Vec<CalDavPropertyName>,
|
||||
pub expand: Option<TimeRange>,
|
||||
pub limit_recurrence: Option<TimeRange>,
|
||||
pub limit_freebusy: Option<TimeRange>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct CalDavPropertyName {
|
||||
pub component: Option<ICalendarComponentType>,
|
||||
pub name: Option<ICalendarProperty>,
|
||||
pub no_value: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[repr(transparent)]
|
||||
pub struct Rfc1123DateTime(pub(crate) i64);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum DavValue {
|
||||
Timestamp(i64),
|
||||
Rfc1123Date(Rfc1123DateTime),
|
||||
Uint64(u64),
|
||||
String(String),
|
||||
CData(String),
|
||||
ResourceTypes(List<ResourceType>),
|
||||
ActiveLocks(List<ActiveLock>),
|
||||
LockEntries(List<LockEntry>),
|
||||
ReportSets(List<ReportSet>),
|
||||
ICalendar(ICalendar),
|
||||
VCard(VCard),
|
||||
Components(List<Comp>),
|
||||
Collations(List<SupportedCollation>),
|
||||
PrivilegeSet(List<SupportedPrivilege>),
|
||||
Privileges(List<Privilege>),
|
||||
Href(List<Href>),
|
||||
Acl(List<Ace>),
|
||||
AclRestrictions(AclRestrictions),
|
||||
Response(Box<Response>),
|
||||
DeadProperty(DeadProperty),
|
||||
SupportedAddressData,
|
||||
SupportedCalendarData,
|
||||
Null,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum ReportSet {
|
||||
SyncCollection,
|
||||
ExpandProperty,
|
||||
AddressbookQuery,
|
||||
AddressbookMultiGet,
|
||||
CalendarQuery,
|
||||
CalendarMultiGet,
|
||||
FreeBusyQuery,
|
||||
AclPrincipalPropSet,
|
||||
PrincipalMatch,
|
||||
PrincipalPropertySearch,
|
||||
PrincipalSearchPropertySet,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Comp(pub ICalendarComponentType);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct SupportedCollation {
|
||||
pub collation: Collation,
|
||||
pub namespace: Namespace,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum ResourceType {
|
||||
Collection,
|
||||
Principal,
|
||||
AddressBook,
|
||||
Calendar,
|
||||
ScheduleInbox,
|
||||
ScheduleOutbox,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct LockDiscovery(pub List<ActiveLock>);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct ActiveLock {
|
||||
pub lock_scope: LockScope,
|
||||
pub lock_type: LockType,
|
||||
pub depth: Depth,
|
||||
pub owner: Option<DeadProperty>,
|
||||
pub timeout: Timeout,
|
||||
pub lock_token: Option<Href>,
|
||||
pub lock_root: Href,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct SupportedLock(pub List<LockEntry>);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct LockEntry {
|
||||
pub lock_scope: LockScope,
|
||||
pub lock_type: LockType,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum LockType {
|
||||
Write,
|
||||
Other,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum LockScope {
|
||||
Exclusive,
|
||||
Shared,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum Privilege {
|
||||
Read,
|
||||
Write,
|
||||
WriteProperties,
|
||||
WriteContent,
|
||||
Unlock,
|
||||
ReadAcl,
|
||||
ReadCurrentUserPrivilegeSet,
|
||||
WriteAcl,
|
||||
Bind,
|
||||
Unbind,
|
||||
All,
|
||||
ReadFreeBusy,
|
||||
ScheduleDeliver,
|
||||
ScheduleDeliverInvite,
|
||||
ScheduleDeliverReply,
|
||||
ScheduleQueryFreeBusy,
|
||||
ScheduleSend,
|
||||
ScheduleSendInvite,
|
||||
ScheduleSendReply,
|
||||
ScheduleSendFreeBusy,
|
||||
}
|
||||
|
||||
impl Privilege {
|
||||
pub fn all(is_calendar: bool) -> Vec<Privilege> {
|
||||
if is_calendar {
|
||||
vec![
|
||||
Privilege::All,
|
||||
Privilege::Read,
|
||||
Privilege::Write,
|
||||
Privilege::WriteProperties,
|
||||
Privilege::WriteContent,
|
||||
Privilege::Unlock,
|
||||
Privilege::ReadAcl,
|
||||
Privilege::ReadCurrentUserPrivilegeSet,
|
||||
Privilege::WriteAcl,
|
||||
Privilege::Bind,
|
||||
Privilege::Unbind,
|
||||
Privilege::ReadFreeBusy,
|
||||
]
|
||||
} else {
|
||||
vec![
|
||||
Privilege::All,
|
||||
Privilege::Read,
|
||||
Privilege::Write,
|
||||
Privilege::WriteProperties,
|
||||
Privilege::WriteContent,
|
||||
Privilege::Unlock,
|
||||
Privilege::ReadAcl,
|
||||
Privilege::ReadCurrentUserPrivilegeSet,
|
||||
Privilege::WriteAcl,
|
||||
Privilege::Bind,
|
||||
Privilege::Unbind,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scheduling(is_inbox: bool, is_owner: bool) -> Vec<Privilege> {
|
||||
let mut privileges = if is_inbox {
|
||||
vec![
|
||||
Privilege::Read,
|
||||
Privilege::ReadCurrentUserPrivilegeSet,
|
||||
Privilege::ScheduleDeliver,
|
||||
Privilege::ScheduleDeliverInvite,
|
||||
Privilege::ScheduleDeliverReply,
|
||||
Privilege::ScheduleQueryFreeBusy,
|
||||
]
|
||||
} else {
|
||||
vec![
|
||||
Privilege::Read,
|
||||
Privilege::ReadCurrentUserPrivilegeSet,
|
||||
Privilege::ScheduleSend,
|
||||
Privilege::ScheduleSendInvite,
|
||||
Privilege::ScheduleSendReply,
|
||||
Privilege::ScheduleSendFreeBusy,
|
||||
]
|
||||
};
|
||||
|
||||
if is_owner {
|
||||
privileges.extend([
|
||||
Privilege::All,
|
||||
Privilege::Write,
|
||||
Privilege::WriteProperties,
|
||||
Privilege::WriteContent,
|
||||
Privilege::ReadAcl,
|
||||
Privilege::WriteAcl,
|
||||
]);
|
||||
}
|
||||
|
||||
privileges
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DavProperty> for DavPropertyValue {
|
||||
fn from(value: DavProperty) -> Self {
|
||||
DavPropertyValue {
|
||||
property: value,
|
||||
value: DavValue::Null,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Rfc1123DateTime {
|
||||
pub fn new(timestamp: i64) -> Self {
|
||||
Self(timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
impl DavProperty {
|
||||
pub const ALL_PROPS: [DavProperty; 11] = [
|
||||
DavProperty::WebDav(WebDavProperty::CreationDate),
|
||||
DavProperty::WebDav(WebDavProperty::DisplayName),
|
||||
DavProperty::WebDav(WebDavProperty::GetETag),
|
||||
DavProperty::WebDav(WebDavProperty::GetLastModified),
|
||||
DavProperty::WebDav(WebDavProperty::ResourceType),
|
||||
DavProperty::WebDav(WebDavProperty::LockDiscovery),
|
||||
DavProperty::WebDav(WebDavProperty::SupportedLock),
|
||||
DavProperty::WebDav(WebDavProperty::CurrentUserPrincipal),
|
||||
DavProperty::WebDav(WebDavProperty::GetContentLanguage),
|
||||
DavProperty::WebDav(WebDavProperty::GetContentLength),
|
||||
DavProperty::WebDav(WebDavProperty::GetContentType),
|
||||
];
|
||||
|
||||
pub fn is_all_prop(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
DavProperty::WebDav(WebDavProperty::CreationDate)
|
||||
| DavProperty::WebDav(WebDavProperty::DisplayName)
|
||||
| DavProperty::WebDav(WebDavProperty::GetETag)
|
||||
| DavProperty::WebDav(WebDavProperty::GetLastModified)
|
||||
| DavProperty::WebDav(WebDavProperty::ResourceType)
|
||||
| DavProperty::WebDav(WebDavProperty::LockDiscovery)
|
||||
| DavProperty::WebDav(WebDavProperty::SupportedLock)
|
||||
| DavProperty::WebDav(WebDavProperty::CurrentUserPrincipal)
|
||||
| DavProperty::WebDav(WebDavProperty::GetContentLanguage)
|
||||
| DavProperty::WebDav(WebDavProperty::GetContentLength)
|
||||
| DavProperty::WebDav(WebDavProperty::GetContentType)
|
||||
| DavProperty::DeadProperty(_)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ReportSet {
|
||||
pub fn calendar() -> Vec<ReportSet> {
|
||||
vec![
|
||||
ReportSet::SyncCollection,
|
||||
ReportSet::AclPrincipalPropSet,
|
||||
ReportSet::PrincipalMatch,
|
||||
ReportSet::ExpandProperty,
|
||||
ReportSet::CalendarQuery,
|
||||
ReportSet::CalendarMultiGet,
|
||||
ReportSet::FreeBusyQuery,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn addressbook() -> Vec<ReportSet> {
|
||||
vec![
|
||||
ReportSet::SyncCollection,
|
||||
ReportSet::AclPrincipalPropSet,
|
||||
ReportSet::PrincipalMatch,
|
||||
ReportSet::ExpandProperty,
|
||||
ReportSet::AddressbookQuery,
|
||||
ReportSet::AddressbookMultiGet,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn file() -> Vec<ReportSet> {
|
||||
vec![
|
||||
ReportSet::SyncCollection,
|
||||
ReportSet::AclPrincipalPropSet,
|
||||
ReportSet::PrincipalMatch,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn principal() -> Vec<ReportSet> {
|
||||
vec![
|
||||
ReportSet::PrincipalPropertySearch,
|
||||
ReportSet::PrincipalSearchPropertySet,
|
||||
ReportSet::PrincipalMatch,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use super::{
|
||||
Collation, MatchType,
|
||||
property::{DavProperty, DavValue, LockScope, LockType},
|
||||
response::Ace,
|
||||
};
|
||||
use crate::{Condition, Depth};
|
||||
use calcard::{
|
||||
icalendar::{ICalendarComponentType, ICalendarParameterName, ICalendarProperty},
|
||||
vcard::{VCardParameterName, VCardProperty},
|
||||
};
|
||||
use types::{
|
||||
TimeRange,
|
||||
dead_property::{ArchivedDeadProperty, ArchivedDeadPropertyTag, DeadElementTag, DeadProperty},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(test, serde(tag = "type", content = "data"))]
|
||||
pub enum PropFind {
|
||||
#[default]
|
||||
PropName,
|
||||
AllProp(Vec<DavProperty>),
|
||||
Prop(Vec<DavProperty>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct PropertyUpdate {
|
||||
pub set: Vec<DavPropertyValue>,
|
||||
pub remove: Vec<DavProperty>,
|
||||
pub set_first: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct DavPropertyValue {
|
||||
pub property: DavProperty,
|
||||
pub value: DavValue,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct MkCol {
|
||||
pub is_mkcalendar: bool,
|
||||
pub props: Vec<DavPropertyValue>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct LockInfo {
|
||||
pub lock_scope: LockScope,
|
||||
pub lock_type: LockType,
|
||||
pub owner: Option<DeadProperty>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(test, serde(tag = "type"))]
|
||||
pub enum Report {
|
||||
AddressbookQuery(AddressbookQuery),
|
||||
AddressbookMultiGet(MultiGet),
|
||||
CalendarQuery(CalendarQuery),
|
||||
CalendarMultiGet(MultiGet),
|
||||
FreeBusyQuery(FreeBusyQuery),
|
||||
SyncCollection(SyncCollection),
|
||||
ExpandProperty(ExpandProperty),
|
||||
AclPrincipalPropSet(AclPrincipalPropSet),
|
||||
PrincipalMatch(PrincipalMatch),
|
||||
PrincipalPropertySearch(PrincipalPropertySearch),
|
||||
PrincipalSearchPropertySet,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct ExpandProperty {
|
||||
pub properties: Vec<ExpandPropertyItem>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct ExpandPropertyItem {
|
||||
pub property: DavProperty,
|
||||
pub depth: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct AddressbookQuery {
|
||||
pub properties: PropFind,
|
||||
pub filters: Vec<Filter<(), VCardPropertyWithGroup, VCardParameterName>>,
|
||||
pub limit: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct VCardPropertyWithGroup {
|
||||
pub name: VCardProperty,
|
||||
pub group: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct CalendarQuery {
|
||||
pub properties: PropFind,
|
||||
pub filters:
|
||||
Vec<Filter<Vec<ICalendarComponentType>, ICalendarProperty, ICalendarParameterName>>,
|
||||
pub timezone: Timezone,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(test, serde(tag = "type"))]
|
||||
pub enum Timezone {
|
||||
Name(String),
|
||||
Id(String),
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct FreeBusyQuery {
|
||||
pub range: Option<TimeRange>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct MultiGet {
|
||||
pub properties: PropFind,
|
||||
pub hrefs: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct SyncCollection {
|
||||
pub sync_token: Option<String>,
|
||||
pub properties: PropFind,
|
||||
pub depth: Depth,
|
||||
pub limit: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(test, serde(tag = "type"))]
|
||||
pub enum Filter<A, B, C> {
|
||||
AnyOf,
|
||||
AllOf,
|
||||
Component {
|
||||
comp: A,
|
||||
op: FilterOp,
|
||||
},
|
||||
Property {
|
||||
comp: A,
|
||||
prop: B,
|
||||
op: FilterOp,
|
||||
},
|
||||
Parameter {
|
||||
comp: A,
|
||||
prop: B,
|
||||
param: C,
|
||||
op: FilterOp,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(test, serde(tag = "type", content = "data"))]
|
||||
pub enum FilterOp {
|
||||
Exists,
|
||||
Undefined,
|
||||
TimeRange(TimeRange),
|
||||
TextMatch(TextMatch),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(test, serde(tag = "type"))]
|
||||
pub struct TextMatch {
|
||||
pub match_type: MatchType,
|
||||
pub value: String,
|
||||
pub collation: Collation,
|
||||
pub negate: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Acl {
|
||||
pub aces: Vec<Ace>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct AclPrincipalPropSet {
|
||||
pub properties: Vec<DavProperty>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct PrincipalMatch {
|
||||
pub principal_properties: PrincipalMatchProperties,
|
||||
pub properties: Vec<DavProperty>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum PrincipalMatchProperties {
|
||||
Properties(Vec<DavProperty>),
|
||||
Self_,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct PrincipalPropertySearch {
|
||||
pub property_search: Vec<PropertySearch>,
|
||||
pub properties: Vec<DavProperty>,
|
||||
pub apply_to_principal_collection_set: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct PropertySearch {
|
||||
pub property: DavProperty,
|
||||
pub match_: String,
|
||||
}
|
||||
|
||||
impl PropertyUpdate {
|
||||
pub fn has_changes(&self) -> bool {
|
||||
!self.set.is_empty() || !self.remove.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl FreeBusyQuery {
|
||||
pub fn new(start: i64, end: i64) -> Self {
|
||||
FreeBusyQuery {
|
||||
range: Some(TimeRange { start, end }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DavDeadProperty {
|
||||
fn to_dav_values(&self, output: &mut Vec<DavPropertyValue>);
|
||||
}
|
||||
|
||||
impl DavDeadProperty for ArchivedDeadProperty {
|
||||
fn to_dav_values(&self, output: &mut Vec<DavPropertyValue>) {
|
||||
let mut depth: u32 = 0;
|
||||
let mut tags = Vec::new();
|
||||
let mut tag_start = None;
|
||||
|
||||
for tag in self.0.iter() {
|
||||
match tag {
|
||||
ArchivedDeadPropertyTag::ElementStart(start) => {
|
||||
if depth == 0 {
|
||||
tag_start = Some(DeadElementTag::from(start));
|
||||
} else {
|
||||
tags.push(tag.into());
|
||||
}
|
||||
|
||||
depth += 1;
|
||||
}
|
||||
ArchivedDeadPropertyTag::ElementEnd => {
|
||||
depth = depth.saturating_sub(1);
|
||||
|
||||
if depth > 0 {
|
||||
tags.push(tag.into());
|
||||
} else if let Some(tag_start) = tag_start.take() {
|
||||
output.push(DavPropertyValue::new(
|
||||
DavProperty::DeadProperty(tag_start),
|
||||
DavValue::DeadProperty(DeadProperty(std::mem::take(&mut tags))),
|
||||
));
|
||||
}
|
||||
}
|
||||
ArchivedDeadPropertyTag::Text(_) => {
|
||||
if tag_start.is_some() {
|
||||
tags.push(tag.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Condition<'_> {
|
||||
pub fn is_none_match(&self) -> bool {
|
||||
match self {
|
||||
Condition::ETag { is_not, .. } | Condition::Exists { is_not } => *is_not,
|
||||
Condition::StateToken { .. } => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use super::{
|
||||
Namespaces,
|
||||
property::{DavProperty, Privilege},
|
||||
request::{DavPropertyValue, Filter},
|
||||
};
|
||||
use calcard::{
|
||||
icalendar::{ICalendarComponentType, ICalendarParameterName, ICalendarProperty},
|
||||
vcard::{VCardParameterName, VCardProperty},
|
||||
};
|
||||
use hyper::StatusCode;
|
||||
use std::{borrow::Cow, fmt::Display};
|
||||
|
||||
pub struct MultiStatus {
|
||||
pub namespaces: Namespaces,
|
||||
pub response: List<Response>,
|
||||
pub response_description: Option<ResponseDescription>,
|
||||
pub sync_token: Option<SyncToken>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Response {
|
||||
pub href: Href,
|
||||
pub typ: ResponseType,
|
||||
pub error: Option<Condition>,
|
||||
pub response_description: Option<ResponseDescription>,
|
||||
pub location: Option<Location>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum ResponseType {
|
||||
PropStat(List<PropStat>),
|
||||
Status { href: List<Href>, status: Status },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[repr(transparent)]
|
||||
pub struct Status(pub StatusCode);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[repr(transparent)]
|
||||
pub struct Location(pub Href);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[repr(transparent)]
|
||||
pub struct ResponseDescription(pub String);
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct SyncToken(pub String);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[repr(transparent)]
|
||||
pub struct Href(pub String);
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[repr(transparent)]
|
||||
pub struct List<T: Display>(pub Vec<T>);
|
||||
|
||||
pub struct MkColResponse {
|
||||
pub namespaces: Namespaces,
|
||||
pub propstat: List<PropStat>,
|
||||
pub mkcalendar: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct PropStat {
|
||||
pub prop: Prop,
|
||||
pub status: Status,
|
||||
pub error: Option<Condition>,
|
||||
pub response_description: Option<ResponseDescription>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
#[repr(transparent)]
|
||||
pub struct Prop(pub List<DavPropertyValue>);
|
||||
|
||||
pub struct PropResponse {
|
||||
pub namespaces: Namespaces,
|
||||
pub properties: List<DavPropertyValue>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ScheduleResponse {
|
||||
pub items: List<ScheduleResponseItem>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ScheduleResponseItem {
|
||||
pub recipient: Href,
|
||||
pub request_status: Cow<'static, str>,
|
||||
pub calendar_data: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct SupportedPrivilege {
|
||||
pub privilege: Privilege,
|
||||
pub abstract_: bool,
|
||||
pub description: String,
|
||||
pub supported_privilege: List<SupportedPrivilege>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Ace {
|
||||
pub principal: Principal,
|
||||
pub invert: bool,
|
||||
pub grant_deny: GrantDeny,
|
||||
pub protected: bool,
|
||||
pub inherited: Option<Href>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum GrantDeny {
|
||||
Grant(List<Privilege>),
|
||||
Deny(List<Privilege>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum Principal {
|
||||
Href(Href),
|
||||
Response(Response),
|
||||
All,
|
||||
#[default]
|
||||
Authenticated,
|
||||
Unauthenticated,
|
||||
Property(List<DavPropertyValue>),
|
||||
Self_,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct AclRestrictions {
|
||||
pub grant_only: bool,
|
||||
pub no_invert: bool,
|
||||
pub deny_before_grant: bool,
|
||||
pub required_principal: Option<RequiredPrincipal>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum RequiredPrincipal {
|
||||
All,
|
||||
Authenticated,
|
||||
Unauthenticated,
|
||||
Self_,
|
||||
Href(List<Href>),
|
||||
Property(Vec<DavPropertyValue>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct PrincipalSearchPropertySet {
|
||||
pub namespaces: Namespaces,
|
||||
pub properties: List<PrincipalSearchProperty>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct PrincipalSearchProperty {
|
||||
pub name: DavProperty,
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
pub struct ErrorResponse {
|
||||
pub namespaces: Namespaces,
|
||||
pub error: Condition,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum Condition {
|
||||
Base(BaseCondition),
|
||||
Cal(CalCondition),
|
||||
Card(CardCondition),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum BaseCondition {
|
||||
NoConflictingLock(List<Href>),
|
||||
LockTokenSubmitted(List<Href>),
|
||||
LockTokenMatchesRequestUri,
|
||||
CannotModifyProtectedProperty,
|
||||
NoExternalEntities,
|
||||
PreservedLiveProperties,
|
||||
PropFindFiniteDepth,
|
||||
ResourceMustBeNull,
|
||||
NeedPrivileges(List<Resource>),
|
||||
NoAceConflict,
|
||||
NoProtectedAceConflict,
|
||||
NoInheritedAceConflict,
|
||||
LimitedNumberOfAces,
|
||||
DenyBeforeGrant,
|
||||
GrantOnly,
|
||||
NoInvert,
|
||||
NoAbstract,
|
||||
NotSupportedPrivilege,
|
||||
MissingRequiredPrincipal,
|
||||
RecognizedPrincipal,
|
||||
AllowedPrincipal,
|
||||
NumberOfMatchesWithinLimit,
|
||||
QuotaNotExceeded,
|
||||
ValidResourceType,
|
||||
ValidSyncToken,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Resource {
|
||||
pub href: Href,
|
||||
pub privilege: Privilege,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum CalCondition {
|
||||
CalendarCollectionLocationOk,
|
||||
ValidCalendarData,
|
||||
ValidFilter,
|
||||
ValidCalendarObjectResource,
|
||||
ValidTimezone,
|
||||
NoUidConflict(Href),
|
||||
InitializeCalendarCollection,
|
||||
SupportedCalendarData,
|
||||
SupportedFilter(
|
||||
Vec<Filter<Vec<ICalendarComponentType>, ICalendarProperty, ICalendarParameterName>>,
|
||||
),
|
||||
SupportedCollation(String),
|
||||
SupportedCalendarComponent,
|
||||
MinDateTime,
|
||||
MaxDateTime,
|
||||
MaxResourceSize(u32),
|
||||
MaxInstances,
|
||||
MaxAttendeesPerInstance,
|
||||
UniqueSchedulingObjectResource(Href),
|
||||
SameOrganizerInAllComponents,
|
||||
AllowedOrganizerObjectChange,
|
||||
AllowedAttendeeObjectChange,
|
||||
DefaultCalendarNeeded,
|
||||
ValidScheduleDefaultCalendarUrl,
|
||||
ValidSchedulingMessage,
|
||||
ValidOrganizer,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum CardCondition {
|
||||
SupportedAddressData,
|
||||
SupportedAddressDataConversion,
|
||||
SupportedFilter(Vec<Filter<(), VCardProperty, VCardParameterName>>),
|
||||
SupportedCollation(String),
|
||||
ValidAddressData,
|
||||
NoUidConflict(Href),
|
||||
MaxResourceSize(u32),
|
||||
AddressBookCollectionLocationOk,
|
||||
}
|
||||
|
||||
impl BaseCondition {
|
||||
pub fn status(&self) -> StatusCode {
|
||||
match self {
|
||||
BaseCondition::NoConflictingLock(_) => StatusCode::LOCKED,
|
||||
BaseCondition::CannotModifyProtectedProperty => StatusCode::FORBIDDEN,
|
||||
BaseCondition::LockTokenSubmitted(_) => StatusCode::LOCKED,
|
||||
BaseCondition::LockTokenMatchesRequestUri => StatusCode::CONFLICT,
|
||||
BaseCondition::NoExternalEntities => StatusCode::FORBIDDEN,
|
||||
BaseCondition::PreservedLiveProperties => StatusCode::CONFLICT,
|
||||
BaseCondition::PropFindFiniteDepth => StatusCode::FORBIDDEN,
|
||||
BaseCondition::ResourceMustBeNull => StatusCode::CONFLICT,
|
||||
BaseCondition::NeedPrivileges(_) => StatusCode::FORBIDDEN,
|
||||
BaseCondition::NumberOfMatchesWithinLimit => StatusCode::FORBIDDEN,
|
||||
_ => StatusCode::FORBIDDEN,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Href {
|
||||
fn from(value: String) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Href {
|
||||
fn from(value: &str) -> Self {
|
||||
Self(value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl MultiStatus {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.response.0.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl BaseCondition {
|
||||
pub fn display_name(&self) -> &'static str {
|
||||
match self {
|
||||
BaseCondition::NoConflictingLock(_) => "NoConflictingLock",
|
||||
BaseCondition::CannotModifyProtectedProperty => "CannotModifyProtectedProperty",
|
||||
BaseCondition::LockTokenSubmitted(_) => "LockTokenSubmitted",
|
||||
BaseCondition::LockTokenMatchesRequestUri => "LockTokenMatchesRequestUri",
|
||||
BaseCondition::NoExternalEntities => "NoExternalEntities",
|
||||
BaseCondition::PreservedLiveProperties => "PreservedLiveProperties",
|
||||
BaseCondition::PropFindFiniteDepth => "PropFindFiniteDepth",
|
||||
BaseCondition::ResourceMustBeNull => "ResourceMustBeNull",
|
||||
BaseCondition::NeedPrivileges(_) => "NeedPrivileges",
|
||||
BaseCondition::NoAceConflict => "NoAceConflict",
|
||||
BaseCondition::NoProtectedAceConflict => "NoProtectedAceConflict",
|
||||
BaseCondition::NoInheritedAceConflict => "NoInheritedAceConflict",
|
||||
BaseCondition::LimitedNumberOfAces => "LimitedNumberOfAces",
|
||||
BaseCondition::DenyBeforeGrant => "DenyBeforeGrant",
|
||||
BaseCondition::GrantOnly => "GrantOnly",
|
||||
BaseCondition::NoInvert => "NoInvert",
|
||||
BaseCondition::NoAbstract => "NoAbstract",
|
||||
BaseCondition::NotSupportedPrivilege => "NotSupportedPrivilege",
|
||||
BaseCondition::MissingRequiredPrincipal => "MissingRequiredPrincipal",
|
||||
BaseCondition::RecognizedPrincipal => "RecognizedPrincipal",
|
||||
BaseCondition::AllowedPrincipal => "AllowedPrincipal",
|
||||
BaseCondition::NumberOfMatchesWithinLimit => "NumberOfMatchesWithinLimit",
|
||||
BaseCondition::QuotaNotExceeded => "QuotaNotExceeded",
|
||||
BaseCondition::ValidResourceType => "ValidResourceType",
|
||||
BaseCondition::ValidSyncToken => "ValidSyncToken",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CalCondition {
|
||||
pub fn display_name(&self) -> &'static str {
|
||||
match self {
|
||||
CalCondition::CalendarCollectionLocationOk => "CalendarCollectionLocationOk",
|
||||
CalCondition::ValidCalendarData => "ValidCalendarData",
|
||||
CalCondition::ValidFilter => "ValidFilter",
|
||||
CalCondition::ValidCalendarObjectResource => "ValidCalendarObjectResource",
|
||||
CalCondition::ValidTimezone => "ValidTimezone",
|
||||
CalCondition::NoUidConflict(_) => "NoUidConflict",
|
||||
CalCondition::InitializeCalendarCollection => "InitializeCalendarCollection",
|
||||
CalCondition::SupportedCalendarData => "SupportedCalendarData",
|
||||
CalCondition::SupportedFilter(_) => "SupportedFilter",
|
||||
CalCondition::SupportedCollation(_) => "SupportedCollation",
|
||||
CalCondition::MinDateTime => "MinDateTime",
|
||||
CalCondition::MaxDateTime => "MaxDateTime",
|
||||
CalCondition::MaxResourceSize(_) => "MaxResourceSize",
|
||||
CalCondition::MaxInstances => "MaxInstances",
|
||||
CalCondition::MaxAttendeesPerInstance => "MaxAttendeesPerInstance",
|
||||
CalCondition::UniqueSchedulingObjectResource(_) => "UniqueSchedulingObjectResource",
|
||||
CalCondition::SameOrganizerInAllComponents => "SameOrganizerInAllComponents",
|
||||
CalCondition::AllowedOrganizerObjectChange => "AllowedOrganizerObjectChange",
|
||||
CalCondition::AllowedAttendeeObjectChange => "AllowedAttendeeObjectChange",
|
||||
CalCondition::DefaultCalendarNeeded => "DefaultCalendarNeeded",
|
||||
CalCondition::ValidScheduleDefaultCalendarUrl => "ValidScheduleDefaultCalendarUrl",
|
||||
CalCondition::ValidSchedulingMessage => "ValidSchedulingMessage",
|
||||
CalCondition::ValidOrganizer => "ValidOrganizer",
|
||||
CalCondition::SupportedCalendarComponent => "SupportedCalendarComponent",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CardCondition {
|
||||
pub fn display_name(&self) -> &'static str {
|
||||
match self {
|
||||
CardCondition::SupportedAddressData => "SupportedAddressData",
|
||||
CardCondition::SupportedAddressDataConversion => "SupportedAddressDataConversion",
|
||||
CardCondition::SupportedFilter(_) => "SupportedFilter",
|
||||
CardCondition::SupportedCollation(_) => "SupportedCollation",
|
||||
CardCondition::ValidAddressData => "ValidAddressData",
|
||||
CardCondition::NoUidConflict(_) => "NoUidConflict",
|
||||
CardCondition::MaxResourceSize(_) => "MaxResourceSize",
|
||||
CardCondition::AddressBookCollectionLocationOk => "AddressBookCollectionLocationOk",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Condition {
|
||||
pub fn display_name(&self) -> &'static str {
|
||||
match self {
|
||||
Condition::Base(base) => base.display_name(),
|
||||
Condition::Cal(cal) => cal.display_name(),
|
||||
Condition::Card(card) => card.display_name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod serde_impl {
|
||||
use super::Status;
|
||||
use hyper::StatusCode;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
impl Serialize for Status {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
// Serialize the status code as a u16
|
||||
serializer.serialize_u16(self.0.as_u16())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Status {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
// Deserialize as u16
|
||||
let status_value = u16::deserialize(deserializer)?;
|
||||
|
||||
// Convert u16 to StatusCode
|
||||
let status_code = StatusCode::try_from(status_value).map_err(|_| {
|
||||
serde::de::Error::custom(format!("Invalid status code: {}", status_value))
|
||||
})?;
|
||||
|
||||
Ok(Status(status_code))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user