ahecha_html/html/
attributes.rs

1#[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}