carddav: Fix filter test="allof"|"anyof"

This commit is contained in:
Lennart
2025-12-31 14:46:49 +01:00
parent e5d6541ffb
commit 845b3e61e3
4 changed files with 35 additions and 31 deletions

View File

@@ -1,9 +1,8 @@
use super::FilterElement;
use rstest::rstest;
use rustical_ical::CalendarObject;
use rustical_xml::XmlDocument;
use crate::calendar::methods::report::calendar_query::FilterElement;
const ICS_1: &str = r"BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN

View File

@@ -2,10 +2,11 @@ use crate::{
address_object::AddressObjectPropWrapperName,
addressbook::methods::report::addressbook_query::PropFilterElement,
};
use derive_more::{From, Into};
use ical::property::Property;
use rustical_dav::xml::{PropfindType, TextMatchElement};
use rustical_ical::{AddressObject, UtcDateTime};
use rustical_xml::XmlDeserialize;
use rustical_xml::{ValueDeserialize, XmlDeserialize, XmlRootTag};
#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)]
#[allow(dead_code)]
@@ -46,18 +47,34 @@ impl ParamFilterElement {
}
}
#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)]
#[allow(dead_code)]
#[derive(Clone, Debug, PartialEq, Eq, Default, From, Into)]
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*)>
// <!ATTLIST filter test (anyof | allof) "anyof">
// <!-- test value:
// anyof logical OR 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 {
#[xml(ty = "attr")]
pub anyof: Option<String>,
#[xml(ty = "attr")]
pub allof: Option<String>,
#[xml(ty = "attr", default = "Default::default")]
pub test: Allof,
#[xml(ns = "rustical_dav::namespace::NS_CARDDAV", flatten)]
pub(crate) prop_filter: Vec<PropFilterElement>,
}
@@ -65,11 +82,7 @@ pub struct FilterElement {
impl FilterElement {
#[must_use]
pub fn matches(&self, addr_object: &AddressObject) -> bool {
let allof = match (self.allof.is_some(), self.anyof.is_some()) {
(true, false) => true,
(false, _) => false,
(true, true) => panic!("wat"),
};
let Allof(allof) = self.test;
let mut results = self
.prop_filter
.iter()

View File

@@ -1,4 +1,4 @@
use super::ParamFilterElement;
use super::{Allof, ParamFilterElement};
use ical::{parser::Component, property::Property};
use rustical_dav::xml::TextMatchElement;
use rustical_ical::AddressObject;
@@ -22,25 +22,17 @@ pub struct PropFilterElement {
pub(crate) text_match: Vec<TextMatchElement>,
#[xml(ns = "rustical_dav::namespace::NS_CARDDAV", flatten)]
pub(crate) param_filter: Vec<ParamFilterElement>,
#[xml(ty = "attr", default = "Default::default")]
pub test: Allof,
#[xml(ty = "attr")]
pub(crate) name: String,
#[xml(ty = "attr")]
pub anyof: Option<String>,
#[xml(ty = "attr")]
pub allof: Option<String>,
}
impl PropFilterElement {
#[must_use]
pub fn match_property(&self, property: &Property) -> bool {
let allof = match (self.allof.is_some(), self.anyof.is_some()) {
(true, false) => true,
(false, _) => false,
(true, true) => panic!("wat"),
};
let Allof(allof) = self.test;
let text_matches = self
.text_match
.iter()

View File

@@ -158,7 +158,9 @@ mod tests {
use super::*;
use crate::{
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};
@@ -250,15 +252,13 @@ mod tests {
vec![]
)),
filter: FilterElement {
anyof: None,
allof: None,
test: Allof::default(),
prop_filter: vec![PropFilterElement {
name: "FN".to_owned(),
is_not_defined: None,
text_match: vec![],
param_filter: vec![],
allof: None,
anyof: None
test: Allof::default()
}]
}
})