1 //! Contains XML attributes manipulation types and functions.
2 //!
3 
4 use std::fmt;
5 
6 use crate::escape::{AttributeEscapes, Escaped};
7 use crate::name::{Name, OwnedName};
8 
9 /// A borrowed version of an XML attribute.
10 ///
11 /// Consists of a borrowed qualified name and a borrowed string value.
12 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
13 pub struct Attribute<'a> {
14     /// Attribute name.
15     pub name: Name<'a>,
16 
17     /// Attribute value.
18     pub value: &'a str,
19 }
20 
21 impl<'a> fmt::Display for Attribute<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result22     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23         write!(f, "{}=\"{}\"", self.name, Escaped::<AttributeEscapes>::new(self.value))
24     }
25 }
26 
27 impl<'a> Attribute<'a> {
28     /// Creates an owned attribute out of this borrowed one.
29     #[inline]
30     #[must_use]
to_owned(&self) -> OwnedAttribute31     pub fn to_owned(&self) -> OwnedAttribute {
32         OwnedAttribute {
33             name: self.name.into(),
34             value: self.value.into(),
35         }
36     }
37 
38     /// Creates a borrowed attribute using the provided borrowed name and a borrowed string value.
39     #[inline]
40     #[must_use]
new(name: Name<'a>, value: &'a str) -> Attribute<'a>41     pub fn new(name: Name<'a>, value: &'a str) -> Attribute<'a> {
42         Attribute { name, value }
43     }
44 }
45 
46 /// An owned version of an XML attribute.
47 ///
48 /// Consists of an owned qualified name and an owned string value.
49 #[derive(Clone, Eq, PartialEq, Hash, Debug)]
50 pub struct OwnedAttribute {
51     /// Attribute name.
52     pub name: OwnedName,
53 
54     /// Attribute value.
55     pub value: String,
56 }
57 
58 impl OwnedAttribute {
59     /// Returns a borrowed `Attribute` out of this owned one.
60     #[must_use]
61     #[inline]
borrow(&self) -> Attribute<'_>62     pub fn borrow(&self) -> Attribute<'_> {
63         Attribute {
64             name: self.name.borrow(),
65             value: &self.value,
66         }
67     }
68 
69     /// Creates a new owned attribute using the provided owned name and an owned string value.
70     #[inline]
new<S: Into<String>>(name: OwnedName, value: S) -> OwnedAttribute71     pub fn new<S: Into<String>>(name: OwnedName, value: S) -> OwnedAttribute {
72         OwnedAttribute {
73             name,
74             value: value.into(),
75         }
76     }
77 }
78 
79 impl fmt::Display for OwnedAttribute {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result80     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81         write!(f, "{}=\"{}\"", self.name, Escaped::<AttributeEscapes>::new(&self.value))
82     }
83 }
84 
85 #[cfg(test)]
86 mod tests {
87     use super::Attribute;
88 
89     use crate::name::Name;
90 
91     #[test]
attribute_display()92     fn attribute_display() {
93         let attr = Attribute::new(
94             Name::qualified("attribute", "urn:namespace", Some("n")),
95             "its value with > & \" ' < weird symbols",
96         );
97 
98         assert_eq!(
99             &*attr.to_string(),
100             "{urn:namespace}n:attribute=\"its value with &gt; &amp; &quot; &apos; &lt; weird symbols\""
101         );
102     }
103 }
104