1pub trait Attribute {
19 type Text<'a>: 'a + AsRef<str> + Into<String> + ToString
20 where
21 Self: 'a;
22
23 fn text(&self) -> Option<Self::Text<'_>>;
29}
30
31pub trait AsAttribute<T>: Attribute {}
35
36macro_rules! define_attribute_values{
37 ($($typ:ty),* $(,)?) => {
38 $(
39 impl Attribute for $typ {
40 type Text<'a> = String;
41
42 fn text(&self) -> Option<Self::Text<'_>> {
43 Some(self.to_string())
44 }
45 }
46
47 impl AsAttribute<$typ> for $typ {}
48 )*
49 }
50}
51
52define_attribute_values!(i8, i16, i32, i64);
53define_attribute_values!(u8, u16, u32, u64);
54define_attribute_values!(f32, f64);
55define_attribute_values!(usize);
56
57impl Attribute for String {
58 type Text<'a> = &'a str;
59
60 fn text(&self) -> Option<Self::Text<'_>> {
61 Some(self)
62 }
63}
64
65impl AsAttribute<String> for String {}
66
67impl<T: Attribute> Attribute for Option<T> {
68 type Text<'a>
69 = T::Text<'a>
70 where
71 T: 'a;
72
73 fn text(&self) -> Option<Self::Text<'_>> {
74 self.as_ref()?.text()
75 }
76}
77
78impl<U: Attribute, T: AsAttribute<U>> AsAttribute<U> for Option<T> {}
79
80impl Attribute for bool {
81 type Text<'a> = &'static str;
82
83 fn text(&self) -> Option<Self::Text<'_>> {
84 if *self {
85 Some("")
86 } else {
87 None
88 }
89 }
90}
91
92impl AsAttribute<bool> for bool {}
93
94impl<'a> Attribute for &'a str {
95 type Text<'b>
96 = &'b str
97 where
98 'a: 'b;
99
100 fn text(&self) -> Option<Self::Text<'_>> {
101 Some(*self)
102 }
103}
104
105impl AsAttribute<String> for &str {}
106
107impl<'a> Attribute for &'a String {
108 type Text<'b>
109 = &'b str
110 where
111 'a: 'b;
112
113 fn text(&self) -> Option<Self::Text<'_>> {
114 Some(self.as_str())
115 }
116}
117
118impl AsAttribute<String> for &String {}