webdav_xml/elements/
multistatus.rs1use nonempty::NonEmpty;
6
7use crate::{
8 elements::{response::Response, ResponseDescription},
9 value::ValueMap,
10 Element, Error, Value, DAV_NAMESPACE, DAV_PREFIX,
11};
12
13#[derive(Clone, Debug, Default, PartialEq)]
15pub struct Multistatus {
16 pub response: Vec<Response>,
17 pub responsedescription: Option<ResponseDescription>,
18}
19
20impl Element for Multistatus {
21 const NAMESPACE: &'static str = DAV_NAMESPACE;
22 const PREFIX: &'static str = DAV_PREFIX;
23 const LOCAL_NAME: &'static str = "multistatus";
24}
25
26impl TryFrom<&Value> for Multistatus {
27 type Error = Error;
28
29 fn try_from(value: &Value) -> Result<Self, Self::Error> {
30 let map = value.to_map()?;
31
32 Ok(Multistatus {
33 response: map.iter_all().collect::<Result<_, _>>()?,
34 responsedescription: map.get().transpose()?,
35 })
36 }
37}
38
39impl From<Multistatus> for Value {
40 fn from(
41 Multistatus {
42 response,
43 responsedescription,
44 }: Multistatus,
45 ) -> Value {
46 let mut map = ValueMap::new();
47
48 map.insert::<Response>(
49 match NonEmpty::collect(response.into_iter().map(Value::from)) {
50 Some(responses) => Value::List(Box::new(responses)),
51 None => Value::Empty,
52 },
53 );
54 if let Some(responsedescription) = responsedescription {
55 map.insert::<ResponseDescription>(responsedescription.into())
56 }
57
58 Value::Map(map)
59 }
60}
61
62#[cfg(test)]
63#[test]
64fn test() -> eyre::Result<()> {
65 use http::StatusCode;
66
67 use crate::{
68 elements::{Href, Status},
69 FromXml,
70 };
71
72 let xml = r#"
74 <?xml version="1.0" encoding="utf-8" ?>
75 <D:multistatus xmlns:D="DAV:">
76 <D:response xmlns:R="http://ns.example.com/boxschema/">
77 <D:href>http://www.example.com/file</D:href>
78 <D:propstat>
79 <D:prop>
80 <R:bigbox>
81 <R:BoxType>Box type A</R:BoxType>
82 </R:bigbox>
83 <R:author>
84 <R:Name>J.J. Johnson</R:Name>
85 </R:author>
86 </D:prop>
87 <D:status>HTTP/1.1 200 OK</D:status>
88 </D:propstat>
89 <D:propstat>
90 <D:prop><R:DingALing/><R:Random/></D:prop>
91 <D:status>HTTP/1.1 403 Forbidden</D:status>
92 <D:responsedescription> The user does not have access to the
93 DingALing property.
94 </D:responsedescription>
95 </D:propstat>
96 </D:response>
97 <D:responsedescription> There has been an access violation error.
98 </D:responsedescription>
99 </D:multistatus>
100 "#;
101 let multistatus = Multistatus::from_xml(xml)?;
102
103 assert!(matches!(
104 &multistatus.response[0],
105 Response::Propstat {
106 href, propstat,
107 responsedescription: None,
108 ..
109 } if href == &Href(http::Uri::from_static("http://www.example.com/file"))
110 && propstat[0].status == Status(StatusCode::OK)
111 && propstat[1].status == Status(StatusCode::FORBIDDEN)
112 && propstat[1].responsedescription.is_some()
113 ));
114
115 Ok(())
116}