1use std::io::{BufRead, Write};
9
10use quick_xml::events::attributes::Attributes;
11use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
12use quick_xml::Error as XmlError;
13use quick_xml::Reader;
14use quick_xml::Writer;
15
16use crate::error::Error;
17use crate::toxml::ToXml;
18use crate::util::{attr_value, decode, element_text};
19
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22#[derive(Debug, Default, Clone, PartialEq)]
23#[cfg_attr(feature = "builders", derive(Builder))]
24#[cfg_attr(
25 feature = "builders",
26 builder(
27 setter(into),
28 default,
29 build_fn(name = "build_impl", private, error = "never::Never")
30 )
31)]
32pub struct Source {
33 pub url: String,
35 pub title: Option<String>,
37}
38
39impl Source {
40 pub fn url(&self) -> &str {
52 self.url.as_str()
53 }
54
55 pub fn set_url<V>(&mut self, url: V)
66 where
67 V: Into<String>,
68 {
69 self.url = url.into();
70 }
71
72 pub fn title(&self) -> Option<&str> {
84 self.title.as_deref()
85 }
86
87 pub fn set_title<V>(&mut self, title: V)
98 where
99 V: Into<Option<String>>,
100 {
101 self.title = title.into();
102 }
103}
104
105impl Source {
106 pub fn from_xml<R: BufRead>(
108 reader: &mut Reader<R>,
109 mut atts: Attributes,
110 ) -> Result<Self, Error> {
111 let mut source = Source::default();
112
113 for attr in atts.with_checks(false).flatten() {
114 if decode(attr.key.as_ref(), reader)?.as_ref() == "url" {
115 source.url = attr_value(&attr, reader)?.to_string();
116 break;
117 }
118 }
119
120 source.title = element_text(reader)?;
121 Ok(source)
122 }
123}
124
125impl ToXml for Source {
126 fn to_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), XmlError> {
127 let name = "source";
128 let mut element = BytesStart::new(name);
129 element.push_attribute(("url", &*self.url));
130
131 writer.write_event(Event::Start(element))?;
132
133 if let Some(ref text) = self.title {
134 writer.write_event(Event::Text(BytesText::new(text)))?;
135 }
136
137 writer.write_event(Event::End(BytesEnd::new(name)))?;
138 Ok(())
139 }
140}
141
142#[cfg(feature = "builders")]
143impl SourceBuilder {
144 pub fn build(&self) -> Source {
146 self.build_impl().unwrap()
147 }
148}