diff options
Diffstat (limited to 'src/dav/calencoder.rs')
-rw-r--r-- | src/dav/calencoder.rs | 886 |
1 files changed, 0 insertions, 886 deletions
diff --git a/src/dav/calencoder.rs b/src/dav/calencoder.rs deleted file mode 100644 index 58b88c7..0000000 --- a/src/dav/calencoder.rs +++ /dev/null @@ -1,886 +0,0 @@ -use quick_xml::Error as QError; -use quick_xml::events::{Event, BytesEnd, BytesStart, BytesText}; -use quick_xml::name::PrefixDeclaration; -use tokio::io::AsyncWrite; - -use super::caltypes::*; -use super::xml::{Node, QWrite, IWrite, Writer}; -use super::types::Extension; - -const ICAL_DATETIME_FMT: &str = "%Y%m%dT%H%M%SZ"; - -// ==================== Calendar Types Serialization ========================= - -// -------------------- MKCALENDAR METHOD ------------------------------------ -impl<E: Extension> QWrite for MkCalendar<E> { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let start = xml.create_cal_element("mkcalendar"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - self.0.qwrite(xml).await?; - xml.q.write_event_async(Event::End(end)).await - } -} - -impl<E: Extension, N: Node<N>> QWrite for MkCalendarResponse<E,N> { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let start = xml.create_cal_element("mkcalendar-response"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - for propstat in self.0.iter() { - propstat.qwrite(xml).await?; - } - xml.q.write_event_async(Event::End(end)).await - } -} - -// ----------------------- REPORT METHOD ------------------------------------- - -impl<E: Extension> QWrite for CalendarQuery<E> { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let start = xml.create_cal_element("calendar-query"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - if let Some(selector) = &self.selector { - selector.qwrite(xml).await?; - } - self.filter.qwrite(xml).await?; - if let Some(tz) = &self.timezone { - tz.qwrite(xml).await?; - } - xml.q.write_event_async(Event::End(end)).await - } -} - -impl<E: Extension> QWrite for CalendarMultiget<E> { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let start = xml.create_cal_element("calendar-multiget"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - if let Some(selector) = &self.selector { - selector.qwrite(xml).await?; - } - for href in self.href.iter() { - href.qwrite(xml).await?; - } - xml.q.write_event_async(Event::End(end)).await - } -} - -impl QWrite for FreeBusyQuery { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let start = xml.create_cal_element("free-busy-query"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - self.0.qwrite(xml).await?; - xml.q.write_event_async(Event::End(end)).await - } -} - -// -------------------------- DAV::prop -------------------------------------- -impl QWrite for PropertyRequest { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut atom = async |c| { - let empty_tag = xml.create_cal_element(c); - xml.q.write_event_async(Event::Empty(empty_tag)).await - }; - - match self { - Self::CalendarDescription => atom("calendar-description").await, - Self::CalendarTimezone => atom("calendar-timezone").await, - Self::SupportedCalendarComponentSet => atom("supported-calendar-component-set").await, - Self::SupportedCalendarData => atom("supported-calendar-data").await, - Self::MaxResourceSize => atom("max-resource-size").await, - Self::MinDateTime => atom("min-date-time").await, - Self::MaxDateTime => atom("max-date-time").await, - Self::MaxInstances => atom("max-instances").await, - Self::MaxAttendeesPerInstance => atom("max-attendees-per-instance").await, - Self::SupportedCollationSet => atom("supported-collation-set").await, - Self::CalendarData(req) => req.qwrite(xml).await, - } - } -} -impl QWrite for Property { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - match self { - Self::CalendarDescription { lang, text } => { - let mut start = xml.create_cal_element("calendar-description"); - if let Some(the_lang) = lang { - start.push_attribute(("xml:lang", the_lang.as_str())); - } - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - xml.q.write_event_async(Event::Text(BytesText::new(text))).await?; - xml.q.write_event_async(Event::End(end)).await - }, - Self::CalendarTimezone(payload) => { - let start = xml.create_cal_element("calendar-timezone"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - xml.q.write_event_async(Event::Text(BytesText::new(payload))).await?; - xml.q.write_event_async(Event::End(end)).await - }, - Self::SupportedCalendarComponentSet(many_comp) => { - let start = xml.create_cal_element("supported-calendar-component-set"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - for comp in many_comp.iter() { - comp.qwrite(xml).await?; - } - xml.q.write_event_async(Event::End(end)).await - }, - Self::SupportedCalendarData(many_mime) => { - let start = xml.create_cal_element("supported-calendar-data"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - for mime in many_mime.iter() { - mime.qwrite(xml).await?; - } - xml.q.write_event_async(Event::End(end)).await - }, - Self::MaxResourceSize(bytes) => { - let start = xml.create_cal_element("max-resource-size"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - xml.q.write_event_async(Event::Text(BytesText::new(bytes.to_string().as_str()))).await?; - xml.q.write_event_async(Event::End(end)).await - }, - Self::MinDateTime(dt) => { - let start = xml.create_cal_element("min-date-time"); - let end = start.to_end(); - - let dtstr = format!("{}", dt.format(ICAL_DATETIME_FMT)); - xml.q.write_event_async(Event::Start(start.clone())).await?; - xml.q.write_event_async(Event::Text(BytesText::new(dtstr.as_str()))).await?; - xml.q.write_event_async(Event::End(end)).await - }, - Self::MaxDateTime(dt) => { - let start = xml.create_cal_element("max-date-time"); - let end = start.to_end(); - - let dtstr = format!("{}", dt.format(ICAL_DATETIME_FMT)); - xml.q.write_event_async(Event::Start(start.clone())).await?; - xml.q.write_event_async(Event::Text(BytesText::new(dtstr.as_str()))).await?; - xml.q.write_event_async(Event::End(end)).await - }, - Self::MaxInstances(count) => { - let start = xml.create_cal_element("max-instances"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - xml.q.write_event_async(Event::Text(BytesText::new(count.to_string().as_str()))).await?; - xml.q.write_event_async(Event::End(end)).await - }, - Self::MaxAttendeesPerInstance(count) => { - let start = xml.create_cal_element("max-attendees-per-instance"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - xml.q.write_event_async(Event::Text(BytesText::new(count.to_string().as_str()))).await?; - xml.q.write_event_async(Event::End(end)).await - }, - Self::SupportedCollationSet(many_collations) => { - let start = xml.create_cal_element("supported-collation-set"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - for collation in many_collations.iter() { - collation.qwrite(xml).await?; - } - xml.q.write_event_async(Event::End(end)).await - }, - Self::CalendarData(inner) => inner.qwrite(xml).await, - } - } -} - -// ---------------------- DAV::resourcetype ---------------------------------- -impl QWrite for ResourceType { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - match self { - Self::Calendar => { - let empty_tag = xml.create_dav_element("calendar"); - xml.q.write_event_async(Event::Empty(empty_tag)).await - }, - } - } -} - -// --------------------------- DAV::error ------------------------------------ -impl QWrite for Violation { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut atom = async |c| { - let empty_tag = xml.create_cal_element(c); - xml.q.write_event_async(Event::Empty(empty_tag)).await - }; - - match self { - //@FIXME - // DAV elements, should not be here but in RFC3744 on ACLs - // (we do not use atom as this error is in the DAV namespace, not the caldav one) - Self::NeedPrivileges => { - let empty_tag = xml.create_dav_element("need-privileges"); - xml.q.write_event_async(Event::Empty(empty_tag)).await - }, - - // Regular CalDAV errors - Self::ResourceMustBeNull => atom("resource-must-be-null").await, - Self::CalendarCollectionLocationOk => atom("calendar-collection-location-ok").await, - Self::ValidCalendarData => atom("valid-calendar-data").await, - Self::InitializeCalendarCollection => atom("initialize-calendar-collection").await, - Self::SupportedCalendarData => atom("supported-calendar-data").await, - Self::ValidCalendarObjectResource => atom("valid-calendar-object-resource").await, - Self::SupportedCalendarComponent => atom("supported-calendar-component").await, - Self::NoUidConflict(href) => { - let start = xml.create_cal_element("no-uid-conflict"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - href.qwrite(xml).await?; - xml.q.write_event_async(Event::End(end)).await - }, - Self::MaxResourceSize => atom("max-resource-size").await, - Self::MinDateTime => atom("min-date-time").await, - Self::MaxDateTime => atom("max-date-time").await, - Self::MaxInstances => atom("max-instances").await, - Self::MaxAttendeesPerInstance => atom("max-attendees-per-instance").await, - Self::ValidFilter => atom("valid-filter").await, - Self::SupportedFilter { comp, prop, param } => { - let start = xml.create_cal_element("supported-filter"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - for comp_item in comp.iter() { - comp_item.qwrite(xml).await?; - } - for prop_item in prop.iter() { - prop_item.qwrite(xml).await?; - } - for param_item in param.iter() { - param_item.qwrite(xml).await?; - } - xml.q.write_event_async(Event::End(end)).await - }, - Self::NumberOfMatchesWithinLimits => atom("number-of-matches-within-limits").await, - } - } -} - - -// ---------------------------- Inner XML ------------------------------------ -impl QWrite for SupportedCollation { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let start = xml.create_cal_element("supported-collation"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - self.0.qwrite(xml).await?; - xml.q.write_event_async(Event::End(end)).await - - } -} - -impl QWrite for Collation { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let col = match self { - Self::AsciiCaseMap => "i;ascii-casemap", - Self::Octet => "i;octet", - Self::Unknown(v) => v.as_str(), - }; - - xml.q.write_event_async(Event::Text(BytesText::new(col))).await - } -} - -impl QWrite for CalendarDataPayload { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut start = xml.create_cal_element("calendar-data"); - if let Some(mime) = &self.mime { - start.push_attribute(("content-type", mime.content_type.as_str())); - start.push_attribute(("version", mime.version.as_str())); - } - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - xml.q.write_event_async(Event::Text(BytesText::new(self.payload.as_str()))).await?; - xml.q.write_event_async(Event::End(end)).await - } -} - -impl QWrite for CalendarDataRequest { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut start = xml.create_cal_element("calendar-data"); - if let Some(mime) = &self.mime { - start.push_attribute(("content-type", mime.content_type.as_str())); - start.push_attribute(("version", mime.version.as_str())); - } - let end = start.to_end(); - xml.q.write_event_async(Event::Start(start.clone())).await?; - if let Some(comp) = &self.comp { - comp.qwrite(xml).await?; - } - if let Some(recurrence) = &self.recurrence { - recurrence.qwrite(xml).await?; - } - if let Some(freebusy) = &self.limit_freebusy_set { - freebusy.qwrite(xml).await?; - } - xml.q.write_event_async(Event::End(end)).await - } -} - -impl QWrite for CalendarDataEmpty { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut empty = xml.create_cal_element("calendar-data"); - if let Some(mime) = &self.0 { - empty.push_attribute(("content-type", mime.content_type.as_str())); - empty.push_attribute(("version", mime.version.as_str())); - } - xml.q.write_event_async(Event::Empty(empty)).await - } -} - -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) => { - 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?; - xml.q.write_event_async(Event::End(end)).await - }, - } - } -} - -impl QWrite for CompSupport { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut empty = xml.create_cal_element("comp"); - empty.push_attribute(("name", self.0.as_str())); - xml.q.write_event_async(Event::Empty(empty)).await - } -} - -impl QWrite for CompKind { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - match self { - Self::AllComp => { - let empty_tag = xml.create_cal_element("allcomp"); - xml.q.write_event_async(Event::Empty(empty_tag)).await - }, - Self::Comp(many_comp) => { - for comp in many_comp.iter() { - // Required: recursion in an async fn requires boxing - // rustc --explain E0733 - Box::pin(comp.qwrite(xml)).await?; - } - Ok(()) - } - } - } -} - -impl QWrite for PropKind { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - match self { - Self::AllProp => { - let empty_tag = xml.create_cal_element("allprop"); - xml.q.write_event_async(Event::Empty(empty_tag)).await - }, - Self::Prop(many_prop) => { - for prop in many_prop.iter() { - prop.qwrite(xml).await?; - } - Ok(()) - } - } - } -} - -impl QWrite for CalProp { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut empty = xml.create_cal_element("prop"); - empty.push_attribute(("name", self.name.0.as_str())); - match self.novalue { - None => (), - Some(true) => empty.push_attribute(("novalue", "yes")), - Some(false) => empty.push_attribute(("novalue", "no")), - } - xml.q.write_event_async(Event::Empty(empty)).await - } -} - -impl QWrite for RecurrenceModifier { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - match self { - Self::Expand(exp) => exp.qwrite(xml).await, - Self::LimitRecurrenceSet(lrs) => lrs.qwrite(xml).await, - } - } -} - -impl QWrite for Expand { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut empty = xml.create_cal_element("expand"); - empty.push_attribute(("start", format!("{}", self.0.format(ICAL_DATETIME_FMT)).as_str())); - empty.push_attribute(("end", format!("{}", self.1.format(ICAL_DATETIME_FMT)).as_str())); - xml.q.write_event_async(Event::Empty(empty)).await - } -} - -impl QWrite for LimitRecurrenceSet { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut empty = xml.create_cal_element("limit-recurrence-set"); - empty.push_attribute(("start", format!("{}", self.0.format(ICAL_DATETIME_FMT)).as_str())); - empty.push_attribute(("end", format!("{}", self.1.format(ICAL_DATETIME_FMT)).as_str())); - xml.q.write_event_async(Event::Empty(empty)).await - } -} - -impl QWrite for LimitFreebusySet { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut empty = xml.create_cal_element("limit-freebusy-set"); - empty.push_attribute(("start", format!("{}", self.0.format(ICAL_DATETIME_FMT)).as_str())); - empty.push_attribute(("end", format!("{}", self.1.format(ICAL_DATETIME_FMT)).as_str())); - xml.q.write_event_async(Event::Empty(empty)).await - } -} - -impl<E: Extension> QWrite for CalendarSelector<E> { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - match self { - Self::AllProp => { - let empty_tag = xml.create_dav_element("allprop"); - xml.q.write_event_async(Event::Empty(empty_tag)).await - }, - Self::PropName => { - let empty_tag = xml.create_dav_element("propname"); - xml.q.write_event_async(Event::Empty(empty_tag)).await - }, - Self::Prop(prop) => prop.qwrite(xml).await, - } - } -} - -impl QWrite for CompFilter { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut start = xml.create_cal_element("comp-filter"); - start.push_attribute(("name", self.name.as_str())); - - match &self.additional_rules { - None => xml.q.write_event_async(Event::Empty(start)).await, - Some(rules) => { - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - rules.qwrite(xml).await?; - xml.q.write_event_async(Event::End(end)).await - } - } - } -} - -impl QWrite for CompFilterRules { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - match self { - Self::IsNotDefined => { - let empty_tag = xml.create_dav_element("is-not-defined"); - xml.q.write_event_async(Event::Empty(empty_tag)).await - }, - Self::Matches(cfm) => cfm.qwrite(xml).await, - } - } -} - -impl QWrite for CompFilterMatch { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - if let Some(time_range) = &self.time_range { - time_range.qwrite(xml).await?; - } - - for prop_item in self.prop_filter.iter() { - prop_item.qwrite(xml).await?; - } - for comp_item in self.comp_filter.iter() { - // Required: recursion in an async fn requires boxing - // rustc --explain E0733 - Box::pin(comp_item.qwrite(xml)).await?; - } - Ok(()) - } -} - -impl QWrite for PropFilter { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut start = xml.create_cal_element("prop-filter"); - start.push_attribute(("name", self.name.as_str())); - - match &self.additional_rules { - None => xml.q.write_event_async(Event::Empty(start.clone())).await, - Some(rules) => { - let end = start.to_end(); - xml.q.write_event_async(Event::Start(start.clone())).await?; - rules.qwrite(xml).await?; - xml.q.write_event_async(Event::End(end)).await - } - } - } -} - -impl QWrite for PropFilterRules { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - match self { - Self::IsNotDefined => { - let empty_tag = xml.create_dav_element("is-not-defined"); - xml.q.write_event_async(Event::Empty(empty_tag)).await - }, - Self::Match(prop_match) => prop_match.qwrite(xml).await, - } - } -} - -impl QWrite for PropFilterMatch { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - if let Some(time_range) = &self.time_range { - time_range.qwrite(xml).await?; - } - if let Some(time_or_text) = &self.time_or_text { - time_or_text.qwrite(xml).await?; - } - for param_item in self.param_filter.iter() { - param_item.qwrite(xml).await?; - } - Ok(()) - } -} - -impl QWrite for TimeOrText { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - match self { - Self::Time(time) => time.qwrite(xml).await, - Self::Text(txt) => txt.qwrite(xml).await, - } - } -} - -impl QWrite for TextMatch { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut start = xml.create_cal_element("text-match"); - if let Some(collation) = &self.collation { - start.push_attribute(("collation", collation.as_str())); - } - match self.negate_condition { - None => (), - Some(true) => start.push_attribute(("negate-condition", "yes")), - Some(false) => start.push_attribute(("negate-condition", "no")), - } - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - xml.q.write_event_async(Event::Text(BytesText::new(self.text.as_str()))).await?; - xml.q.write_event_async(Event::End(end)).await - } -} - -impl QWrite for ParamFilter { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut start = xml.create_cal_element("param-filter"); - start.push_attribute(("name", self.name.as_str())); - - match &self.additional_rules { - None => xml.q.write_event_async(Event::Empty(start)).await, - Some(rules) => { - let end = start.to_end(); - xml.q.write_event_async(Event::Start(start.clone())).await?; - rules.qwrite(xml).await?; - xml.q.write_event_async(Event::End(end)).await - } - } - } -} - -impl QWrite for ParamFilterMatch { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - match self { - Self::IsNotDefined => { - let empty_tag = xml.create_dav_element("is-not-defined"); - xml.q.write_event_async(Event::Empty(empty_tag)).await - }, - Self::Match(tm) => tm.qwrite(xml).await, - } - } -} - -impl QWrite for TimeZone { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut start = xml.create_cal_element("timezone"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - xml.q.write_event_async(Event::Text(BytesText::new(self.0.as_str()))).await?; - xml.q.write_event_async(Event::End(end)).await - } -} - -impl QWrite for Filter { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut start = xml.create_cal_element("filter"); - let end = start.to_end(); - - xml.q.write_event_async(Event::Start(start.clone())).await?; - self.0.qwrite(xml).await?; - xml.q.write_event_async(Event::End(end)).await - } -} - -impl QWrite for TimeRange { - async fn qwrite(&self, xml: &mut Writer<impl IWrite>) -> Result<(), QError> { - let mut empty = xml.create_cal_element("time-range"); - match self { - Self::OnlyStart(start) => empty.push_attribute(("start", format!("{}", start.format(ICAL_DATETIME_FMT)).as_str())), - Self::OnlyEnd(end) => empty.push_attribute(("end", format!("{}", end.format(ICAL_DATETIME_FMT)).as_str())), - Self::FullRange(start, end) => { - empty.push_attribute(("start", format!("{}", start.format(ICAL_DATETIME_FMT)).as_str())); - empty.push_attribute(("end", format!("{}", end.format(ICAL_DATETIME_FMT)).as_str())); - } - } - xml.q.write_event_async(Event::Empty(empty)).await - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::dav::types as dav; - use crate::dav::realization::Calendar; - use tokio::io::AsyncWriteExt; - use chrono::{Utc,TimeZone,DateTime}; - - async fn serialize(elem: &impl QWrite) -> String { - let mut buffer = Vec::new(); - let mut tokio_buffer = tokio::io::BufWriter::new(&mut buffer); - let q = quick_xml::writer::Writer::new_with_indent(&mut tokio_buffer, b' ', 4); - let ns_to_apply = vec![ - ("xmlns:D".into(), "DAV:".into()), - ("xmlns:C".into(), "urn:ietf:params:xml:ns:caldav".into()), - ]; - let mut writer = Writer { q, ns_to_apply }; - - elem.qwrite(&mut writer).await.expect("xml serialization"); - tokio_buffer.flush().await.expect("tokio buffer flush"); - let got = std::str::from_utf8(buffer.as_slice()).unwrap(); - - return got.into() - } - - #[tokio::test] - async fn basic_violation() { - let got = serialize( - &dav::Error::<Calendar>(vec![ - dav::Violation::Extension(Violation::ResourceMustBeNull), - ]) - ).await; - - let expected = r#"<D:error xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav"> - <C:resource-must-be-null/> -</D:error>"#; - - assert_eq!(&got, expected, "\n---GOT---\n{got}\n---EXP---\n{expected}\n"); - } - - #[tokio::test] - async fn rfc_calendar_query1_req() { - let got = serialize( - &CalendarQuery::<Calendar> { - selector: Some(CalendarSelector::Prop(dav::PropName(vec![ - dav::PropertyRequest::GetEtag, - dav::PropertyRequest::Extension(PropertyRequest::CalendarData(CalendarDataRequest { - mime: None, - comp: Some(Comp { - name: Component::VCalendar, - additional_rules: Some(CompInner { - prop_kind: PropKind::Prop(vec![ - CalProp { - name: ComponentProperty("VERSION".into()), - novalue: None, - } - ]), - comp_kind: 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![]), - }), - }, - Comp { - name: Component::VTimeZone, - additional_rules: None, - } - ]), - }), - }), - recurrence: None, - limit_freebusy_set: None, - })), - ]))), - filter: Filter(CompFilter { - name: Component::VCalendar, - additional_rules: Some(CompFilterRules::Matches(CompFilterMatch { - time_range: None, - prop_filter: vec![], - comp_filter: vec![ - CompFilter { - name: Component::VEvent, - additional_rules: Some(CompFilterRules::Matches(CompFilterMatch { - 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(), - )), - prop_filter: vec![], - comp_filter: vec![], - })), - }, - ], - })), - }), - timezone: None, - } - ).await; - - let expected = r#"<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>"#; - - assert_eq!(&got, expected, "\n---GOT---\n{got}\n---EXP---\n{expected}\n"); - } - - #[tokio::test] - async fn rfc_calendar_query1_res() { - let got = serialize( - &dav::Multistatus::<Calendar,dav::PropValue<Calendar>> { - responses: vec![ - dav::Response { - status_or_propstat: dav::StatusOrPropstat::PropStat( - dav::Href("http://cal.example.com/bernard/work/abcd2.ics".into()), - vec![dav::PropStat { - prop: dav::PropValue(vec![ - dav::Property::GetEtag("\"fffff-abcd2\"".into()), - dav::Property::Extension(Property::CalendarData(CalendarDataPayload { - mime: None, - payload: "PLACEHOLDER".into() - })), - ]), - status: dav::Status(http::status::StatusCode::OK), - error: None, - responsedescription: None, - }] - ), - location: None, - error: None, - responsedescription: None, - }, - dav::Response { - status_or_propstat: dav::StatusOrPropstat::PropStat( - dav::Href("http://cal.example.com/bernard/work/abcd3.ics".into()), - vec![dav::PropStat { - prop: dav::PropValue(vec![ - dav::Property::GetEtag("\"fffff-abcd3\"".into()), - dav::Property::Extension(Property::CalendarData(CalendarDataPayload{ - mime: None, - payload: "PLACEHOLDER".into(), - })), - ]), - status: dav::Status(http::status::StatusCode::OK), - error: None, - responsedescription: None, - }] - ), - location: None, - error: None, - responsedescription: None, - }, - ], - responsedescription: None, - }, - ).await; - - let expected = r#"<D:multistatus xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav"> - <D:response> - <D:href>http://cal.example.com/bernard/work/abcd2.ics</D:href> - <D:propstat> - <D:prop> - <D:getetag>"fffff-abcd2"</D:getetag> - <C:calendar-data>PLACEHOLDER</C:calendar-data> - </D:prop> - <D:status>HTTP/1.1 200 OK</D:status> - </D:propstat> - </D:response> - <D:response> - <D:href>http://cal.example.com/bernard/work/abcd3.ics</D:href> - <D:propstat> - <D:prop> - <D:getetag>"fffff-abcd3"</D:getetag> - <C:calendar-data>PLACEHOLDER</C:calendar-data> - </D:prop> - <D:status>HTTP/1.1 200 OK</D:status> - </D:propstat> - </D:response> -</D:multistatus>"#; - - - assert_eq!(&got, expected, "\n---GOT---\n{got}\n---EXP---\n{expected}\n"); - } -} |