aboutsummaryrefslogtreecommitdiff
path: root/aero-dav
diff options
context:
space:
mode:
authorQuentin Dufour <quentin@deuxfleurs.fr>2024-03-12 10:18:13 +0100
committerQuentin Dufour <quentin@deuxfleurs.fr>2024-03-12 10:18:13 +0100
commit442433d70bf13b1641ec76077d9955f5d63ee965 (patch)
treeee48a3a3f579bcb0b14812cee24a45b9660966a5 /aero-dav
parent6d1f538091ca9445cdc0d72b051fa5090b6ec68a (diff)
downloadaerogramme-442433d70bf13b1641ec76077d9955f5d63ee965.tar.gz
aerogramme-442433d70bf13b1641ec76077d9955f5d63ee965.zip
fix parsing
Diffstat (limited to 'aero-dav')
-rw-r--r--aero-dav/src/caldecoder.rs181
-rw-r--r--aero-dav/src/calencoder.rs61
-rw-r--r--aero-dav/src/caltypes.rs9
-rw-r--r--aero-dav/src/xml.rs4
4 files changed, 184 insertions, 71 deletions
diff --git a/aero-dav/src/caldecoder.rs b/aero-dav/src/caldecoder.rs
index 239b005..2e833a1 100644
--- a/aero-dav/src/caldecoder.rs
+++ b/aero-dav/src/caldecoder.rs
@@ -357,25 +357,41 @@ impl QRead<CalendarDataEmpty> for CalendarDataEmpty {
impl QRead<Comp> for Comp {
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
- xml.open(CAL_URN, "comp").await?;
+ let (mut prop_kind, mut comp_kind) = (None, None);
+
+ let bs = xml.open(CAL_URN, "comp").await?;
let name = Component::new(xml.prev_attr("name").ok_or(ParsingError::MissingAttribute)?);
- let additional_rules = Box::pin(xml.maybe_find()).await?;
- xml.close().await?;
- Ok(Self { name, additional_rules })
- }
-}
-impl QRead<CompInner> for CompInner {
- async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
- let (mut prop_kind, mut comp_kind) = (None, None);
+ // Return early if it's an empty tag
+ if matches!(bs, Event::Empty(_)) {
+ xml.close().await?;
+ return Ok(Self { name, prop_kind, comp_kind })
+ }
loop {
let mut dirty = false;
-
- xml.maybe_read(&mut prop_kind, &mut dirty).await?;
- xml.maybe_read(&mut comp_kind, &mut dirty).await?;
+ let (mut tmp_prop_kind, mut tmp_comp_kind): (Option<PropKind>, Option<CompKind>) = (None, None);
+
+ xml.maybe_read(&mut tmp_prop_kind, &mut dirty).await?;
+ Box::pin(xml.maybe_read(&mut tmp_comp_kind, &mut dirty)).await?;
+
+ //@FIXME hack
+ // Merge
+ match (tmp_prop_kind, &mut prop_kind) {
+ (Some(PropKind::Prop(mut a)), Some(PropKind::Prop(ref mut b))) => b.append(&mut a),
+ (Some(PropKind::AllProp), v) => *v = Some(PropKind::AllProp),
+ (Some(x), b) => *b = Some(x),
+ (None, _) => (),
+ };
+ match (tmp_comp_kind, &mut comp_kind) {
+ (Some(CompKind::Comp(mut a)), Some(CompKind::Comp(ref mut b))) => b.append(&mut a),
+ (Some(CompKind::AllComp), v) => *v = Some(CompKind::AllComp),
+ (Some(a), b) => *b = Some(a),
+ (None, _) => (),
+ };
+
- if !dirty {
+ if !dirty {
match xml.peek() {
Event::End(_) => break,
_ => xml.skip().await?,
@@ -383,19 +399,15 @@ impl QRead<CompInner> for CompInner {
}
};
- match (prop_kind, comp_kind) {
- (Some(prop_kind), Some(comp_kind)) => Ok(Self { prop_kind, comp_kind }),
- _ => Err(ParsingError::MissingChild),
- }
+ xml.close().await?;
+ Ok(Self { name, prop_kind, comp_kind })
}
}
impl QRead<CompSupport> for CompSupport {
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
xml.open(CAL_URN, "comp").await?;
- println!("before");
let inner = Component::new(xml.prev_attr("name").ok_or(ParsingError::MissingAttribute)?);
- println!("after");
xml.close().await?;
Ok(Self(inner))
}
@@ -415,13 +427,13 @@ impl QRead<CompKind> for CompKind {
xml.maybe_push(&mut comp, &mut dirty).await?;
if !dirty {
- match xml.peek() {
- Event::End(_) => break,
- _ => xml.skip().await?,
- };
+ break
}
}
- Ok(CompKind::Comp(comp))
+ match &comp[..] {
+ [] => Err(ParsingError::Recoverable),
+ _ => Ok(CompKind::Comp(comp)),
+ }
}
}
@@ -439,13 +451,14 @@ impl QRead<PropKind> for PropKind {
xml.maybe_push(&mut prop, &mut dirty).await?;
if !dirty {
- match xml.peek() {
- Event::End(_) => break,
- _ => xml.skip().await?,
- };
+ break
}
}
- Ok(PropKind::Prop(prop))
+
+ match &prop[..] {
+ [] => Err(ParsingError::Recoverable),
+ _ => Ok(PropKind::Prop(prop)),
+ }
}
}
@@ -687,7 +700,7 @@ impl QRead<TimeZone> for TimeZone {
impl QRead<Filter> for Filter {
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
- xml.open(CAL_URN, "timezone").await?;
+ xml.open(CAL_URN, "filter").await?;
let comp_filter = xml.find().await?;
xml.close().await?;
Ok(Self(comp_filter))
@@ -736,7 +749,7 @@ impl QRead<CalProp> for CalProp {
#[cfg(test)]
mod tests {
use super::*;
- //use chrono::{FixedOffset, TimeZone};
+ use chrono::{Utc, TimeZone};
use crate::realization::Calendar;
//use quick_reader::NsReader;
@@ -803,4 +816,110 @@ END:VCALENDAR]]></C:calendar-timezone>
let got = deserialize::<MkCalendar<Calendar>>(src).await;
assert_eq!(got, expected)
}
+
+ #[tokio::test]
+ async fn rfc_calendar_query() {
+ let expected = CalendarQuery {
+ selector: Some(CalendarSelector::Prop(dav::PropName(vec![
+ dav::PropertyRequest::GetEtag,
+ dav::PropertyRequest::Extension(PropertyRequest::CalendarData(CalendarDataRequest {
+ mime: None,
+ comp: Some(Comp {
+ name: Component::VCalendar,
+ prop_kind: Some(PropKind::Prop(vec![
+ CalProp {
+ name: ComponentProperty("VERSION".into()),
+ novalue: None,
+ }
+ ])),
+ comp_kind: Some(CompKind::Comp(vec![
+ Comp {
+ name: Component::VEvent,
+ prop_kind: Some(PropKind::Prop(vec![
+ CalProp { name: ComponentProperty("SUMMARY".into()), novalue: None },
+ CalProp { name: ComponentProperty("UID".into()), novalue: None },
+ CalProp { name: ComponentProperty("DTSTART".into()), novalue: None },
+ CalProp { name: ComponentProperty("DTEND".into()), novalue: None },
+ CalProp { name: ComponentProperty("DURATION".into()), novalue: None },
+ CalProp { name: ComponentProperty("RRULE".into()), novalue: None },
+ CalProp { name: ComponentProperty("RDATE".into()), novalue: None },
+ CalProp { name: ComponentProperty("EXRULE".into()), novalue: None },
+ CalProp { name: ComponentProperty("EXDATE".into()), novalue: None },
+ CalProp { name: ComponentProperty("RECURRENCE-ID".into()), novalue: None },
+ ])),
+ comp_kind: None,
+ },
+ Comp {
+ name: Component::VTimeZone,
+ prop_kind: None,
+ comp_kind: None,
+ }
+ ])),
+ }),
+ recurrence: None,
+ limit_freebusy_set: None,
+ })),
+ ]))),
+ filter: Filter(CompFilter {
+ name: Component::VCalendar,
+ additional_rules: Some(CompFilterRules::Matches(CompFilterMatch {
+ prop_filter: vec![],
+ comp_filter: vec![
+ CompFilter {
+ name: Component::VEvent,
+ additional_rules: Some(CompFilterRules::Matches(CompFilterMatch {
+ prop_filter: vec![],
+ comp_filter: vec![],
+ time_range: Some(TimeRange::FullRange(
+ Utc.with_ymd_and_hms(2006, 1, 4, 0, 0, 0).unwrap(),
+ Utc.with_ymd_and_hms(2006, 1, 5, 0, 0, 0).unwrap(),
+ )),
+ })),
+ },
+ ],
+ time_range: None,
+ })),
+ }),
+ timezone: None,
+ };
+
+ let src = r#"
+<?xml version="1.0" encoding="utf-8" ?>
+<C:calendar-query xmlns:D="DAV:"
+ xmlns:C="urn:ietf:params:xml:ns:caldav">
+ <D:prop>
+ <D:getetag/>
+ <C:calendar-data>
+ <C:comp name="VCALENDAR">
+ <C:prop name="VERSION"/>
+ <C:comp name="VEVENT">
+ <C:prop name="SUMMARY"/>
+ <C:prop name="UID"/>
+ <C:prop name="DTSTART"/>
+ <C:prop name="DTEND"/>
+ <C:prop name="DURATION"/>
+ <C:prop name="RRULE"/>
+ <C:prop name="RDATE"/>
+ <C:prop name="EXRULE"/>
+ <C:prop name="EXDATE"/>
+ <C:prop name="RECURRENCE-ID"/>
+ </C:comp>
+ <C:comp name="VTIMEZONE"/>
+ </C:comp>
+ </C:calendar-data>
+ </D:prop>
+ <C:filter>
+ <C:comp-filter name="VCALENDAR">
+ <C:comp-filter name="VEVENT">
+ <C:time-range start="20060104T000000Z"
+ end="20060105T000000Z"/>
+ </C:comp-filter>
+ </C:comp-filter>
+ </C:filter>
+</C:calendar-query>
+"#;
+
+ let got = deserialize::<CalendarQuery<Calendar>>(src).await;
+ assert_eq!(got, expected)
+ }
}
diff --git a/aero-dav/src/calencoder.rs b/aero-dav/src/calencoder.rs
index 6ad9f41..fff4d47 100644
--- a/aero-dav/src/calencoder.rs
+++ b/aero-dav/src/calencoder.rs
@@ -353,23 +353,21 @@ impl QWrite for CalendarDataEmpty {
}
}
-impl QWrite for CompInner {
- async fn qwrite(&self, _xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
- unreachable!();
- }
-}
-
impl QWrite for Comp {
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
let mut start = xml.create_cal_element("comp");
start.push_attribute(("name", self.name.as_str()));
- match &self.additional_rules {
- None => xml.q.write_event_async(Event::Empty(start)).await,
- Some(rules) => {
+ match (&self.prop_kind, &self.comp_kind) {
+ (None, None) => xml.q.write_event_async(Event::Empty(start)).await,
+ _ => {
let end = start.to_end();
xml.q.write_event_async(Event::Start(start.clone())).await?;
- rules.prop_kind.qwrite(xml).await?;
- rules.comp_kind.qwrite(xml).await?;
+ if let Some(prop_kind) = &self.prop_kind {
+ prop_kind.qwrite(xml).await?;
+ }
+ if let Some(comp_kind) = &self.comp_kind {
+ comp_kind.qwrite(xml).await?;
+ }
xml.q.write_event_async(Event::End(end)).await
},
}
@@ -721,39 +719,36 @@ mod tests {
mime: None,
comp: Some(Comp {
name: Component::VCalendar,
- additional_rules: Some(CompInner {
- prop_kind: PropKind::Prop(vec![
+ prop_kind: Some(PropKind::Prop(vec![
CalProp {
name: ComponentProperty("VERSION".into()),
novalue: None,
}
- ]),
- comp_kind: CompKind::Comp(vec![
+ ])),
+ comp_kind: Some(CompKind::Comp(vec![
Comp {
name: Component::VEvent,
- additional_rules: Some(CompInner {
- prop_kind: PropKind::Prop(vec![
- CalProp { name: ComponentProperty("SUMMARY".into()), novalue: None },
- CalProp { name: ComponentProperty("UID".into()), novalue: None },
- CalProp { name: ComponentProperty("DTSTART".into()), novalue: None },
- CalProp { name: ComponentProperty("DTEND".into()), novalue: None },
- CalProp { name: ComponentProperty("DURATION".into()), novalue: None },
- CalProp { name: ComponentProperty("RRULE".into()), novalue: None },
- CalProp { name: ComponentProperty("RDATE".into()), novalue: None },
- CalProp { name: ComponentProperty("EXRULE".into()), novalue: None },
- CalProp { name: ComponentProperty("EXDATE".into()), novalue: None },
- CalProp { name: ComponentProperty("RECURRENCE-ID".into()), novalue: None },
- ]),
- comp_kind: CompKind::Comp(vec![]),
- }),
+ prop_kind: Some(PropKind::Prop(vec![
+ CalProp { name: ComponentProperty("SUMMARY".into()), novalue: None },
+ CalProp { name: ComponentProperty("UID".into()), novalue: None },
+ CalProp { name: ComponentProperty("DTSTART".into()), novalue: None },
+ CalProp { name: ComponentProperty("DTEND".into()), novalue: None },
+ CalProp { name: ComponentProperty("DURATION".into()), novalue: None },
+ CalProp { name: ComponentProperty("RRULE".into()), novalue: None },
+ CalProp { name: ComponentProperty("RDATE".into()), novalue: None },
+ CalProp { name: ComponentProperty("EXRULE".into()), novalue: None },
+ CalProp { name: ComponentProperty("EXDATE".into()), novalue: None },
+ CalProp { name: ComponentProperty("RECURRENCE-ID".into()), novalue: None },
+ ])),
+ comp_kind: None,
},
Comp {
name: Component::VTimeZone,
- additional_rules: None,
+ prop_kind: None,
+ comp_kind: None,
}
- ]),
+ ])),
}),
- }),
recurrence: None,
limit_freebusy_set: None,
})),
diff --git a/aero-dav/src/caltypes.rs b/aero-dav/src/caltypes.rs
index a6ea7ce..628ec4b 100644
--- a/aero-dav/src/caltypes.rs
+++ b/aero-dav/src/caltypes.rs
@@ -855,13 +855,8 @@ pub struct CalendarDataSupport {
#[derive(Debug, PartialEq)]
pub struct Comp {
pub name: Component,
- pub additional_rules: Option<CompInner>,
-}
-
-#[derive(Debug, PartialEq)]
-pub struct CompInner {
- pub prop_kind: PropKind,
- pub comp_kind: CompKind,
+ pub prop_kind: Option<PropKind>,
+ pub comp_kind: Option<CompKind>,
}
/// For SupportedCalendarComponentSet
diff --git a/aero-dav/src/xml.rs b/aero-dav/src/xml.rs
index 347a123..2f3b7a6 100644
--- a/aero-dav/src/xml.rs
+++ b/aero-dav/src/xml.rs
@@ -128,6 +128,10 @@ impl<T: IRead> Reader<T> {
&self.cur
}
+ pub fn previous(&self) -> &Event<'static> {
+ &self.prev
+ }
+
// NEW API
pub async fn tag_string(&mut self) -> Result<String, ParsingError> {
self.ensure_parent_has_child()?;