fix parsing
This commit is contained in:
parent
6d1f538091
commit
442433d70b
4 changed files with 185 additions and 72 deletions
|
@ -356,26 +356,42 @@ impl QRead<CalendarDataEmpty> for CalendarDataEmpty {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QRead<Comp> for Comp {
|
impl QRead<Comp> for Comp {
|
||||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
||||||
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> {
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||||
let (mut prop_kind, mut comp_kind) = (None, None);
|
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)?);
|
||||||
|
|
||||||
|
// 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 {
|
loop {
|
||||||
let mut dirty = false;
|
let mut dirty = false;
|
||||||
|
let (mut tmp_prop_kind, mut tmp_comp_kind): (Option<PropKind>, Option<CompKind>) = (None, None);
|
||||||
xml.maybe_read(&mut prop_kind, &mut dirty).await?;
|
|
||||||
xml.maybe_read(&mut comp_kind, &mut dirty).await?;
|
|
||||||
|
|
||||||
if !dirty {
|
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 {
|
||||||
match xml.peek() {
|
match xml.peek() {
|
||||||
Event::End(_) => break,
|
Event::End(_) => break,
|
||||||
_ => xml.skip().await?,
|
_ => xml.skip().await?,
|
||||||
|
@ -383,19 +399,15 @@ impl QRead<CompInner> for CompInner {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match (prop_kind, comp_kind) {
|
xml.close().await?;
|
||||||
(Some(prop_kind), Some(comp_kind)) => Ok(Self { prop_kind, comp_kind }),
|
Ok(Self { name, prop_kind, comp_kind })
|
||||||
_ => Err(ParsingError::MissingChild),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QRead<CompSupport> for CompSupport {
|
impl QRead<CompSupport> for CompSupport {
|
||||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
||||||
xml.open(CAL_URN, "comp").await?;
|
xml.open(CAL_URN, "comp").await?;
|
||||||
println!("before");
|
|
||||||
let inner = Component::new(xml.prev_attr("name").ok_or(ParsingError::MissingAttribute)?);
|
let inner = Component::new(xml.prev_attr("name").ok_or(ParsingError::MissingAttribute)?);
|
||||||
println!("after");
|
|
||||||
xml.close().await?;
|
xml.close().await?;
|
||||||
Ok(Self(inner))
|
Ok(Self(inner))
|
||||||
}
|
}
|
||||||
|
@ -415,13 +427,13 @@ impl QRead<CompKind> for CompKind {
|
||||||
xml.maybe_push(&mut comp, &mut dirty).await?;
|
xml.maybe_push(&mut comp, &mut dirty).await?;
|
||||||
|
|
||||||
if !dirty {
|
if !dirty {
|
||||||
match xml.peek() {
|
break
|
||||||
Event::End(_) => break,
|
|
||||||
_ => xml.skip().await?,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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?;
|
xml.maybe_push(&mut prop, &mut dirty).await?;
|
||||||
|
|
||||||
if !dirty {
|
if !dirty {
|
||||||
match xml.peek() {
|
break
|
||||||
Event::End(_) => break,
|
|
||||||
_ => xml.skip().await?,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 {
|
impl QRead<Filter> for Filter {
|
||||||
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
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?;
|
let comp_filter = xml.find().await?;
|
||||||
xml.close().await?;
|
xml.close().await?;
|
||||||
Ok(Self(comp_filter))
|
Ok(Self(comp_filter))
|
||||||
|
@ -736,7 +749,7 @@ impl QRead<CalProp> for CalProp {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
//use chrono::{FixedOffset, TimeZone};
|
use chrono::{Utc, TimeZone};
|
||||||
use crate::realization::Calendar;
|
use crate::realization::Calendar;
|
||||||
//use quick_reader::NsReader;
|
//use quick_reader::NsReader;
|
||||||
|
|
||||||
|
@ -803,4 +816,110 @@ END:VCALENDAR]]></C:calendar-timezone>
|
||||||
let got = deserialize::<MkCalendar<Calendar>>(src).await;
|
let got = deserialize::<MkCalendar<Calendar>>(src).await;
|
||||||
assert_eq!(got, expected)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
impl QWrite for Comp {
|
||||||
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> {
|
||||||
let mut start = xml.create_cal_element("comp");
|
let mut start = xml.create_cal_element("comp");
|
||||||
start.push_attribute(("name", self.name.as_str()));
|
start.push_attribute(("name", self.name.as_str()));
|
||||||
match &self.additional_rules {
|
match (&self.prop_kind, &self.comp_kind) {
|
||||||
None => xml.q.write_event_async(Event::Empty(start)).await,
|
(None, None) => xml.q.write_event_async(Event::Empty(start)).await,
|
||||||
Some(rules) => {
|
_ => {
|
||||||
let end = start.to_end();
|
let end = start.to_end();
|
||||||
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
xml.q.write_event_async(Event::Start(start.clone())).await?;
|
||||||
rules.prop_kind.qwrite(xml).await?;
|
if let Some(prop_kind) = &self.prop_kind {
|
||||||
rules.comp_kind.qwrite(xml).await?;
|
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
|
xml.q.write_event_async(Event::End(end)).await
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -721,39 +719,36 @@ mod tests {
|
||||||
mime: None,
|
mime: None,
|
||||||
comp: Some(Comp {
|
comp: Some(Comp {
|
||||||
name: Component::VCalendar,
|
name: Component::VCalendar,
|
||||||
additional_rules: Some(CompInner {
|
prop_kind: Some(PropKind::Prop(vec![
|
||||||
prop_kind: PropKind::Prop(vec![
|
|
||||||
CalProp {
|
CalProp {
|
||||||
name: ComponentProperty("VERSION".into()),
|
name: ComponentProperty("VERSION".into()),
|
||||||
novalue: None,
|
novalue: None,
|
||||||
}
|
}
|
||||||
]),
|
])),
|
||||||
comp_kind: CompKind::Comp(vec![
|
comp_kind: Some(CompKind::Comp(vec![
|
||||||
Comp {
|
Comp {
|
||||||
name: Component::VEvent,
|
name: Component::VEvent,
|
||||||
additional_rules: Some(CompInner {
|
prop_kind: Some(PropKind::Prop(vec![
|
||||||
prop_kind: PropKind::Prop(vec![
|
CalProp { name: ComponentProperty("SUMMARY".into()), novalue: None },
|
||||||
CalProp { name: ComponentProperty("SUMMARY".into()), novalue: None },
|
CalProp { name: ComponentProperty("UID".into()), novalue: None },
|
||||||
CalProp { name: ComponentProperty("UID".into()), novalue: None },
|
CalProp { name: ComponentProperty("DTSTART".into()), novalue: None },
|
||||||
CalProp { name: ComponentProperty("DTSTART".into()), novalue: None },
|
CalProp { name: ComponentProperty("DTEND".into()), novalue: None },
|
||||||
CalProp { name: ComponentProperty("DTEND".into()), novalue: None },
|
CalProp { name: ComponentProperty("DURATION".into()), novalue: None },
|
||||||
CalProp { name: ComponentProperty("DURATION".into()), novalue: None },
|
CalProp { name: ComponentProperty("RRULE".into()), novalue: None },
|
||||||
CalProp { name: ComponentProperty("RRULE".into()), novalue: None },
|
CalProp { name: ComponentProperty("RDATE".into()), novalue: None },
|
||||||
CalProp { name: ComponentProperty("RDATE".into()), novalue: None },
|
CalProp { name: ComponentProperty("EXRULE".into()), novalue: None },
|
||||||
CalProp { name: ComponentProperty("EXRULE".into()), novalue: None },
|
CalProp { name: ComponentProperty("EXDATE".into()), novalue: None },
|
||||||
CalProp { name: ComponentProperty("EXDATE".into()), novalue: None },
|
CalProp { name: ComponentProperty("RECURRENCE-ID".into()), novalue: None },
|
||||||
CalProp { name: ComponentProperty("RECURRENCE-ID".into()), novalue: None },
|
])),
|
||||||
]),
|
comp_kind: None,
|
||||||
comp_kind: CompKind::Comp(vec![]),
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
Comp {
|
Comp {
|
||||||
name: Component::VTimeZone,
|
name: Component::VTimeZone,
|
||||||
additional_rules: None,
|
prop_kind: None,
|
||||||
|
comp_kind: None,
|
||||||
}
|
}
|
||||||
]),
|
])),
|
||||||
}),
|
}),
|
||||||
}),
|
|
||||||
recurrence: None,
|
recurrence: None,
|
||||||
limit_freebusy_set: None,
|
limit_freebusy_set: None,
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -855,13 +855,8 @@ pub struct CalendarDataSupport {
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Comp {
|
pub struct Comp {
|
||||||
pub name: Component,
|
pub name: Component,
|
||||||
pub additional_rules: Option<CompInner>,
|
pub prop_kind: Option<PropKind>,
|
||||||
}
|
pub comp_kind: Option<CompKind>,
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub struct CompInner {
|
|
||||||
pub prop_kind: PropKind,
|
|
||||||
pub comp_kind: CompKind,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For SupportedCalendarComponentSet
|
/// For SupportedCalendarComponentSet
|
||||||
|
|
|
@ -128,6 +128,10 @@ impl<T: IRead> Reader<T> {
|
||||||
&self.cur
|
&self.cur
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn previous(&self) -> &Event<'static> {
|
||||||
|
&self.prev
|
||||||
|
}
|
||||||
|
|
||||||
// NEW API
|
// NEW API
|
||||||
pub async fn tag_string(&mut self) -> Result<String, ParsingError> {
|
pub async fn tag_string(&mut self) -> Result<String, ParsingError> {
|
||||||
self.ensure_parent_has_child()?;
|
self.ensure_parent_has_child()?;
|
||||||
|
|
Loading…
Reference in a new issue