432 lines
13 KiB
Rust
432 lines
13 KiB
Rust
use quick_xml::events::Event;
|
|
use chrono::NaiveDateTime;
|
|
|
|
use super::types as dav;
|
|
use super::caltypes::*;
|
|
use super::xml::{QRead, IRead, Reader, Node, CAL_URN};
|
|
use super::error::ParsingError;
|
|
|
|
// ---- ROOT ELEMENTS ---
|
|
impl<E: dav::Extension> QRead<MkCalendar<E>> for MkCalendar<E> {
|
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
xml.open(CAL_URN, "mkcalendar").await?;
|
|
let set = xml.find().await?;
|
|
xml.close().await?;
|
|
Ok(MkCalendar(set))
|
|
}
|
|
}
|
|
|
|
impl<E: dav::Extension, N: Node<N>> QRead<MkCalendarResponse<E,N>> for MkCalendarResponse<E,N> {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl<E: dav::Extension> QRead<CalendarQuery<E>> for CalendarQuery<E> {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl<E: dav::Extension> QRead<CalendarMultiget<E>> for CalendarMultiget<E> {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<FreeBusyQuery> for FreeBusyQuery {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
|
|
// ---- EXTENSIONS ---
|
|
impl QRead<Violation> for Violation {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<Property> for Property {
|
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
if xml.maybe_open(CAL_URN, "calendar-description").await?.is_some() {
|
|
let lang = xml.prev_attr("xml:lang");
|
|
let text = xml.tag_string().await?;
|
|
xml.close().await?;
|
|
return Ok(Property::CalendarDescription { lang, text })
|
|
}
|
|
|
|
if xml.maybe_open(CAL_URN, "calendar-timezone").await?.is_some() {
|
|
let tz = xml.tag_string().await?;
|
|
xml.close().await?;
|
|
return Ok(Property::CalendarTimezone(tz))
|
|
}
|
|
|
|
if xml.maybe_open(CAL_URN, "supported-calendar-component-set").await?.is_some() {
|
|
let comp = xml.collect().await?;
|
|
xml.close().await?;
|
|
return Ok(Property::SupportedCalendarComponentSet(comp))
|
|
}
|
|
|
|
if xml.maybe_open(CAL_URN, "supported-calendar-data").await?.is_some() {
|
|
let mime = xml.collect().await?;
|
|
xml.close().await?;
|
|
return Ok(Property::SupportedCalendarData(mime))
|
|
}
|
|
|
|
if xml.maybe_open(CAL_URN, "max-resource-size").await?.is_some() {
|
|
let sz = xml.tag_string().await?.parse::<u64>()?;
|
|
xml.close().await?;
|
|
return Ok(Property::MaxResourceSize(sz))
|
|
}
|
|
|
|
if xml.maybe_open(CAL_URN, "max-date-time").await?.is_some() {
|
|
let dtstr = xml.tag_string().await?;
|
|
let dt = NaiveDateTime::parse_from_str(dtstr.as_str(), ICAL_DATETIME_FMT)?.and_utc();
|
|
xml.close().await?;
|
|
return Ok(Property::MaxDateTime(dt))
|
|
}
|
|
|
|
if xml.maybe_open(CAL_URN, "max-instances").await?.is_some() {
|
|
let sz = xml.tag_string().await?.parse::<u64>()?;
|
|
xml.close().await?;
|
|
return Ok(Property::MaxInstances(sz))
|
|
}
|
|
|
|
if xml.maybe_open(CAL_URN, "max-attendees-per-instance").await?.is_some() {
|
|
let sz = xml.tag_string().await?.parse::<u64>()?;
|
|
xml.close().await?;
|
|
return Ok(Property::MaxAttendeesPerInstance(sz))
|
|
}
|
|
|
|
if xml.maybe_open(CAL_URN, "supported-collation-set").await?.is_some() {
|
|
let cols = xml.collect().await?;
|
|
xml.close().await?;
|
|
return Ok(Property::SupportedCollationSet(cols))
|
|
}
|
|
|
|
let mut dirty = false;
|
|
let mut caldata: Option<CalendarDataPayload> = None;
|
|
xml.maybe_read(&mut caldata, &mut dirty).await?;
|
|
if let Some(cal) = caldata {
|
|
return Ok(Property::CalendarData(cal))
|
|
}
|
|
|
|
Err(ParsingError::Recoverable)
|
|
}
|
|
}
|
|
|
|
impl QRead<PropertyRequest> for PropertyRequest {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<ResourceType> for ResourceType {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
// ---- INNER XML ----
|
|
impl QRead<SupportedCollation> for SupportedCollation {
|
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
xml.open(CAL_URN, "supported-collation").await?;
|
|
let col = Collation::new(xml.tag_string().await?);
|
|
xml.close().await?;
|
|
Ok(SupportedCollation(col))
|
|
}
|
|
}
|
|
|
|
impl QRead<CalendarDataPayload> for CalendarDataPayload {
|
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
xml.open(CAL_URN, "calendar-data").await?;
|
|
let mime = CalendarDataSupport::qread(xml).await.ok();
|
|
let payload = xml.tag_string().await?;
|
|
xml.close().await?;
|
|
Ok(CalendarDataPayload { mime, payload })
|
|
}
|
|
}
|
|
|
|
impl QRead<CalendarDataSupport> for CalendarDataSupport {
|
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
let ct = xml.prev_attr("content-type");
|
|
let vs = xml.prev_attr("version");
|
|
match (ct, vs) {
|
|
(Some(content_type), Some(version)) => Ok(Self { content_type, version }),
|
|
_ => Err(ParsingError::Recoverable),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl QRead<CalendarDataRequest> for CalendarDataRequest {
|
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
xml.open(CAL_URN, "calendar-data").await?;
|
|
let mime = CalendarDataSupport::qread(xml).await.ok();
|
|
|
|
let (mut comp, mut recurrence, mut limit_freebusy_set) = (None, None, None);
|
|
|
|
loop {
|
|
let mut dirty = false;
|
|
xml.maybe_read(&mut comp, &mut dirty).await?;
|
|
xml.maybe_read(&mut recurrence, &mut dirty).await?;
|
|
xml.maybe_read(&mut limit_freebusy_set, &mut dirty).await?;
|
|
|
|
if !dirty {
|
|
match xml.peek() {
|
|
Event::End(_) => break,
|
|
_ => xml.skip().await?,
|
|
};
|
|
}
|
|
|
|
}
|
|
|
|
xml.close().await?;
|
|
Ok(Self { mime, comp, recurrence, limit_freebusy_set })
|
|
}
|
|
}
|
|
|
|
impl QRead<CalendarDataEmpty> for CalendarDataEmpty {
|
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
xml.open(CAL_URN, "calendar-data").await?;
|
|
let mime = CalendarDataSupport::qread(xml).await.ok();
|
|
xml.close().await?;
|
|
Ok(Self(mime))
|
|
}
|
|
}
|
|
|
|
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> {
|
|
let (mut prop_kind, mut comp_kind) = (None, None);
|
|
|
|
loop {
|
|
let mut dirty = false;
|
|
|
|
xml.maybe_read(&mut prop_kind, &mut dirty).await?;
|
|
xml.maybe_read(&mut comp_kind, &mut dirty).await?;
|
|
|
|
if !dirty {
|
|
match xml.peek() {
|
|
Event::End(_) => break,
|
|
_ => xml.skip().await?,
|
|
};
|
|
}
|
|
};
|
|
|
|
match (prop_kind, comp_kind) {
|
|
(Some(prop_kind), Some(comp_kind)) => Ok(Self { prop_kind, comp_kind }),
|
|
_ => Err(ParsingError::MissingChild),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl QRead<CompSupport> for CompSupport {
|
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
xml.open(CAL_URN, "comp").await?;
|
|
let inner = Component::new(xml.prev_attr("name").ok_or(ParsingError::MissingAttribute)?);
|
|
xml.close().await?;
|
|
Ok(Self(inner))
|
|
}
|
|
}
|
|
|
|
impl QRead<CompKind> for CompKind {
|
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
let mut comp = Vec::new();
|
|
loop {
|
|
let mut dirty = false;
|
|
|
|
if xml.maybe_open(CAL_URN, "allcomp").await?.is_some() {
|
|
xml.close().await?;
|
|
return Ok(CompKind::AllComp)
|
|
}
|
|
|
|
xml.maybe_push(&mut comp, &mut dirty).await?;
|
|
|
|
if !dirty {
|
|
match xml.peek() {
|
|
Event::End(_) => break,
|
|
_ => xml.skip().await?,
|
|
};
|
|
}
|
|
}
|
|
Ok(CompKind::Comp(comp))
|
|
}
|
|
}
|
|
|
|
impl QRead<PropKind> for PropKind {
|
|
async fn qread(xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
let mut prop = Vec::new();
|
|
loop {
|
|
let mut dirty = false;
|
|
|
|
if xml.maybe_open(CAL_URN, "allprop").await?.is_some() {
|
|
xml.close().await?;
|
|
return Ok(PropKind::AllProp)
|
|
}
|
|
|
|
xml.maybe_push(&mut prop, &mut dirty).await?;
|
|
|
|
if !dirty {
|
|
match xml.peek() {
|
|
Event::End(_) => break,
|
|
_ => xml.skip().await?,
|
|
};
|
|
}
|
|
}
|
|
Ok(PropKind::Prop(prop))
|
|
}
|
|
}
|
|
|
|
impl QRead<RecurrenceModifier> for RecurrenceModifier {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<Expand> for Expand {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<LimitRecurrenceSet> for LimitRecurrenceSet {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<LimitFreebusySet> for LimitFreebusySet {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl<E: dav::Extension> QRead<CalendarSelector<E>> for CalendarSelector<E> {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<CompFilter> for CompFilter {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<CompFilterRules> for CompFilterRules {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<CompFilterMatch> for CompFilterMatch {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<PropFilter> for PropFilter {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<PropFilterRules> for PropFilterRules {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<PropFilterMatch> for PropFilterMatch {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<TimeOrText> for TimeOrText {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<TextMatch> for TextMatch {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<ParamFilterMatch> for ParamFilterMatch {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<TimeZone> for TimeZone {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<Filter> for Filter {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<TimeRange> for TimeRange {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
impl QRead<CalProp> for CalProp {
|
|
async fn qread(_xml: &mut Reader<impl IRead>) -> Result<Self, ParsingError> {
|
|
unreachable!();
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
//use chrono::{FixedOffset, TimeZone};
|
|
use crate::realization::Calendar;
|
|
//use quick_reader::NsReader;
|
|
|
|
async fn deserialize<T: Node<T>>(src: &str) -> T {
|
|
let mut rdr = Reader::new(quick_xml::NsReader::from_reader(src.as_bytes())).await.unwrap();
|
|
rdr.find().await.unwrap()
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn basic_mkcalendar() {
|
|
let expected = MkCalendar(dav::Set(dav::PropValue(vec![
|
|
dav::Property::DisplayName("Lisa's Events".into()),
|
|
])));
|
|
|
|
let src = r#"
|
|
<?xml version="1.0" encoding="utf-8" ?>
|
|
<C:mkcalendar xmlns:D="DAV:"
|
|
xmlns:C="urn:ietf:params:xml:ns:caldav">
|
|
<D:set>
|
|
<D:prop>
|
|
<D:displayname>Lisa's Events</D:displayname>
|
|
</D:prop>
|
|
</D:set>
|
|
</C:mkcalendar>
|
|
"#;
|
|
let got = deserialize::<MkCalendar<Calendar>>(src).await;
|
|
assert_eq!(got, expected)
|
|
}
|
|
}
|