webdav_xml/elements/
response.rs

1// SPDX-FileCopyrightText: d-k-bo <d-k-bo@mailbox.org>
2//
3// SPDX-License-Identifier: MIT OR Apache-2.0
4
5use nonempty::NonEmpty;
6
7use crate::{
8    elements::{Href, Propstat, ResponseDescription, Status},
9    utils::NonEmptyExt,
10    value::ValueMap,
11    Element, Error, OptionExt, Value, DAV_NAMESPACE, DAV_PREFIX,
12};
13
14/// The `response` XML element as defined in [RFC 4918](http://webdav.org/specs/rfc4918.html#ELEMENT_response).
15#[derive(Clone, Debug, PartialEq)]
16pub enum Response {
17    Propstat {
18        href: Href,
19        propstat: NonEmpty<Propstat>,
20        // error: Option<Error>,
21        responsedescription: Option<ResponseDescription>,
22        // location: Option<Location>,
23    },
24    Status {
25        href: NonEmpty<Href>,
26        status: Status,
27        // error: Option<Error>,
28        responsedescription: Option<ResponseDescription>,
29        // location: Option<Location>,
30    },
31}
32
33impl Element for Response {
34    const NAMESPACE: &'static str = DAV_NAMESPACE;
35    const PREFIX: &'static str = DAV_PREFIX;
36    const LOCAL_NAME: &'static str = "response";
37}
38
39impl TryFrom<&Value> for Response {
40    type Error = Error;
41
42    fn try_from(value: &Value) -> Result<Self, Self::Error> {
43        let map = value.to_map()?;
44
45        match NonEmpty::try_collect(map.iter_all::<Propstat>())? {
46            Some(propstat) => Ok(Self::Propstat {
47                href: map.get().required::<Href>()??,
48                propstat,
49                responsedescription: map.get().transpose()?,
50            }),
51            None => Ok(Self::Status {
52                href: NonEmpty::try_collect(map.iter_all())?.required::<Href>()?,
53                status: map.get().required::<Status>()??,
54                responsedescription: map.get().transpose()?,
55            }),
56        }
57    }
58}
59
60impl From<Response> for Value {
61    fn from(response: Response) -> Value {
62        let mut map = ValueMap::new();
63
64        match response {
65            Response::Propstat {
66                href,
67                propstat,
68                responsedescription,
69            } => {
70                map.insert::<Href>(href.into());
71                map.insert::<Propstat>(Value::List(Box::new(
72                    NonEmpty::collect(propstat.into_iter().map(Value::from)).expect(
73                        "iterator is created from a `NonEmpty` and is guaranteed to be nonempty",
74                    ),
75                )));
76                if let Some(responsedescription) = responsedescription {
77                    map.insert::<ResponseDescription>(responsedescription.into())
78                }
79            }
80            Response::Status {
81                href,
82                status,
83                responsedescription,
84            } => {
85                map.insert::<Href>(Value::List(Box::new(
86                    NonEmpty::collect(href.into_iter().map(Value::from)).expect(
87                        "iterator is created from a `NonEmpty` and is guaranteed to be nonempty",
88                    ),
89                )));
90                map.insert::<Status>(status.into());
91                if let Some(responsedescription) = responsedescription {
92                    map.insert::<ResponseDescription>(responsedescription.into())
93                }
94            }
95        }
96
97        Value::Map(map)
98    }
99}