sauron_core/vdom/attribute/
value.rs

1use std::borrow::Cow;
2use std::fmt;
3
4/// Wraps different primitive variants used as values in html
5/// This is needed since html attributes can have different value types
6/// such as checked(bool), name(String), tab_index(i32)
7/// Note: memory size of Value is 32 bytes, in comparison String is 24 bytes
8#[derive(Debug, Clone)]
9pub enum Value {
10    /// bool value
11    Bool(bool),
12    /// String value and &'static str
13    Cow(Cow<'static, str>),
14    /// a vec of values
15    Vec(Vec<Value>),
16    /// u8 value
17    U8(u8),
18    /// u16 value
19    U16(u16),
20    /// u32 value
21    U32(u32),
22    /// u64 value
23    U64(u64),
24    /// usize value
25    Usize(usize),
26    /// u128 value
27    U128(u128),
28    /// i8 value
29    I8(i8),
30    /// i16 value
31    I16(i16),
32    /// i32 value
33    I32(i32),
34    /// i64 value
35    I64(i64),
36    /// i128 value
37    I128(i128),
38    /// isize value
39    Isize(isize),
40    /// f32 value
41    F32(f32),
42    /// f64 value
43    F64(f64),
44}
45
46impl Value {
47    /// returns an &str reference if this value is `Str` or `String` variant
48    /// Note: This doesn't convert other variant into str representation
49    /// Use the `to_string()` for that.
50    pub fn as_str(&self) -> Option<&str> {
51        match self {
52            Self::Cow(ref v) => Some(v.as_ref()),
53            _ => None,
54        }
55    }
56
57    /// returns the bool value if this a Bool variant
58    pub fn as_bool(&self) -> Option<bool> {
59        match self {
60            Self::Bool(v) => Some(*v),
61            _ => None,
62        }
63    }
64
65    /// converts to f32 if the variants are numerical representation
66    pub fn as_f32(&self) -> Option<f32> {
67        match self {
68            Self::Bool(_) => None,
69            Self::Cow(_v) => None,
70            Self::Vec(_v) => None,
71            Self::U8(v) => Some(f32::from(*v)),
72            Self::U16(v) => Some(f32::from(*v)),
73            Self::U32(v) => Some(*v as f32),
74            Self::U64(v) => Some(*v as f32),
75            Self::U128(v) => Some(*v as f32),
76            Self::Usize(v) => Some(*v as f32),
77            Self::I8(v) => Some(f32::from(*v)),
78            Self::I16(v) => Some(f32::from(*v)),
79            Self::I32(v) => Some(*v as f32),
80            Self::I64(v) => Some(*v as f32),
81            Self::I128(v) => Some(*v as f32),
82            Self::Isize(v) => Some(*v as f32),
83            Self::F32(v) => Some(*v),
84            Self::F64(v) => Some(*v as f32),
85        }
86    }
87
88    /// converts to f64 if the variants are numerical representation
89    pub fn as_f64(&self) -> Option<f64> {
90        match self {
91            Self::Bool(_) => None,
92            Self::Cow(_v) => None,
93            Self::Vec(_v) => None,
94            Self::U8(v) => Some(f64::from(*v)),
95            Self::U16(v) => Some(f64::from(*v)),
96            Self::U32(v) => Some(f64::from(*v)),
97            Self::U64(v) => Some(*v as f64),
98            Self::U128(v) => Some(*v as f64),
99            Self::Usize(v) => Some(*v as f64),
100            Self::I8(v) => Some(f64::from(*v)),
101            Self::I16(v) => Some(f64::from(*v)),
102            Self::I32(v) => Some(f64::from(*v)),
103            Self::I64(v) => Some(*v as f64),
104            Self::I128(v) => Some(*v as f64),
105            Self::Isize(v) => Some(*v as f64),
106            Self::F32(v) => Some(f64::from(*v)),
107            Self::F64(v) => Some(*v),
108        }
109    }
110
111    /// converts to i32 if the variants are numerical representation
112    pub fn as_i32(&self) -> Option<i32> {
113        match self {
114            Self::Bool(_) => None,
115            Self::Cow(_v) => None,
116            Self::Vec(_v) => None,
117            Self::U8(v) => Some(i32::from(*v)),
118            Self::U16(v) => Some(i32::from(*v)),
119            Self::U32(v) => Some(*v as i32),
120            Self::U64(v) => Some(*v as i32),
121            Self::U128(v) => Some(*v as i32),
122            Self::Usize(v) => Some(*v as i32),
123            Self::I8(v) => Some(i32::from(*v)),
124            Self::I16(v) => Some(i32::from(*v)),
125            Self::I32(v) => Some(*v),
126            Self::I64(v) => Some(*v as i32),
127            Self::I128(v) => Some(*v as i32),
128            Self::Isize(v) => Some(*v as i32),
129            Self::F32(v) => Some(*v as i32),
130            Self::F64(v) => Some(*v as i32),
131        }
132    }
133
134    /// converts to i64 if the variants are numerical representation
135    pub fn as_i64(&self) -> Option<i64> {
136        match self {
137            Self::Bool(_) => None,
138            Self::Cow(_v) => None,
139            Self::Vec(_v) => None,
140            Self::U8(v) => Some(i64::from(*v)),
141            Self::U16(v) => Some(i64::from(*v)),
142            Self::U32(v) => Some(*v as i64),
143            Self::U64(v) => Some(*v as i64),
144            Self::U128(v) => Some(*v as i64),
145            Self::Usize(v) => Some(*v as i64),
146            Self::I8(v) => Some(i64::from(*v)),
147            Self::I16(v) => Some(i64::from(*v)),
148            Self::I32(v) => Some(*v as i64),
149            Self::I64(v) => Some(*v),
150            Self::I128(v) => Some(*v as i64),
151            Self::Isize(v) => Some(*v as i64),
152            Self::F32(v) => Some(*v as i64),
153            Self::F64(v) => Some(*v as i64),
154        }
155    }
156
157    /// If this is Value::Vec variant, append the new value
158    /// otherwise, turn this value into Value::Vec(Vec<Value>) variant
159    /// and append the new value.
160    pub fn append(&mut self, new_value: Value) {
161        match self {
162            Self::Vec(values) => {
163                values.push(new_value);
164            }
165            _ => {
166                *self = Value::Vec(vec![self.clone(), new_value]);
167            }
168        }
169    }
170
171    pub(crate) fn merge_to_string<'a>(
172        values: impl IntoIterator<Item = &'a Value>,
173    ) -> Option<String> {
174        let stringed = values
175            .into_iter()
176            .map(|v| v.to_string())
177            .collect::<Vec<_>>();
178        if !stringed.is_empty() {
179            Some(stringed.join(" "))
180        } else {
181            None
182        }
183    }
184}
185
186impl PartialEq for Value {
187    fn eq(&self, other: &Self) -> bool {
188        match (self, other) {
189            (Self::Bool(v), Self::Bool(o)) => v == o,
190            (Self::Cow(v), Self::Cow(o)) => v == o,
191            (Self::Vec(v), Self::Vec(o)) => v == o,
192            (Self::U8(v), Self::U8(o)) => v == o,
193            (Self::U16(v), Self::U16(o)) => v == o,
194            (Self::U32(v), Self::U32(o)) => v == o,
195            (Self::U64(v), Self::U64(o)) => v == o,
196            (Self::U128(v), Self::U128(o)) => v == o,
197            (Self::Usize(v), Self::Usize(o)) => v == o,
198            (Self::I8(v), Self::I8(o)) => v == o,
199            (Self::I16(v), Self::I16(o)) => v == o,
200            (Self::I32(v), Self::I32(o)) => v == o,
201            (Self::I64(v), Self::I64(o)) => v == o,
202            (Self::I128(v), Self::I128(o)) => v == o,
203            (Self::Isize(v), Self::Isize(o)) => v == o,
204            (Self::F32(v), Self::F32(o)) => v == o,
205            (Self::F64(v), Self::F64(o)) => v == o,
206            _ => false,
207        }
208    }
209}
210
211impl Eq for Value {}
212
213impl fmt::Display for Value {
214    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
215        match self {
216            Self::Bool(v) => write!(f, "{}", v),
217            Self::Cow(v) => write!(f, "{}", v),
218            Self::Vec(v) => {
219                write!(
220                    f,
221                    "{}",
222                    v.iter()
223                        .map(ToString::to_string)
224                        .collect::<Vec<String>>()
225                        .join(" ")
226                )
227            }
228            Self::U8(v) => write!(f, "{}", v),
229            Self::U16(v) => write!(f, "{}", v),
230            Self::U32(v) => write!(f, "{}", v),
231            Self::U64(v) => write!(f, "{}", v),
232            Self::U128(v) => write!(f, "{}", v),
233            Self::Usize(v) => write!(f, "{}", v),
234            Self::I8(v) => write!(f, "{}", v),
235            Self::I16(v) => write!(f, "{}", v),
236            Self::I32(v) => write!(f, "{}", v),
237            Self::I64(v) => write!(f, "{}", v),
238            Self::I128(v) => write!(f, "{}", v),
239            Self::Isize(v) => write!(f, "{}", v),
240            Self::F32(v) => write!(f, "{}", v),
241            Self::F64(v) => write!(f, "{}", v),
242        }
243    }
244}
245
246impl From<&String> for Value {
247    fn from(v: &String) -> Self {
248        Self::Cow(v.to_string().into())
249    }
250}
251
252impl From<&'static str> for Value {
253    fn from(v: &'static str) -> Self {
254        Self::Cow(v.into())
255    }
256}
257
258impl From<String> for Value {
259    fn from(v: String) -> Self {
260        Self::Cow(v.into())
261    }
262}
263
264impl<T, const N: usize> From<[T; N]> for Value
265where
266    T: Into<Value> + Clone,
267{
268    fn from(v: [T; N]) -> Self {
269        Value::Vec(
270            v.iter()
271                .map(|i| i.to_owned().into())
272                .collect::<Vec<Value>>(),
273        )
274    }
275}
276
277macro_rules! impl_from {
278    ($ty:ty => $variant:ident) => {
279        impl From<$ty> for Value {
280            fn from(f: $ty) -> Self {
281                Value::$variant(f)
282            }
283        }
284    };
285}
286
287impl_from!(bool => Bool);
288impl_from!(u8 => U8);
289impl_from!(u16 => U16);
290impl_from!(u32 => U32);
291impl_from!(u64 => U64);
292impl_from!(u128 => U128);
293impl_from!(usize => Usize);
294impl_from!(i8 => I8);
295impl_from!(i16 => I16);
296impl_from!(i32 => I32);
297impl_from!(i64 => I64);
298impl_from!(i128 => I128);
299impl_from!(isize => Isize);
300impl_from!(f32 => F32);
301impl_from!(f64 => F64);
302
303impl<V0, V1> From<(V0, V1)> for Value
304where
305    V0: Into<Value>,
306    V1: Into<Value>,
307{
308    fn from(values: (V0, V1)) -> Self {
309        Self::Vec(vec![values.0.into(), values.1.into()])
310    }
311}
312
313impl<V0, V1, V2> From<(V0, V1, V2)> for Value
314where
315    V0: Into<Value>,
316    V1: Into<Value>,
317    V2: Into<Value>,
318{
319    fn from(values: (V0, V1, V2)) -> Self {
320        Self::Vec(vec![values.0.into(), values.1.into(), values.2.into()])
321    }
322}
323
324impl<V0, V1, V2, V3> From<(V0, V1, V2, V3)> for Value
325where
326    V0: Into<Value>,
327    V1: Into<Value>,
328    V2: Into<Value>,
329    V3: Into<Value>,
330{
331    fn from(values: (V0, V1, V2, V3)) -> Self {
332        Self::Vec(vec![
333            values.0.into(),
334            values.1.into(),
335            values.2.into(),
336            values.3.into(),
337        ])
338    }
339}
340
341impl<V0, V1, V2, V3, V4> From<(V0, V1, V2, V3, V4)> for Value
342where
343    V0: Into<Value>,
344    V1: Into<Value>,
345    V2: Into<Value>,
346    V3: Into<Value>,
347    V4: Into<Value>,
348{
349    fn from(values: (V0, V1, V2, V3, V4)) -> Self {
350        Self::Vec(vec![
351            values.0.into(),
352            values.1.into(),
353            values.2.into(),
354            values.3.into(),
355            values.4.into(),
356        ])
357    }
358}