1extern crate alloc;
4
5use core::fmt;
6use alloc::string::String;
7
8use crate::escape::{AttributeEscapes, Escaped};
9use crate::name::{Name, OwnedName};
10
11#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
15pub struct Attribute<'a> {
16 pub name: Name<'a>,
18
19 pub value: &'a str,
21}
22
23impl fmt::Display for Attribute<'_> {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 write!(f, "{}=\"{}\"", self.name, Escaped::<AttributeEscapes>::new(self.value))
26 }
27}
28
29impl<'a> Attribute<'a> {
30 #[inline]
32 #[must_use]
33 pub fn to_owned(&self) -> OwnedAttribute {
34 OwnedAttribute {
35 name: self.name.into(),
36 value: self.value.into(),
37 }
38 }
39
40 #[inline]
42 #[must_use]
43 pub const fn new(name: Name<'a>, value: &'a str) -> Self {
44 Attribute { name, value }
45 }
46}
47
48#[derive(Clone, Eq, PartialEq, Hash, Debug, PartialOrd, Ord)]
52pub struct OwnedAttribute {
53 pub name: OwnedName,
55
56 pub value: String,
58}
59
60impl OwnedAttribute {
61 #[must_use]
63 #[inline]
64 pub fn borrow(&self) -> Attribute<'_> {
65 Attribute {
66 name: self.name.borrow(),
67 value: &self.value,
68 }
69 }
70
71 #[inline]
73 pub fn new<S: Into<String>>(name: OwnedName, value: S) -> OwnedAttribute {
74 OwnedAttribute {
75 name,
76 value: value.into(),
77 }
78 }
79}
80
81impl fmt::Display for OwnedAttribute {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 write!(f, "{}=\"{}\"", self.name, Escaped::<AttributeEscapes>::new(&self.value))
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::Attribute;
90
91 use crate::name::Name;
92
93 #[test]
94 fn attribute_display() {
95 let attr = Attribute::new(
96 Name::qualified("attribute", "urn:namespace", Some("n")),
97 "its value with > & \" ' < weird symbols",
98 );
99
100 assert_eq!(
101 &*attr.to_string(),
102 "{urn:namespace}n:attribute=\"its value with > & " ' < weird symbols\""
103 );
104 }
105}