mirror of
https://github.com/lennart-k/rustical.git
synced 2026-01-30 11:48:18 +00:00
carddav: Fix filter test="allof"|"anyof"
This commit is contained in:
@@ -1,9 +1,8 @@
|
|||||||
|
use super::FilterElement;
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
use rustical_ical::CalendarObject;
|
use rustical_ical::CalendarObject;
|
||||||
use rustical_xml::XmlDocument;
|
use rustical_xml::XmlDocument;
|
||||||
|
|
||||||
use crate::calendar::methods::report::calendar_query::FilterElement;
|
|
||||||
|
|
||||||
const ICS_1: &str = r"BEGIN:VCALENDAR
|
const ICS_1: &str = r"BEGIN:VCALENDAR
|
||||||
VERSION:2.0
|
VERSION:2.0
|
||||||
PRODID:-//Example Corp.//CalDAV Client//EN
|
PRODID:-//Example Corp.//CalDAV Client//EN
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ use crate::{
|
|||||||
address_object::AddressObjectPropWrapperName,
|
address_object::AddressObjectPropWrapperName,
|
||||||
addressbook::methods::report::addressbook_query::PropFilterElement,
|
addressbook::methods::report::addressbook_query::PropFilterElement,
|
||||||
};
|
};
|
||||||
|
use derive_more::{From, Into};
|
||||||
use ical::property::Property;
|
use ical::property::Property;
|
||||||
use rustical_dav::xml::{PropfindType, TextMatchElement};
|
use rustical_dav::xml::{PropfindType, TextMatchElement};
|
||||||
use rustical_ical::{AddressObject, UtcDateTime};
|
use rustical_ical::{AddressObject, UtcDateTime};
|
||||||
use rustical_xml::XmlDeserialize;
|
use rustical_xml::{ValueDeserialize, XmlDeserialize, XmlRootTag};
|
||||||
|
|
||||||
#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)]
|
#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -46,18 +47,34 @@ impl ParamFilterElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq, Default, From, Into)]
|
||||||
#[allow(dead_code)]
|
pub struct Allof(pub bool);
|
||||||
|
|
||||||
|
impl ValueDeserialize for Allof {
|
||||||
|
fn deserialize(val: &str) -> Result<Self, rustical_xml::XmlError> {
|
||||||
|
Ok(Self(match val {
|
||||||
|
"allof" => true,
|
||||||
|
"anyof" => false,
|
||||||
|
_ => {
|
||||||
|
return Err(rustical_xml::XmlError::InvalidVariant(format!(
|
||||||
|
"Invalid test parameter: {val}"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// <!ELEMENT filter (prop-filter*)>
|
// <!ELEMENT filter (prop-filter*)>
|
||||||
// <!ATTLIST filter test (anyof | allof) "anyof">
|
// <!ATTLIST filter test (anyof | allof) "anyof">
|
||||||
// <!-- test value:
|
// <!-- test value:
|
||||||
// anyof logical OR for prop-filter matches
|
// anyof logical OR for prop-filter matches
|
||||||
// allof logical AND for prop-filter matches -->
|
// allof logical AND for prop-filter matches -->
|
||||||
|
#[derive(XmlDeserialize, XmlRootTag, Clone, Debug, PartialEq, Eq)]
|
||||||
|
#[xml(root = "filter", ns = "rustical_dav::namespace::NS_CARDDAV")]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct FilterElement {
|
pub struct FilterElement {
|
||||||
#[xml(ty = "attr")]
|
#[xml(ty = "attr", default = "Default::default")]
|
||||||
pub anyof: Option<String>,
|
pub test: Allof,
|
||||||
#[xml(ty = "attr")]
|
|
||||||
pub allof: Option<String>,
|
|
||||||
#[xml(ns = "rustical_dav::namespace::NS_CARDDAV", flatten)]
|
#[xml(ns = "rustical_dav::namespace::NS_CARDDAV", flatten)]
|
||||||
pub(crate) prop_filter: Vec<PropFilterElement>,
|
pub(crate) prop_filter: Vec<PropFilterElement>,
|
||||||
}
|
}
|
||||||
@@ -65,11 +82,7 @@ pub struct FilterElement {
|
|||||||
impl FilterElement {
|
impl FilterElement {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn matches(&self, addr_object: &AddressObject) -> bool {
|
pub fn matches(&self, addr_object: &AddressObject) -> bool {
|
||||||
let allof = match (self.allof.is_some(), self.anyof.is_some()) {
|
let Allof(allof) = self.test;
|
||||||
(true, false) => true,
|
|
||||||
(false, _) => false,
|
|
||||||
(true, true) => panic!("wat"),
|
|
||||||
};
|
|
||||||
let mut results = self
|
let mut results = self
|
||||||
.prop_filter
|
.prop_filter
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use super::ParamFilterElement;
|
use super::{Allof, ParamFilterElement};
|
||||||
use ical::{parser::Component, property::Property};
|
use ical::{parser::Component, property::Property};
|
||||||
use rustical_dav::xml::TextMatchElement;
|
use rustical_dav::xml::TextMatchElement;
|
||||||
use rustical_ical::AddressObject;
|
use rustical_ical::AddressObject;
|
||||||
@@ -22,25 +22,17 @@ pub struct PropFilterElement {
|
|||||||
pub(crate) text_match: Vec<TextMatchElement>,
|
pub(crate) text_match: Vec<TextMatchElement>,
|
||||||
#[xml(ns = "rustical_dav::namespace::NS_CARDDAV", flatten)]
|
#[xml(ns = "rustical_dav::namespace::NS_CARDDAV", flatten)]
|
||||||
pub(crate) param_filter: Vec<ParamFilterElement>,
|
pub(crate) param_filter: Vec<ParamFilterElement>,
|
||||||
|
#[xml(ty = "attr", default = "Default::default")]
|
||||||
|
pub test: Allof,
|
||||||
|
|
||||||
#[xml(ty = "attr")]
|
#[xml(ty = "attr")]
|
||||||
pub(crate) name: String,
|
pub(crate) name: String,
|
||||||
|
|
||||||
#[xml(ty = "attr")]
|
|
||||||
pub anyof: Option<String>,
|
|
||||||
#[xml(ty = "attr")]
|
|
||||||
pub allof: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PropFilterElement {
|
impl PropFilterElement {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn match_property(&self, property: &Property) -> bool {
|
pub fn match_property(&self, property: &Property) -> bool {
|
||||||
let allof = match (self.allof.is_some(), self.anyof.is_some()) {
|
let Allof(allof) = self.test;
|
||||||
(true, false) => true,
|
|
||||||
(false, _) => false,
|
|
||||||
(true, true) => panic!("wat"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let text_matches = self
|
let text_matches = self
|
||||||
.text_match
|
.text_match
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
@@ -158,7 +158,9 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
address_object::AddressObjectPropName,
|
address_object::AddressObjectPropName,
|
||||||
addressbook::methods::report::addressbook_query::{FilterElement, PropFilterElement},
|
addressbook::methods::report::addressbook_query::{
|
||||||
|
Allof, FilterElement, PropFilterElement,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use rustical_dav::xml::{PropElement, sync_collection::SyncLevel};
|
use rustical_dav::xml::{PropElement, sync_collection::SyncLevel};
|
||||||
|
|
||||||
@@ -250,15 +252,13 @@ mod tests {
|
|||||||
vec![]
|
vec![]
|
||||||
)),
|
)),
|
||||||
filter: FilterElement {
|
filter: FilterElement {
|
||||||
anyof: None,
|
test: Allof::default(),
|
||||||
allof: None,
|
|
||||||
prop_filter: vec![PropFilterElement {
|
prop_filter: vec![PropFilterElement {
|
||||||
name: "FN".to_owned(),
|
name: "FN".to_owned(),
|
||||||
is_not_defined: None,
|
is_not_defined: None,
|
||||||
text_match: vec![],
|
text_match: vec![],
|
||||||
param_filter: vec![],
|
param_filter: vec![],
|
||||||
allof: None,
|
test: Allof::default()
|
||||||
anyof: None
|
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user