rustical_dav/xml/
propfind.rs1use quick_xml::events::Event;
2use quick_xml::name::ResolveResult;
3use rustical_xml::NamespaceOwned;
4use rustical_xml::Unparsed;
5use rustical_xml::XmlDeserialize;
6use rustical_xml::XmlError;
7use rustical_xml::XmlRootTag;
8
9#[derive(Debug, Clone, XmlDeserialize, XmlRootTag, PartialEq, Eq)]
10#[xml(root = "propfind", ns = "crate::namespace::NS_DAV")]
11pub struct PropfindElement<PN: XmlDeserialize> {
12 #[xml(ty = "untagged")]
13 pub prop: PropfindType<PN>,
14 #[xml(ns = "crate::namespace::NS_DAV")]
15 pub include: Option<PropElement<PN>>,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct PropElement<PN: XmlDeserialize>(
20 pub Vec<PN>,
22 pub Vec<(Option<NamespaceOwned>, String)>,
24);
25
26impl<PN: XmlDeserialize> XmlDeserialize for PropElement<PN> {
27 fn deserialize<R: std::io::BufRead>(
28 reader: &mut quick_xml::NsReader<R>,
29 start: &quick_xml::events::BytesStart,
30 empty: bool,
31 ) -> Result<Self, XmlError> {
32 if empty {
33 return Ok(Self(vec![], vec![]));
34 }
35 let mut buf = Vec::new();
36 let mut valid_props = vec![];
37 let mut invalid_props = vec![];
38 loop {
39 let event = reader.read_event_into(&mut buf)?;
40 match &event {
41 Event::End(e) if e.name() == start.name() => {
42 break;
43 }
44 Event::Eof => return Err(XmlError::Eof),
45 Event::Start(start) | Event::Empty(start) => {
47 let empty = matches!(event, Event::Empty(_));
48 let (ns, name) = reader.resolver().resolve_element(start.name());
49 let ns = match ns {
50 ResolveResult::Bound(ns) => Some(NamespaceOwned::from(ns)),
51 ResolveResult::Unknown(_ns) => todo!("handle error"),
52 ResolveResult::Unbound => None,
53 };
54
55 match PN::deserialize(reader, start, empty) {
56 Ok(propname) => valid_props.push(propname),
57 Err(XmlError::InvalidVariant(_)) => {
58 invalid_props.push((ns, name.as_ref().to_owned()));
59 Unparsed::deserialize(reader, start, empty)?;
61 }
62 Err(err) => return Err(err),
63 }
64 }
65 Event::Text(text) => {
66 if text.xml11_content().chars().any(|chr| !chr.is_whitespace()) {
67 return Err(::rustical_xml::XmlError::UnsupportedEvent(
68 "unexpected text",
69 ));
70 }
71 }
72 Event::CData(_) => {
73 return Err(XmlError::UnsupportedEvent("Not expecting text here"));
74 }
75 Event::GeneralRef(_) => {
76 return Err(::rustical_xml::XmlError::UnsupportedEvent("GeneralRef"));
77 }
78 Event::Decl(_) | Event::Comment(_) | Event::DocType(_) | Event::PI(_) => { }
80 Event::End(_end) => {
81 unreachable!(
82 "Unexpected closing tag for wrong element, should be handled by quick_xml"
83 );
84 }
85 }
86 }
87 Ok(Self(valid_props, invalid_props))
88 }
89}
90
91#[derive(Debug, Clone, XmlDeserialize, PartialEq, Eq)]
92pub enum PropfindType<PN: XmlDeserialize> {
93 #[xml(ns = "crate::namespace::NS_DAV")]
94 Propname,
95 #[xml(ns = "crate::namespace::NS_DAV")]
96 Allprop,
97 #[xml(ns = "crate::namespace::NS_DAV")]
98 Prop(PropElement<PN>),
99}