rss/cloud.rs
1// This file is part of rss.
2//
3// Copyright © 2015-2021 The rust-syndication Developers
4//
5// This program is free software; you can redistribute it and/or modify
6// it under the terms of the MIT License and/or Apache 2.0 License.
7
8use std::io::{BufRead, Write};
9
10use quick_xml::events::{BytesStart, Event};
11use quick_xml::Error as XmlError;
12use quick_xml::Reader;
13use quick_xml::Writer;
14
15use crate::error::Error;
16use crate::toxml::ToXml;
17use crate::util::{attr_value, decode, skip};
18
19/// Represents a cloud in an RSS feed.
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21#[derive(Debug, Default, Clone, PartialEq)]
22#[cfg_attr(feature = "builders", derive(Builder))]
23#[cfg_attr(
24 feature = "builders",
25 builder(
26 setter(into),
27 default,
28 build_fn(name = "build_impl", private, error = "never::Never")
29 )
30)]
31pub struct Cloud {
32 /// The domain to register with.
33 pub domain: String,
34 /// The port to register with.
35 pub port: String,
36 /// The path to register with.
37 pub path: String,
38 /// The procedure to register with.
39 pub register_procedure: String,
40 /// The protocol to register with.
41 pub protocol: String,
42}
43
44impl Cloud {
45 /// Return the domain for this cloud.
46 ///
47 /// # Examples
48 ///
49 /// ```
50 /// use rss::Cloud;
51 ///
52 /// let mut cloud = Cloud::default();
53 /// cloud.set_domain("http://example.com");
54 /// assert_eq!(cloud.domain(), "http://example.com");
55 /// ```
56 pub fn domain(&self) -> &str {
57 self.domain.as_str()
58 }
59
60 /// Set the domain for this cloud.
61 ///
62 /// # Examples
63 ///
64 /// ```
65 /// use rss::Cloud;
66 ///
67 /// let mut cloud = Cloud::default();
68 /// cloud.set_domain("http://example.com");
69 /// ```
70 pub fn set_domain<V>(&mut self, domain: V)
71 where
72 V: Into<String>,
73 {
74 self.domain = domain.into();
75 }
76
77 /// Return the port for this cloud.
78 ///
79 /// # Examples
80 ///
81 /// ```
82 /// use rss::Cloud;
83 ///
84 /// let mut cloud = Cloud::default();
85 /// cloud.set_port("80");
86 /// assert_eq!(cloud.port(), "80");
87 /// ```
88 pub fn port(&self) -> &str {
89 self.port.as_str()
90 }
91
92 /// Set the port for this cloud.
93 ///
94 /// # Examples
95 ///
96 /// ```
97 /// use rss::Cloud;
98 ///
99 /// let mut cloud = Cloud::default();
100 /// cloud.set_port("80");
101 /// ```
102 pub fn set_port<V>(&mut self, port: V)
103 where
104 V: Into<String>,
105 {
106 self.port = port.into();
107 }
108
109 /// Return the path for this cloud.
110 ///
111 /// # Examples
112 ///
113 /// ```
114 /// use rss::Cloud;
115 ///
116 /// let mut cloud = Cloud::default();
117 /// cloud.set_port("/rpc");
118 /// assert_eq!(cloud.port(), "/rpc");
119 /// ```
120 pub fn path(&self) -> &str {
121 self.path.as_str()
122 }
123
124 /// Set the path for this cloud.
125 ///
126 /// # Examples
127 ///
128 /// ```
129 /// use rss::Cloud;
130 ///
131 /// let mut cloud = Cloud::default();
132 /// cloud.set_path("/rpc");
133 /// ```
134 pub fn set_path<V>(&mut self, path: V)
135 where
136 V: Into<String>,
137 {
138 self.path = path.into();
139 }
140
141 /// Return the register procedure for this cloud.
142 ///
143 /// # Examples
144 ///
145 /// ```
146 /// use rss::Cloud;
147 ///
148 /// let mut cloud = Cloud::default();
149 /// cloud.set_register_procedure("pingMe");
150 /// assert_eq!(cloud.register_procedure(), "pingMe");
151 /// ```
152 pub fn register_procedure(&self) -> &str {
153 self.register_procedure.as_str()
154 }
155
156 /// Set the register procedure for this cloud.
157 ///
158 /// # Examples
159 ///
160 /// ```
161 /// use rss::Cloud;
162 ///
163 /// let mut cloud = Cloud::default();
164 /// cloud.set_register_procedure("pingMe");
165 /// ```
166 pub fn set_register_procedure<V>(&mut self, register_procedure: V)
167 where
168 V: Into<String>,
169 {
170 self.register_procedure = register_procedure.into();
171 }
172
173 /// Return the protocol for this cloud.
174 ///
175 /// # Examples
176 ///
177 /// ```
178 /// use rss::Cloud;
179 ///
180 /// let mut cloud = Cloud::default();
181 /// cloud.set_protocol("xml-rpc");
182 /// assert_eq!(cloud.protocol(), "xml-rpc");
183 /// ```
184 pub fn protocol(&self) -> &str {
185 self.protocol.as_str()
186 }
187
188 /// Set the protocol for this cloud.
189 ///
190 /// # Examples
191 ///
192 /// ```
193 /// use rss::Cloud;
194 ///
195 /// let mut cloud = Cloud::default();
196 /// cloud.set_protocol("xml-rpc");
197 /// ```
198 pub fn set_protocol<V>(&mut self, protocol: V)
199 where
200 V: Into<String>,
201 {
202 self.protocol = protocol.into();
203 }
204}
205
206impl Cloud {
207 /// Builds a Cloud from source XML
208 pub fn from_xml<'s, R: BufRead>(
209 reader: &mut Reader<R>,
210 element: &'s BytesStart<'s>,
211 ) -> Result<Self, Error> {
212 let mut cloud = Cloud::default();
213
214 for att in element.attributes().with_checks(false).flatten() {
215 match decode(att.key.as_ref(), reader)?.as_ref() {
216 "domain" => cloud.domain = attr_value(&att, reader)?.to_string(),
217 "port" => cloud.port = attr_value(&att, reader)?.to_string(),
218 "path" => cloud.path = attr_value(&att, reader)?.to_string(),
219 "registerProcedure" => {
220 cloud.register_procedure = attr_value(&att, reader)?.to_string()
221 }
222 "protocol" => cloud.protocol = attr_value(&att, reader)?.to_string(),
223 _ => {}
224 }
225 }
226
227 skip(element.name(), reader)?;
228
229 Ok(cloud)
230 }
231}
232
233impl ToXml for Cloud {
234 fn to_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), XmlError> {
235 let name = "cloud";
236 let mut element = BytesStart::new(name);
237
238 element.push_attribute(("domain", self.domain.as_str()));
239 element.push_attribute(("port", self.port.as_str()));
240 element.push_attribute(("path", self.path.as_str()));
241 element.push_attribute(("registerProcedure", self.register_procedure.as_str()));
242 element.push_attribute(("protocol", self.protocol.as_str()));
243
244 writer.write_event(Event::Empty(element))?;
245 Ok(())
246 }
247}
248
249#[cfg(feature = "builders")]
250impl CloudBuilder {
251 /// Builds a new `Cloud`.
252 pub fn build(&self) -> Cloud {
253 self.build_impl().unwrap()
254 }
255}