jss/
value.rs

1use std::fmt;
2
3/// Wraps different primitive variants used as values in html
4/// This is needed since html attributes can have different value types
5/// such as checked(bool), name(String), tab_index(i32)
6/// Note: memory size of Value is 32 bytes, in comparison String is 24 bytes
7#[derive(Debug, PartialEq, Clone)]
8pub enum Value {
9    /// bool value
10    Bool(bool),
11    /// &'static str value
12    Str(&'static str),
13    /// String value
14    String(String),
15    /// a vec of values
16    Vec(Vec<Value>),
17    /// u8 value
18    U8(u8),
19    /// u16 value
20    U16(u16),
21    /// u32 value
22    U32(u32),
23    /// u64 value
24    U64(u64),
25    /// usize value
26    Usize(usize),
27    /// u128 value
28    U128(u128),
29    /// i8 value
30    I8(i8),
31    /// i16 value
32    I16(i16),
33    /// i32 value
34    I32(i32),
35    /// i64 value
36    I64(i64),
37    /// i128 value
38    I128(i128),
39    /// isize value
40    Isize(isize),
41    /// f32 value
42    F32(f32),
43    /// f64 value
44    F64(f64),
45}
46
47impl Value {
48    /// returns an &str reference if this value is `Str` or `String` variant
49    /// Note: This doesn't convert other variant into str representation
50    /// Use the `to_string()` for that.
51    pub fn as_str(&self) -> Option<&str> {
52        match self {
53            Value::String(ref v) => Some(v),
54            Value::Str(v) => Some(v),
55            _ => None,
56        }
57    }
58
59    /// returns the bool value if this a Bool variant
60    pub fn as_bool(&self) -> Option<bool> {
61        match self {
62            Value::Bool(v) => Some(*v),
63            _ => None,
64        }
65    }
66
67    /// converts to f64 if the variants are numerical representation
68    pub fn as_f64(&self) -> Option<f64> {
69        match self {
70            Value::Bool(_) => None,
71            Value::String(_v) => None,
72            Value::Str(_v) => None,
73            Value::Vec(_v) => None,
74            Value::U8(v) => Some(f64::from(*v)),
75            Value::U16(v) => Some(f64::from(*v)),
76            Value::U32(v) => Some(f64::from(*v)),
77            Value::U64(v) => Some(*v as f64),
78            Value::U128(v) => Some(*v as f64),
79            Value::Usize(v) => Some(*v as f64),
80            Value::I8(v) => Some(f64::from(*v)),
81            Value::I16(v) => Some(f64::from(*v)),
82            Value::I32(v) => Some(f64::from(*v)),
83            Value::I64(v) => Some(*v as f64),
84            Value::I128(v) => Some(*v as f64),
85            Value::Isize(v) => Some(*v as f64),
86            Value::F32(v) => Some(f64::from(*v)),
87            Value::F64(v) => Some(*v),
88        }
89    }
90
91    /// converts to i32 if the variants are numerical representation
92    pub fn as_i32(&self) -> Option<i32> {
93        match self {
94            Value::Bool(_) => None,
95            Value::String(_v) => None,
96            Value::Str(_v) => None,
97            Value::Vec(_v) => None,
98            Value::U8(v) => Some(i32::from(*v)),
99            Value::U16(v) => Some(i32::from(*v)),
100            Value::U32(v) => Some(*v as i32),
101            Value::U64(v) => Some(*v as i32),
102            Value::U128(v) => Some(*v as i32),
103            Value::Usize(v) => Some(*v as i32),
104            Value::I8(v) => Some(i32::from(*v)),
105            Value::I16(v) => Some(i32::from(*v)),
106            Value::I32(v) => Some(*v),
107            Value::I64(v) => Some(*v as i32),
108            Value::I128(v) => Some(*v as i32),
109            Value::Isize(v) => Some(*v as i32),
110            Value::F32(v) => Some(*v as i32),
111            Value::F64(v) => Some(*v as i32),
112        }
113    }
114
115    /// If this is Value::Vec variant, append the new value
116    /// otherwise, turn this value into Value::Vec(Vec<Value>) variant
117    /// and append the new value.
118    pub fn append(&mut self, new_value: Value) {
119        match self {
120            Value::Vec(values) => {
121                values.push(new_value);
122            }
123            _ => {
124                *self = Value::Vec(vec![self.clone(), new_value]);
125            }
126        }
127    }
128}
129
130impl fmt::Display for Value {
131    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
132        match self {
133            Value::Bool(v) => write!(f, "{}", v),
134            Value::String(v) => write!(f, "{}", v),
135            Value::Str(v) => write!(f, "{}", v),
136            Value::Vec(v) => {
137                write!(
138                    f,
139                    "{}",
140                    v.iter()
141                        .map(ToString::to_string)
142                        .collect::<Vec<String>>()
143                        .join(" ")
144                )
145            }
146            Value::U8(v) => write!(f, "{}", v),
147            Value::U16(v) => write!(f, "{}", v),
148            Value::U32(v) => write!(f, "{}", v),
149            Value::U64(v) => write!(f, "{}", v),
150            Value::U128(v) => write!(f, "{}", v),
151            Value::Usize(v) => write!(f, "{}", v),
152            Value::I8(v) => write!(f, "{}", v),
153            Value::I16(v) => write!(f, "{}", v),
154            Value::I32(v) => write!(f, "{}", v),
155            Value::I64(v) => write!(f, "{}", v),
156            Value::I128(v) => write!(f, "{}", v),
157            Value::Isize(v) => write!(f, "{}", v),
158            Value::F32(v) => write!(f, "{}", v),
159            Value::F64(v) => write!(f, "{}", v),
160        }
161    }
162}
163
164impl From<&String> for Value {
165    fn from(v: &String) -> Self {
166        Value::String(v.to_string())
167    }
168}
169
170impl<T, const N: usize> From<[T; N]> for Value
171where
172    T: Into<Value> + Clone,
173{
174    fn from(v: [T; N]) -> Self {
175        Value::Vec(
176            v.iter()
177                .map(|i| i.to_owned().into())
178                .collect::<Vec<Value>>(),
179        )
180    }
181}
182
183macro_rules! impl_from {
184    ($ty:ty => $variant:ident) => {
185        impl From<$ty> for Value {
186            fn from(f: $ty) -> Self {
187                Value::$variant(f)
188            }
189        }
190    };
191}
192
193impl_from!(bool => Bool);
194impl_from!(String => String);
195impl_from!(&'static str => Str);
196impl_from!(u8 => U8);
197impl_from!(u16 => U16);
198impl_from!(u32 => U32);
199impl_from!(u64 => U64);
200impl_from!(u128 => U128);
201impl_from!(usize => Usize);
202impl_from!(i8 => I8);
203impl_from!(i16 => I16);
204impl_from!(i32 => I32);
205impl_from!(i64 => I64);
206impl_from!(i128 => I128);
207impl_from!(isize => Isize);
208impl_from!(f32 => F32);
209impl_from!(f64 => F64);
210
211macro_rules! impl_from_tuple {
212    (($($T:ident),*) => $($n:tt),*) => {
213        impl<$($T),*>From<($($T),*)> for Value
214            where
215                $($T: Into<Value>),*
216        {
217            fn from(v: ($($T),*)) -> Self {
218                Value::Vec(vec![$(v.$n.into()),*])
219            }
220        }
221    };
222}
223
224impl_from_tuple!((T, U) => 0, 1);
225impl_from_tuple!((T, U, V) => 0, 1, 2);
226impl_from_tuple!((T, U, V, X) => 0, 1, 2, 3);
227impl_from_tuple!((T, U, V, X, Z) => 0, 1, 2, 3, 4);