webdav_xml/elements/
prop.rs1use bytestring::ByteString;
6
7use crate::{
8 element::{Element, ElementName},
9 properties::{
10 ContentLanguage, ContentLength, ContentType, CreationDate, DisplayName, ETag, LastModified,
11 LockDiscovery, ResourceType, SupportedLock,
12 },
13 value::{Value, ValueMap},
14 Error, DAV_NAMESPACE, DAV_PREFIX,
15};
16
17#[derive(Clone, Debug, Default, PartialEq)]
22pub struct Properties(ValueMap);
23
24impl Properties {
25 pub fn new() -> Self {
26 Self::default()
27 }
28 pub fn with<E>(mut self, e: E) -> Self
29 where
30 E: Element + Into<Value>,
31 {
32 self.0.insert::<E>(e.into());
33 self
34 }
35 pub fn with_name<E>(mut self) -> Self
36 where
37 E: Element,
38 {
39 self.0.insert::<E>(Value::Empty);
40 self
41 }
42}
43
44impl Properties {
45 pub fn get<'v, P>(&'v self) -> Option<Option<Result<P, Error>>>
54 where
55 P: Element + TryFrom<&'v Value, Error = Error>,
56 {
57 self.0.get_optional()
58 }
59 pub fn names(&self) -> impl Iterator<Item = &ElementName<ByteString>> {
61 self.0 .0.keys()
62 }
63}
64
65impl Properties {
66 pub fn creationdate(&self) -> Option<Option<Result<CreationDate, Error>>> {
70 self.get()
71 }
72 pub fn displayname(&self) -> Option<Option<Result<DisplayName, Error>>> {
76 self.get()
77 }
78 pub fn getcontentlanguage(&self) -> Option<Option<Result<ContentLanguage, Error>>> {
82 self.get()
83 }
84 pub fn getcontentlength(&self) -> Option<Option<Result<ContentLength, Error>>> {
88 self.get()
89 }
90 pub fn getcontenttype(&self) -> Option<Option<Result<ContentType, Error>>> {
94 self.get()
95 }
96 pub fn getetag(&self) -> Option<Option<Result<ETag, Error>>> {
100 self.get()
101 }
102 pub fn getlastmodified(&self) -> Option<Option<Result<LastModified, Error>>> {
106 self.get()
107 }
108 pub fn lockdiscovery(&self) -> Option<Option<Result<LockDiscovery, Error>>> {
112 self.get()
113 }
114 pub fn resourcetype(&self) -> Option<Option<Result<ResourceType, Error>>> {
118 self.get()
119 }
120 pub fn supportedlock(&self) -> Option<Option<Result<SupportedLock, Error>>> {
124 self.get()
125 }
126}
127
128impl Element for Properties {
129 const NAMESPACE: &'static str = DAV_NAMESPACE;
130 const PREFIX: &'static str = DAV_PREFIX;
131 const LOCAL_NAME: &'static str = "prop";
132}
133
134impl TryFrom<&Value> for Properties {
135 type Error = Error;
136
137 fn try_from(value: &Value) -> Result<Self, Self::Error> {
138 value.to_map().cloned().map(Self)
139 }
140}
141
142impl From<Properties> for Value {
143 fn from(Properties(map): Properties) -> Value {
144 Value::Map(map)
145 }
146}
147
148#[cfg(test)]
149#[test]
150fn test_deserialize() -> eyre::Result<()> {
151 use pretty_assertions::assert_eq;
152
153 use crate::FromXml;
154
155 let xml = r#"
156 <d:prop xmlns:d="DAV:">
157 <d:getlastmodified>Mon, 30 Sep 2019 12:13:02 GMT</d:getlastmodified>
158 <d:getcontentlength>0</d:getcontentlength>
159 <d:resourcetype/>
160 <d:getetag>"a28785e285ce0de0738676814705c4e1"</d:getetag>
161 <d:getcontenttype>text/plain</d:getcontenttype>
162 </d:prop>
163 "#;
164
165 let prop = Properties::from_xml(xml)?;
166
167 assert_eq!(
168 prop.getlastmodified().unwrap().unwrap()?,
169 LastModified("Mon, 30 Sep 2019 12:13:02 GMT".parse()?)
170 );
171 assert_eq!(prop.getcontentlength().unwrap().unwrap()?, ContentLength(0));
172 assert!(prop.resourcetype().unwrap().is_none());
173 assert_eq!(
174 prop.getetag().unwrap().unwrap()?,
175 ETag(r#""a28785e285ce0de0738676814705c4e1""#.into())
176 );
177 assert_eq!(
178 prop.getcontenttype().unwrap().unwrap()?,
179 ContentType(mime::TEXT_PLAIN)
180 );
181
182 Ok(())
183}