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