rss_for_mikan/
source.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::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/// Represents the source of an RSS item.
21#[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    /// The URL of the source.
34    pub url: String,
35    /// The title of the source.
36    pub title: Option<String>,
37}
38
39impl Source {
40    /// Return the URL of this source.
41    ///
42    /// # Examples
43    ///
44    /// ```
45    /// use rss::Source;
46    ///
47    /// let mut source = Source::default();
48    /// source.set_url("http://example.com");
49    /// assert_eq!(source.url(), "http://example.com");
50    /// ```
51    pub fn url(&self) -> &str {
52        self.url.as_str()
53    }
54
55    /// Set the URL of this source.
56    ///
57    /// # Examples
58    ///
59    /// ```
60    /// use rss::Source;
61    ///
62    /// let mut source = Source::default();
63    /// source.set_url("http://example.com");
64    /// ```
65    pub fn set_url<V>(&mut self, url: V)
66    where
67        V: Into<String>,
68    {
69        self.url = url.into();
70    }
71
72    /// Return the title of this source.
73    ///
74    /// # Examples
75    ///
76    /// ```
77    /// use rss::Source;
78    ///
79    /// let mut source = Source::default();
80    /// source.set_title("Source Title".to_string());
81    /// assert_eq!(source.title(), Some("Source Title"));
82    /// ```
83    pub fn title(&self) -> Option<&str> {
84        self.title.as_deref()
85    }
86
87    /// Set the title of this source.
88    ///
89    /// # Examples
90    ///
91    /// ```
92    /// use rss::Source;
93    ///
94    /// let mut source = Source::default();
95    /// source.set_title("Source Title".to_string());
96    /// ```
97    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    /// Builds a Source from source XML
107    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    /// Builds a new `Source`.
145    pub fn build(&self) -> Source {
146        self.build_impl().unwrap()
147    }
148}