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)]
10#[xml(root = b"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)]
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.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
59 .push((ns, String::from_utf8_lossy(name.as_ref()).to_string()));
60 Unparsed::deserialize(reader, start, empty)?;
62 }
63 Err(err) => return Err(err),
64 }
65 }
66 Event::Text(_) | Event::CData(_) => {
67 return Err(XmlError::UnsupportedEvent("Not expecting text here"));
68 }
69 Event::Decl(_) | Event::Comment(_) | Event::DocType(_) | Event::PI(_) => { }
71 Event::End(_end) => {
72 unreachable!(
73 "Unexpected closing tag for wrong element, should be handled by quick_xml"
74 );
75 }
76 }
77 }
78 Ok(Self(valid_props, invalid_props))
79 }
80}
81
82#[derive(Debug, Clone, XmlDeserialize, PartialEq)]
83pub enum PropfindType<PN: XmlDeserialize> {
84 #[xml(ns = "crate::namespace::NS_DAV")]
85 Propname,
86 #[xml(ns = "crate::namespace::NS_DAV")]
87 Allprop,
88 #[xml(ns = "crate::namespace::NS_DAV")]
89 Prop(PropElement<PN>),
90}