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> { |
22 | 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 ] |
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)] |
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 ] |
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 | |
79 | impl 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)] |
86 | mod 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 > & " ' < weird symbols \"" |
101 | ); |
102 | } |
103 | } |
104 | |