ahecha_html/html/
attributes.rs1#[derive(Debug, Clone, PartialEq)]
2pub enum AttributeValue {
3 Bool(bool),
4 None,
5 String(String),
6}
7
8impl ToString for AttributeValue {
9 fn to_string(&self) -> String {
10 match self {
11 AttributeValue::Bool(value) => value.to_string(),
12 AttributeValue::None => "".to_owned(),
13 AttributeValue::String(text) => text.clone(),
14 }
15 }
16}
17
18#[derive(Default, Debug, Clone)]
19pub struct Attributes {
20 pub attrs: Vec<(String, AttributeValue)>,
21}
22
23impl Attributes {
24 pub fn set<K, V>(mut self, tuple: Option<(K, V)>) -> Self
25 where
26 K: Into<String>,
27 V: Into<AttributeValue>,
28 {
29 if let Some((key, value)) = tuple {
30 self.attrs.push((key.into(), value.into()));
31 }
32 self
33 }
34
35 pub fn is_empty(&self) -> bool {
36 self.attrs.is_empty()
37 }
38}
39
40macro_rules! impl_into_attribute_value {
41 ($($ty: ty),*) => {
42 $(
43 impl From<$ty> for AttributeValue
44 {
45 fn from(item: $ty) -> Self {
46 let value = format!("{}", item);
47
48 if value.is_empty() {
49 AttributeValue::None
50 } else if let Ok(boolean) = value.parse::<bool>() {
51 AttributeValue::Bool(boolean)
52 } else {
53 AttributeValue::String(value)
54 }
55 }
56 }
57
58 impl From<Option<$ty>> for AttributeValue
59 {
60 fn from(item: Option<$ty>) -> Self {
61 match item {
62 Some(value) => value.into(),
63 None => AttributeValue::None,
64 }
65 }
66 }
67
68 impl From<&$ty> for AttributeValue
69 {
70 fn from(item: &$ty) -> Self {
71 let value = format!("{}", item);
72
73 if value.is_empty() {
74 AttributeValue::None
75 } else if let Ok(boolean) = value.parse::<bool>() {
76 AttributeValue::Bool(boolean)
77 } else {
78 AttributeValue::String(value)
79 }
80 }
81 }
82
83 impl From<Option<&$ty>> for AttributeValue
84 {
85 fn from(item: Option<&$ty>) -> Self {
86 match item {
87 Some(value) => value.into(),
88 None => AttributeValue::None,
89 }
90 }
91 }
92 )*
93 };
94}
95
96impl_into_attribute_value!(
97 bool, i8, i16, i32, i64, i128, f32, f64, u8, u16, u32, u64, u128, &str, String
98);
99
100impl<T> From<Result<String, T>> for AttributeValue
101where
102 T: ToString,
103{
104 fn from(item: Result<String, T>) -> Self {
105 match item {
106 Ok(value) => value.into(),
107 Err(e) => {
108 println!("{}", e.to_string());
109 AttributeValue::None
110 }
111 }
112 }
113}
114
115#[cfg(feature = "time")]
116mod _time {
117 use time::OffsetDateTime;
118
119 use super::*;
120
121 impl_into_attribute_value!();
122
123 impl From<OffsetDateTime> for AttributeValue {
124 fn from(item: OffsetDateTime) -> Self {
125 let value = format!("{}", item);
126
127 if value.is_empty() {
128 AttributeValue::None
129 } else if let Ok(boolean) = value.parse::<bool>() {
130 AttributeValue::Bool(boolean)
131 } else {
132 AttributeValue::String(value)
133 }
134 }
135 }
136
137 impl From<Option<OffsetDateTime>> for AttributeValue {
138 fn from(item: Option<OffsetDateTime>) -> Self {
139 match item {
140 Some(value) => value.into(),
141 None => AttributeValue::None,
142 }
143 }
144 }
145
146 impl From<&OffsetDateTime> for AttributeValue {
147 fn from(item: &OffsetDateTime) -> Self {
148 let value = format!("{}", item);
149
150 if value.is_empty() {
151 AttributeValue::None
152 } else if let Ok(boolean) = value.parse::<bool>() {
153 AttributeValue::Bool(boolean)
154 } else {
155 AttributeValue::String(value)
156 }
157 }
158 }
159
160 impl From<Option<&OffsetDateTime>> for AttributeValue {
161 fn from(item: Option<&OffsetDateTime>) -> Self {
162 match item {
163 Some(value) => value.into(),
164 None => AttributeValue::None,
165 }
166 }
167 }
168}