use crate::{namespace::Namespace, xml::TagList}; use actix_web::{ body::BoxBody, http::header::ContentType, HttpRequest, HttpResponse, Responder, ResponseError, }; use log::debug; use serde::Serialize; // Intermediate struct because of a serde limitation, see following article: // https://stackoverflow.com/questions/78444158/unsupportedcannot-serialize-enum-newtype-variant-exampledata #[derive(Serialize)] pub struct PropTagWrapper { #[serde(rename = "$value")] pub prop: Vec, } // RFC 2518 // #[derive(Serialize)] #[serde(rename_all = "kebab-case")] pub struct PropstatElement { pub prop: PropType, pub status: String, } #[derive(Serialize)] #[serde(untagged)] pub enum PropstatWrapper { Normal(PropstatElement>), TagList(PropstatElement), } // RFC 2518 // #[derive(Serialize)] #[serde(rename_all = "kebab-case")] pub struct ResponseElement { pub href: String, #[serde(skip_serializing_if = "Option::is_none")] pub status: Option, pub propstat: Vec, } impl Default for ResponseElement { fn default() -> Self { Self { href: String::new(), status: None, propstat: vec![], } } } // RFC 2518 // // Extended by sync-token as specified in RFC 6578 #[derive(Serialize)] #[serde(rename = "multistatus", rename_all = "kebab-case")] pub struct MultistatusElement { #[serde(rename = "response")] pub responses: Vec>, #[serde(rename = "response")] pub member_responses: Vec>, #[serde(rename = "@xmlns")] pub ns_dav: &'static str, #[serde(rename = "@xmlns:C")] pub ns_caldav: &'static str, #[serde(rename = "@xmlns:IC")] pub ns_ical: &'static str, #[serde(skip_serializing_if = "Option::is_none")] pub sync_token: Option, } impl Default for MultistatusElement { fn default() -> Self { Self { responses: vec![], member_responses: vec![], ns_dav: Namespace::Dav.as_str(), ns_caldav: Namespace::CalDAV.as_str(), ns_ical: Namespace::ICal.as_str(), sync_token: None, } } } impl Responder for MultistatusElement { type Body = BoxBody; fn respond_to(self, _req: &HttpRequest) -> HttpResponse { let mut output = "\n".to_owned(); let mut ser = quick_xml::se::Serializer::new(&mut output); ser.indent(' ', 4); if let Err(err) = self.serialize(ser) { return crate::Error::from(err).error_response(); } debug!("Return multistatus:\n{output}"); HttpResponse::MultiStatus() .content_type(ContentType::xml()) .body(output) } }