1//! Contains XML attributes manipulation types and functions.
2//!
3
4use std::fmt;
5
6use crate::escape::{AttributeEscapes, Escaped};
7use 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)]
13pub struct Attribute<'a> {
14 /// Attribute name.
15 pub name: Name<'a>,
16
17 /// Attribute value.
18 pub value: &'a str,
19}
20
21impl<'a> fmt::Display for Attribute<'a> {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 write!(f, "{}=\"{}\"", self.name, Escaped::<AttributeEscapes>::new(self.value))
24 }
25}
26
27impl<'a> Attribute<'a> {
28 /// Creates an owned attribute out of this borrowed one.
29 #[inline]
30 #[must_use]
31 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]
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)]
50pub struct OwnedAttribute {
51 /// Attribute name.
52 pub name: OwnedName,
53
54 /// Attribute value.
55 pub value: String,
56}
57
58impl OwnedAttribute {
59 /// Returns a borrowed `Attribute` out of this owned one.
60 #[must_use]
61 #[inline]
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]
71 pub fn new<S: Into<String>>(name: OwnedName, value: S) -> OwnedAttribute {
72 OwnedAttribute {
73 name,
74 value: value.into(),
75 }
76 }
77}
78
79impl fmt::Display for OwnedAttribute {
80 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)]
86mod tests {
87 use super::Attribute;
88
89 use crate::name::Name;
90
91 #[test]
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