simplify resourcetype

This commit is contained in:
Lennart
2024-11-04 20:46:16 +01:00
parent ab9c5f6b38
commit 2143bc850c
13 changed files with 98 additions and 72 deletions

View File

@@ -39,14 +39,6 @@ pub struct SupportedCalendarData {
calendar_data: CalendarData, calendar_data: CalendarData,
} }
#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub struct Resourcetype {
#[serde(rename = "C:calendar", alias = "calendar")]
calendar: (),
collection: (),
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum ReportMethod { pub enum ReportMethod {

View File

@@ -1,7 +1,7 @@
use super::methods::mkcalendar::route_mkcalendar; use super::methods::mkcalendar::route_mkcalendar;
use super::methods::report::route_report_calendar; use super::methods::report::route_report_calendar;
use super::prop::{ use super::prop::{
Resourcetype, SupportedCalendarComponent, SupportedCalendarComponentSet, SupportedCalendarData, SupportedCalendarComponent, SupportedCalendarComponentSet, SupportedCalendarData,
SupportedReportSet, SupportedReportSet,
}; };
use crate::calendar_object::resource::CalendarObjectResource; use crate::calendar_object::resource::CalendarObjectResource;
@@ -83,7 +83,7 @@ pub enum CalendarProp {
#[serde(skip_deserializing, untagged)] #[serde(skip_deserializing, untagged)]
#[from] #[from]
ExtCommonProperties(CommonPropertiesProp<Resourcetype>), ExtCommonProperties(CommonPropertiesProp),
#[serde(untagged)] #[serde(untagged)]
#[default] #[default]
@@ -97,9 +97,12 @@ impl Resource for CalendarResource {
type PropName = CalendarPropName; type PropName = CalendarPropName;
type Prop = CalendarProp; type Prop = CalendarProp;
type Error = Error; type Error = Error;
type ResourceType = Resourcetype;
type PrincipalResource = PrincipalResource; type PrincipalResource = PrincipalResource;
fn get_resourcetype() -> &'static [&'static str] {
&["collection", "C:calendar"]
}
fn get_prop( fn get_prop(
&self, &self,
_rmap: &ResourceMap, _rmap: &ResourceMap,

View File

@@ -41,7 +41,7 @@ pub enum CalendarObjectProp {
#[serde(skip_deserializing, untagged)] #[serde(skip_deserializing, untagged)]
#[from] #[from]
ExtCommonProperties(CommonPropertiesProp<Resourcetype>), ExtCommonProperties(CommonPropertiesProp),
#[serde(untagged)] #[serde(untagged)]
#[default] #[default]
@@ -54,16 +54,15 @@ pub struct CalendarObjectResource {
pub principal: String, pub principal: String,
} }
#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub struct Resourcetype {}
impl Resource for CalendarObjectResource { impl Resource for CalendarObjectResource {
type PropName = CalendarObjectPropName; type PropName = CalendarObjectPropName;
type Prop = CalendarObjectProp; type Prop = CalendarObjectProp;
type Error = Error; type Error = Error;
type PrincipalResource = PrincipalResource; type PrincipalResource = PrincipalResource;
type ResourceType = Resourcetype;
fn get_resourcetype() -> &'static [&'static str] {
&[]
}
fn get_prop( fn get_prop(
&self, &self,

View File

@@ -25,13 +25,6 @@ pub struct PrincipalResource {
principal: String, principal: String,
} }
#[derive(Deserialize, Serialize, Default, Debug, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub struct Resourcetype {
principal: (),
collection: (),
}
#[derive(Default, Deserialize, Serialize, From, PartialEq)] #[derive(Default, Deserialize, Serialize, From, PartialEq)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum PrincipalProp { pub enum PrincipalProp {
@@ -47,7 +40,7 @@ pub enum PrincipalProp {
#[serde(skip_deserializing, untagged)] #[serde(skip_deserializing, untagged)]
#[from] #[from]
ExtCommonProperties(CommonPropertiesProp<Resourcetype>), ExtCommonProperties(CommonPropertiesProp),
#[serde(untagged)] #[serde(untagged)]
#[default] #[default]
@@ -73,9 +66,12 @@ impl Resource for PrincipalResource {
type PropName = PrincipalPropName; type PropName = PrincipalPropName;
type Prop = PrincipalProp; type Prop = PrincipalProp;
type Error = Error; type Error = Error;
type ResourceType = Resourcetype;
type PrincipalResource = PrincipalResource; type PrincipalResource = PrincipalResource;
fn get_resourcetype() -> &'static [&'static str] {
&["collection", "principal"]
}
fn get_prop( fn get_prop(
&self, &self,
rmap: &ResourceMap, rmap: &ResourceMap,

View File

@@ -42,7 +42,7 @@ pub enum AddressObjectProp {
#[serde(skip_deserializing, untagged)] #[serde(skip_deserializing, untagged)]
#[from] #[from]
ExtCommonProperties(CommonPropertiesProp<Resourcetype>), ExtCommonProperties(CommonPropertiesProp),
#[serde(untagged)] #[serde(untagged)]
#[default] #[default]
@@ -55,17 +55,16 @@ pub struct AddressObjectResource {
pub principal: String, pub principal: String,
} }
#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub struct Resourcetype {}
impl Resource for AddressObjectResource { impl Resource for AddressObjectResource {
type PropName = AddressObjectPropName; type PropName = AddressObjectPropName;
type Prop = AddressObjectProp; type Prop = AddressObjectProp;
type Error = Error; type Error = Error;
type ResourceType = Resourcetype;
type PrincipalResource = PrincipalResource; type PrincipalResource = PrincipalResource;
fn get_resourcetype() -> &'static [&'static str] {
&[]
}
fn get_prop( fn get_prop(
&self, &self,
_rmap: &ResourceMap, _rmap: &ResourceMap,

View File

@@ -33,14 +33,6 @@ impl Default for SupportedAddressData {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub struct Resourcetype {
#[serde(rename = "CARD:addressbook", alias = "addressbook")]
addressbook: (),
collection: (),
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum ReportMethod { pub enum ReportMethod {

View File

@@ -1,6 +1,6 @@
use super::methods::mkcol::route_mkcol; use super::methods::mkcol::route_mkcol;
use super::methods::report::route_report_addressbook; use super::methods::report::route_report_addressbook;
use super::prop::{Resourcetype, SupportedAddressData, SupportedReportSet}; use super::prop::{SupportedAddressData, SupportedReportSet};
use crate::address_object::resource::AddressObjectResource; use crate::address_object::resource::AddressObjectResource;
use crate::principal::PrincipalResource; use crate::principal::PrincipalResource;
use crate::Error; use crate::Error;
@@ -68,7 +68,7 @@ pub enum AddressbookProp {
#[serde(skip_deserializing, untagged)] #[serde(skip_deserializing, untagged)]
#[from] #[from]
ExtCommonProperties(CommonPropertiesProp<Resourcetype>), ExtCommonProperties(CommonPropertiesProp),
#[serde(untagged)] #[serde(untagged)]
#[default] #[default]
@@ -82,9 +82,12 @@ impl Resource for AddressbookResource {
type PropName = AddressbookPropName; type PropName = AddressbookPropName;
type Prop = AddressbookProp; type Prop = AddressbookProp;
type Error = Error; type Error = Error;
type ResourceType = Resourcetype;
type PrincipalResource = PrincipalResource; type PrincipalResource = PrincipalResource;
fn get_resourcetype() -> &'static [&'static str] {
&["collection", "CARD:addressbook"]
}
fn get_prop( fn get_prop(
&self, &self,
_rmap: &ResourceMap, _rmap: &ResourceMap,

View File

@@ -25,13 +25,6 @@ pub struct PrincipalResource {
principal: String, principal: String,
} }
#[derive(Deserialize, Serialize, Default, Debug, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub struct Resourcetype {
principal: (),
collection: (),
}
#[derive(Default, Deserialize, Serialize, From, PartialEq)] #[derive(Default, Deserialize, Serialize, From, PartialEq)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum PrincipalProp { pub enum PrincipalProp {
@@ -47,7 +40,7 @@ pub enum PrincipalProp {
#[serde(skip_deserializing, untagged)] #[serde(skip_deserializing, untagged)]
#[from] #[from]
ExtCommonProperties(CommonPropertiesProp<Resourcetype>), ExtCommonProperties(CommonPropertiesProp),
#[serde(untagged)] #[serde(untagged)]
#[default] #[default]
@@ -73,9 +66,12 @@ impl Resource for PrincipalResource {
type PropName = PrincipalPropName; type PropName = PrincipalPropName;
type Prop = PrincipalProp; type Prop = PrincipalProp;
type Error = Error; type Error = Error;
type ResourceType = Resourcetype;
type PrincipalResource = PrincipalResource; type PrincipalResource = PrincipalResource;
fn get_resourcetype() -> &'static [&'static str] {
&["collection", "principal"]
}
fn get_prop( fn get_prop(
&self, &self,
rmap: &ResourceMap, rmap: &ResourceMap,

View File

@@ -1,8 +1,8 @@
use crate::{ use crate::{
extension::ResourceExtension, extension::ResourceExtension,
privileges::UserPrivilegeSet, privileges::UserPrivilegeSet,
resource::{InvalidProperty, Resource, ResourceType}, resource::{InvalidProperty, Resource},
xml::HrefElement, xml::{HrefElement, Resourcetype},
}; };
use actix_web::dev::ResourceMap; use actix_web::dev::ResourceMap;
use rustical_store::auth::User; use rustical_store::auth::User;
@@ -21,10 +21,10 @@ impl<R: Resource> Default for CommonPropertiesExtension<R> {
#[derive(Deserialize, Serialize, PartialEq)] #[derive(Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum CommonPropertiesProp<RT: ResourceType> { pub enum CommonPropertiesProp {
// WebDAV (RFC 2518) // WebDAV (RFC 2518)
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
Resourcetype(RT), Resourcetype(Resourcetype),
// WebDAV Current Principal Extension (RFC 5397) // WebDAV Current Principal Extension (RFC 5397)
CurrentUserPrincipal(HrefElement), CurrentUserPrincipal(HrefElement),
@@ -37,7 +37,7 @@ pub enum CommonPropertiesProp<RT: ResourceType> {
Invalid, Invalid,
} }
impl<RT: ResourceType> InvalidProperty for CommonPropertiesProp<RT> { impl InvalidProperty for CommonPropertiesProp {
fn invalid_property(&self) -> bool { fn invalid_property(&self) -> bool {
matches!(self, Self::Invalid) matches!(self, Self::Invalid)
} }
@@ -54,9 +54,9 @@ pub enum CommonPropertiesPropName {
impl<R: Resource> ResourceExtension<R> for CommonPropertiesExtension<R> impl<R: Resource> ResourceExtension<R> for CommonPropertiesExtension<R>
where where
R::Prop: From<CommonPropertiesProp<R::ResourceType>>, R::Prop: From<CommonPropertiesProp>,
{ {
type Prop = CommonPropertiesProp<R::ResourceType>; type Prop = CommonPropertiesProp;
type PropName = CommonPropertiesPropName; type PropName = CommonPropertiesPropName;
type Error = R::Error; type Error = R::Error;
@@ -69,7 +69,7 @@ where
) -> Result<Self::Prop, Self::Error> { ) -> Result<Self::Prop, Self::Error> {
Ok(match prop { Ok(match prop {
CommonPropertiesPropName::Resourcetype => { CommonPropertiesPropName::Resourcetype => {
CommonPropertiesProp::Resourcetype(R::ResourceType::default()) CommonPropertiesProp::Resourcetype(Resourcetype(R::get_resourcetype()))
} }
CommonPropertiesPropName::CurrentUserPrincipal => { CommonPropertiesPropName::CurrentUserPrincipal => {
CommonPropertiesProp::CurrentUserPrincipal( CommonPropertiesProp::CurrentUserPrincipal(

View File

@@ -29,10 +29,11 @@ impl<T: Serialize + for<'de> Deserialize<'de>> ResourceType for T {}
pub trait Resource: Clone + 'static { pub trait Resource: Clone + 'static {
type PropName: ResourcePropName; type PropName: ResourcePropName;
type Prop: ResourceProp + From<CommonPropertiesProp<Self::ResourceType>> + PartialEq; type Prop: ResourceProp + From<CommonPropertiesProp> + PartialEq;
type Error: ResponseError + From<crate::Error>; type Error: ResponseError + From<crate::Error>;
type PrincipalResource: Resource; type PrincipalResource: Resource;
type ResourceType: Default + Serialize + for<'de> Deserialize<'de>;
fn get_resourcetype() -> &'static [&'static str];
fn list_extensions() -> Vec<impl ResourceExtension<Self>> { fn list_extensions() -> Vec<impl ResourceExtension<Self>> {
vec![CommonPropertiesExtension::default()] vec![CommonPropertiesExtension::default()]
@@ -122,7 +123,7 @@ pub trait Resource: Clone + 'static {
Error::BadRequest("allprop MUST be the only queried prop".to_owned()).into(), Error::BadRequest("allprop MUST be the only queried prop".to_owned()).into(),
); );
} }
props = Self::list_props(); props = Self::list_props().to_vec();
for extension in Self::list_extensions() { for extension in Self::list_extensions() {
let ext_props: Vec<&str> = extension.list_props().into(); let ext_props: Vec<&str> = extension.list_props().into();
props.extend(ext_props); props.extend(ext_props);

View File

@@ -5,17 +5,10 @@ use actix_web::dev::ResourceMap;
use actix_web::HttpRequest; use actix_web::HttpRequest;
use async_trait::async_trait; use async_trait::async_trait;
use rustical_store::auth::User; use rustical_store::auth::User;
use serde::{Deserialize, Serialize};
use std::any::type_name; use std::any::type_name;
use std::marker::PhantomData; use std::marker::PhantomData;
use strum::{EnumString, VariantNames}; use strum::{EnumString, VariantNames};
#[derive(Deserialize, Serialize, Default, Debug, PartialEq)]
#[serde(rename_all = "kebab-case")]
pub struct Resourcetype {
collection: (),
}
#[derive(Clone)] #[derive(Clone)]
pub struct RootResource<PR: Resource>(PhantomData<PR>); pub struct RootResource<PR: Resource>(PhantomData<PR>);
@@ -31,11 +24,14 @@ pub enum RootResourcePropName {}
impl<PR: Resource> Resource for RootResource<PR> { impl<PR: Resource> Resource for RootResource<PR> {
type PropName = RootResourcePropName; type PropName = RootResourcePropName;
type Prop = CommonPropertiesProp<Self::ResourceType>; type Prop = CommonPropertiesProp;
type Error = PR::Error; type Error = PR::Error;
type ResourceType = Resourcetype;
type PrincipalResource = PR; type PrincipalResource = PR;
fn get_resourcetype() -> &'static [&'static str] {
&["collection"]
}
fn get_prop( fn get_prop(
&self, &self,
_rmap: &ResourceMap, _rmap: &ResourceMap,

View File

@@ -1,4 +1,5 @@
pub mod multistatus; pub mod multistatus;
mod resourcetype;
pub mod tag_list; pub mod tag_list;
pub mod tag_name; pub mod tag_name;
@@ -7,6 +8,8 @@ pub use multistatus::MultistatusElement;
pub use tag_list::TagList; pub use tag_list::TagList;
pub use tag_name::TagName; pub use tag_name::TagName;
pub use resourcetype::Resourcetype;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize, From, PartialEq)] #[derive(Debug, Clone, Deserialize, Serialize, From, PartialEq)]

View File

@@ -0,0 +1,46 @@
use serde::de::{MapAccess, Visitor};
use serde::ser::SerializeMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq)]
pub struct Resourcetype(pub &'static [&'static str]);
struct ResourcetypeVisitor;
impl<'de> Visitor<'de> for ResourcetypeVisitor {
type Value = Resourcetype;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("TagList")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
while map.next_key::<String>()?.is_some() {}
Ok(Resourcetype(&[]))
}
}
impl<'de> Deserialize<'de> for Resourcetype {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_map(ResourcetypeVisitor)
}
}
impl Serialize for Resourcetype {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut map = serializer.serialize_map(Some(self.0.len()))?;
for entry in self.0 {
map.serialize_entry(entry, &())?;
}
map.end()
}
}