virtual_node/velement/
attribute_value.rs

1use std::fmt::{Display, Formatter};
2use wasm_bindgen::JsValue;
3
4/// The value associated with an element's attribute.
5///
6/// For <button disabled=true></button>, the element attribute value would be
7/// `ElementAttributeValue::Bool(true)`
8#[derive(Debug, PartialEq, Clone)]
9pub enum AttributeValue {
10    /// A string attribute such as value="My text input contents"
11    String(String),
12    /// A boolean attribute disabled=true
13    Bool(bool),
14}
15
16impl AttributeValue {
17    /// If the attribute is a string, return it. Otherwise return None.
18    pub fn as_string(&self) -> Option<&String> {
19        match self {
20            AttributeValue::String(s) => Some(s),
21            _ => None,
22        }
23    }
24
25    /// If the attribute is a bool, return it. Otherwise return None.
26    pub fn as_bool(&self) -> Option<bool> {
27        match self {
28            AttributeValue::Bool(b) => Some(*b),
29            _ => None,
30        }
31    }
32}
33
34// Implements
35//   From<T> and From<&T> -> AttributeValue::String(T.to_string())
36macro_rules! to_string_impls {
37    ($ty:ty) => {
38        impl From<$ty> for AttributeValue {
39            fn from(val: $ty) -> Self {
40                AttributeValue::String(val.to_string())
41            }
42        }
43
44        impl From<&$ty> for AttributeValue {
45            fn from(val: &$ty) -> Self {
46                AttributeValue::String(val.to_string())
47            }
48        }
49    };
50
51    ($ty:ty, $($tys:ty),*) => {
52        to_string_impls!( $ty );
53        to_string_impls! ( $($tys),* );
54    }
55}
56to_string_impls!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64);
57
58impl Into<JsValue> for AttributeValue {
59    fn into(self) -> JsValue {
60        match self {
61            AttributeValue::String(s) => s.into(),
62            AttributeValue::Bool(b) => b.into(),
63        }
64    }
65}
66
67impl From<String> for AttributeValue {
68    fn from(s: String) -> Self {
69        AttributeValue::String(s)
70    }
71}
72
73impl From<&String> for AttributeValue {
74    fn from(s: &String) -> Self {
75        AttributeValue::String(s.to_string())
76    }
77}
78
79impl From<&str> for AttributeValue {
80    fn from(s: &str) -> Self {
81        AttributeValue::String(s.to_string())
82    }
83}
84
85impl<S: AsRef<str>, const N: usize> From<[S; N]> for AttributeValue {
86    fn from(vals: [S; N]) -> Self {
87        let mut combined = "".to_string();
88
89        for (idx, val) in vals.iter().enumerate() {
90            if idx != 0 {
91                combined += " ";
92            }
93
94            combined += val.as_ref();
95        }
96
97        AttributeValue::String(combined)
98    }
99}
100
101impl<S: AsRef<str>> From<Vec<S>> for AttributeValue {
102    fn from(vals: Vec<S>) -> Self {
103        let mut combined = "".to_string();
104
105        for (idx, val) in vals.iter().enumerate() {
106            if idx != 0 {
107                combined += " ";
108            }
109
110            combined += val.as_ref();
111        }
112
113        AttributeValue::String(combined)
114    }
115}
116
117impl From<bool> for AttributeValue {
118    fn from(b: bool) -> Self {
119        AttributeValue::Bool(b)
120    }
121}
122
123impl From<&bool> for AttributeValue {
124    fn from(b: &bool) -> Self {
125        AttributeValue::Bool(*b)
126    }
127}
128
129impl Display for AttributeValue {
130    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
131        match self {
132            AttributeValue::String(s) => s.fmt(f),
133            AttributeValue::Bool(b) => b.fmt(f),
134        }
135    }
136}
137
138#[cfg(test)]
139mod tests {
140    use super::*;
141
142    #[test]
143    fn array_of_as_ref_str() {
144        assert_eq!(
145            AttributeValue::from(["hello", "world"]),
146            AttributeValue::String("hello world".to_string())
147        );
148    }
149
150    #[test]
151    fn vec_of_as_ref_str() {
152        assert_eq!(
153            AttributeValue::from(vec!["foo", "bar"]),
154            AttributeValue::String("foo bar".to_string())
155        );
156    }
157}