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 QRead> for MkCalendar { async fn qread(xml: &mut Reader) -> Result { xml.open(CAL_URN, "mkcalendar").await?; let set = xml.find().await?; xml.close().await?; Ok(MkCalendar(set)) } } impl> QRead> for MkCalendarResponse { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead> for CalendarQuery { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead> for CalendarMultiget { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for FreeBusyQuery { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } // ---- EXTENSIONS --- impl QRead for Violation { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for Property { async fn qread(xml: &mut Reader) -> Result { 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::()?; 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::()?; 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::()?; 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 = None; xml.maybe_read(&mut caldata, &mut dirty).await?; if let Some(cal) = caldata { return Ok(Property::CalendarData(cal)) } Err(ParsingError::Recoverable) } } impl QRead for PropertyRequest { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for ResourceType { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } // ---- INNER XML ---- impl QRead for SupportedCollation { async fn qread(xml: &mut Reader) -> Result { xml.open(CAL_URN, "supported-collation").await?; let col = Collation::new(xml.tag_string().await?); xml.close().await?; Ok(SupportedCollation(col)) } } impl QRead for CalendarDataPayload { async fn qread(xml: &mut Reader) -> Result { 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 for CalendarDataSupport { async fn qread(xml: &mut Reader) -> Result { 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 for CalendarDataRequest { async fn qread(xml: &mut Reader) -> Result { 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 for CalendarDataEmpty { async fn qread(xml: &mut Reader) -> Result { xml.open(CAL_URN, "calendar-data").await?; let mime = CalendarDataSupport::qread(xml).await.ok(); xml.close().await?; Ok(Self(mime)) } } impl QRead for Comp { async fn qread(xml: &mut Reader) -> Result { 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 for CompInner { async fn qread(xml: &mut Reader) -> Result { 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 for CompSupport { async fn qread(xml: &mut Reader) -> Result { 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 for CompKind { async fn qread(xml: &mut Reader) -> Result { 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 for PropKind { async fn qread(xml: &mut Reader) -> Result { 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 for RecurrenceModifier { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for Expand { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for LimitRecurrenceSet { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for LimitFreebusySet { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead> for CalendarSelector { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for CompFilter { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for CompFilterRules { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for CompFilterMatch { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for PropFilter { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for PropFilterRules { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for PropFilterMatch { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for TimeOrText { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for TextMatch { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for ParamFilterMatch { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for TimeZone { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for Filter { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for TimeRange { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } impl QRead for CalProp { async fn qread(_xml: &mut Reader) -> Result { unreachable!(); } } #[cfg(test)] mod tests { use super::*; //use chrono::{FixedOffset, TimeZone}; use crate::realization::Calendar; //use quick_reader::NsReader; async fn deserialize>(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#" Lisa's Events "#; let got = deserialize::>(src).await; assert_eq!(got, expected) } }