Skip to main content

rss/
guid.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::{decode, element_text};
19
20/// Represents the GUID of an RSS item.
21#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22#[derive(Debug, 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 Guid {
33    /// The value of the GUID.
34    pub value: String,
35    /// Indicates if the GUID is a permalink.
36    pub permalink: bool,
37}
38
39impl Guid {
40    /// Return whether this GUID is a permalink.
41    ///
42    /// # Examples
43    ///
44    /// ```
45    /// use rss::Guid;
46    ///
47    /// let mut guid = Guid::default();
48    /// guid.set_permalink(true);
49    /// assert!(guid.is_permalink());
50    /// ```
51    pub fn is_permalink(&self) -> bool {
52        self.permalink
53    }
54
55    /// Set whether this GUID is a permalink.
56    ///
57    /// # Examples
58    ///
59    /// ```
60    /// use rss::Guid;
61    ///
62    /// let mut guid = Guid::default();
63    /// guid.set_permalink(true);
64    /// ```
65    pub fn set_permalink<V>(&mut self, permalink: V)
66    where
67        V: Into<bool>,
68    {
69        self.permalink = permalink.into()
70    }
71
72    /// Return the value of this GUID.
73    ///
74    /// # Examples
75    ///
76    /// ```
77    /// use rss::Guid;
78    ///
79    /// let mut guid = Guid::default();
80    /// guid.set_value("00000000-0000-0000-0000-00000000000");
81    /// assert_eq!(guid.value(), "00000000-0000-0000-0000-00000000000");
82    /// ```
83    pub fn value(&self) -> &str {
84        self.value.as_str()
85    }
86
87    /// Set the value of this GUID.
88    ///
89    /// # Examples
90    ///
91    /// ```
92    /// use rss::Guid;
93    ///
94    /// let mut guid = Guid::default();
95    /// guid.set_value("00000000-0000-0000-0000-00000000000");
96    /// ```
97    pub fn set_value<V>(&mut self, value: V)
98    where
99        V: Into<String>,
100    {
101        self.value = value.into();
102    }
103}
104
105impl Default for Guid {
106    #[inline]
107    fn default() -> Self {
108        Guid {
109            value: Default::default(),
110            permalink: true,
111        }
112    }
113}
114
115impl Guid {
116    /// Builds a Guid from source XML
117    pub fn from_xml<R: BufRead>(
118        reader: &mut Reader<R>,
119        mut atts: Attributes,
120    ) -> Result<Self, Error> {
121        let mut guid = Guid::default();
122
123        for attr in atts.with_checks(false).flatten() {
124            if decode(attr.key.as_ref(), reader)?.as_ref() == "isPermaLink" {
125                guid.permalink = &*attr.value != b"false";
126                break;
127            }
128        }
129
130        guid.value = element_text(reader)?.unwrap_or_default();
131        Ok(guid)
132    }
133}
134
135impl ToXml for Guid {
136    fn to_xml<W: Write>(&self, writer: &mut Writer<W>) -> Result<(), XmlError> {
137        let name = "guid";
138        let mut element = BytesStart::new(name);
139        if !self.permalink {
140            element.push_attribute(("isPermaLink", "false"));
141        }
142        writer.write_event(Event::Start(element))?;
143        writer.write_event(Event::Text(BytesText::new(&self.value)))?;
144        writer.write_event(Event::End(BytesEnd::new(name)))?;
145        Ok(())
146    }
147}
148
149#[cfg(feature = "builders")]
150impl GuidBuilder {
151    /// Builds a new `Guid`.
152    pub fn build(&self) -> Guid {
153        self.build_impl().unwrap()
154    }
155}