1use serde::{Deserialize, Serialize};
2
3const MAX_FLOAT_PRECISION: i32 = 8;
4
5pub type IntegerType = i64;
7
8pub type FloatType = f64;
10
11pub type ArrayType = Vec<Value>;
13
14#[derive(Debug, Serialize, Deserialize)]
24pub enum Value {
25 None,
27
28 Identifier(String),
30
31 Boolean(bool),
33
34 Integer(IntegerType),
36
37 Float(FloatType),
39
40 String(String),
42
43 Array(ArrayType)
45}
46
47impl std::fmt::Display for Value {
48 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
49 write!(f, "{}", self.as_string())
50 }
51}
52
53impl Value {
54 pub fn as_string(&self) -> String {
56 match self {
57 Value::Boolean(v) => (if *v {"true"} else {"false"}).to_string(),
58 Value::Integer(n) => {format!("{}", *n)},
59 Value::Float(n) => {
60 let multiplier = f64::powi(10.0, MAX_FLOAT_PRECISION);
61 let mut v = (*n * multiplier).round() / multiplier;
62
63 if v == -0.0 { v = 0.0; }
64 let mut f = format!("{:}", v);
65 if !f.contains('.') {
66 f += ".0";
67 }
68
69 f
70 },
71 Value::String(s) => s.to_string(),
72 Value::Array(v) => format!("[{}]", v.iter().map(|e| e.as_string()).collect::<Vec<String>>().join(", ")),
73 Value::Identifier(s) => s.to_string(),
74 Value::None => "".to_string(),
75 }
76 }
77
78 pub fn as_bool(&self) -> bool {
80 match self {
81 Value::None => false,
82 Value::Identifier(_) => false,
83 Value::Boolean(v) => *v,
84 Value::Integer(n) => *n != 0,
85 Value::Float(n) => *n != 0.0,
86 Value::String(s) => !s.is_empty(),
87 Value::Array(v) => v.iter().any(|e|e.as_bool())
88 }
89 }
90
91 pub fn as_int(&self) -> Option<IntegerType> {
93 match self {
94 Value::None => None,
95 Value::Identifier(_) => None,
96 Value::Boolean(v) => Some(*v as IntegerType),
97 Value::Integer(n) => Some(*n),
98 Value::Float(n) => Some(*n as IntegerType),
99 Value::String(_) => None,
100 Value::Array(_) => None,
101 }
102 }
103
104 pub fn as_float(&self) -> Option<FloatType> {
106 match self {
107 Value::None => None,
108 Value::Identifier(_) => None,
109 Value::Boolean(v) => Some((*v as IntegerType) as FloatType),
110 Value::Integer(n) => Some(*n as FloatType),
111 Value::Float(n) => Some(*n),
112 Value::String(_) => None,
113 Value::Array(_) => None,
114 }
115 }
116
117 pub fn as_array(&self) -> ArrayType {
119 match self {
120 Value::None => vec![],
121 Value::Identifier(_) => vec![],
122 Value::Boolean(_) => vec![self.clone()],
123 Value::Integer(_) => vec![self.clone()],
124 Value::Float(_) => vec![self.clone()],
125 Value::String(_) => vec![self.clone()],
126 Value::Array(v) => v.clone(),
127 }
128 }
129
130 pub fn is_bool(&self) -> bool {
132 matches!(self, Value::Boolean(_))
133 }
134
135 pub fn is_int(&self) -> bool {
137 matches!(self, Value::Integer(_))
138 }
139
140 pub fn is_float(&self) -> bool {
142 matches!(self, Value::Float(_))
143 }
144
145 pub fn is_numeric(&self) -> bool {
147 self.is_float() || self.is_int()
148 }
149
150 pub fn is_string(&self) -> bool {
152 matches!(self, Value::String(_))
153 }
154
155 pub fn is_array(&self) -> bool {
157 matches!(self, Value::Array(_))
158 }
159
160 pub fn is_identifier(&self) -> bool {
162 matches!(self, Value::Identifier(_))
163 }
164
165 pub fn is_none(&self) -> bool {
167 matches!(self, Value::None)
168 }
169}
170
171impl Clone for Value {
172 fn clone(&self) -> Value {
173 match self {
174 Value::None => Value::None,
175 Value::Identifier(s) => Value::Identifier(s.to_string()),
176 Value::Boolean(v) => Value::Boolean(*v),
177 Value::Integer(n) => Value::Integer(*n),
178 Value::Float(n) => Value::Float(*n),
179 Value::String(s) => Value::String(s.to_string()),
180 Value::Array(v) => Value::Array(v.clone()),
181 }
182 }
183}
184
185impl PartialEq for Value {
186 fn eq(&self, other: &Self) -> bool {
187 match (self, other) {
188 (Value::None, Value::None) => true,
189 (Value::Identifier(s), Value::Identifier(o)) => s == o,
190 (Value::Boolean(s), Value::Boolean(o)) => s == o,
191 (Value::Integer(s), Value::Integer(o)) => s == o,
192 (Value::Float(s), Value::Float(o)) => s == o,
193 (Value::String(s), Value::String(o)) => s == o,
194 (Value::Array(s), Value::Array(o)) => s == o,
195
196 _ => false
197 }
198 }
199}
200
201impl PartialEq<bool> for Value {
202 fn eq(&self, other: &bool) -> bool {
203 self.as_bool() == *other
204 }
205}
206
207impl PartialEq<IntegerType> for Value {
208 fn eq(&self, other: &IntegerType) -> bool {
209 if let Some(n) = self.as_int() {
210 n == *other
211 } else {
212 false
213 }
214 }
215}
216
217impl PartialEq<FloatType> for Value {
218 fn eq(&self, other: &FloatType) -> bool {
219 if let Some(n) = self.as_float() {
220 n == *other
221 } else {
222 false
223 }
224 }
225}
226
227impl PartialEq<String> for Value {
228 fn eq(&self, other: &String) -> bool {
229 self.as_string() == *other
230 }
231}
232
233impl PartialEq<&str> for Value {
234 fn eq(&self, other: &&str) -> bool {
235 self.as_string() == *other.to_string()
236 }
237}
238
239impl PartialEq<ArrayType> for Value {
240 fn eq(&self, other: &ArrayType) -> bool {
241 self.as_array().len() == other.len() &&
242 self.as_array().iter().zip(other.iter()).all(|(a,b)| a == b)
243 }
244}
245
246impl Eq for Value {}
247
248#[cfg(test)]
249mod test_atomic_value {
250 use super::*;
251
252 #[test]
253 fn test_as_string() {
254 assert_eq!("5", Value::Integer(5).as_string());
255 assert_eq!("5.0", Value::Float(5.0).as_string());
256 assert_eq!("5.1", Value::Float(5.1).as_string());
257 assert_eq!("test", Value::String("test".to_string()).as_string());
258 assert_eq!("", Value::None.as_string());
259 }
260
261 #[test]
262 fn test_as_bool() {
263 assert_eq!(true, Value::Float(5.0).as_bool());
264 assert_eq!(true, Value::Integer(5).as_bool());
265 assert_eq!(true, Value::String("5.0".to_string()).as_bool());
266 }
267
268 #[test]
269 fn test_as_int() {
270 assert_eq!(true, Value::Float(5.0).as_int().is_some());
271 assert_eq!(5, Value::Float(5.0).as_int().unwrap());
272
273 assert_eq!(true, Value::Integer(5).as_int().is_some());
274 assert_eq!(5, Value::Integer(5).as_int().unwrap());
275
276 assert_eq!(false, Value::String("".to_string()).as_int().is_some());
277 }
278
279 #[test]
280 fn test_as_float() {
281 assert_eq!(true, Value::Float(5.0).as_float().is_some());
282 assert_eq!(5.0, Value::Float(5.0).as_float().unwrap());
283
284 assert_eq!(true, Value::Integer(5).as_float().is_some());
285 assert_eq!(5.0, Value::Integer(5).as_float().unwrap());
286
287 assert_eq!(false, Value::String("".to_string()).as_float().is_some());
288 }
289
290 #[test]
291 fn test_as_array() {
292 assert_eq!(1, Value::Float(5.0).as_array().len());
293 assert_eq!(2, Value::Array(vec![Value::Integer(5), Value::Integer(5)]).as_array().len());
294 }
295
296 #[test]
297 fn test_is_float() {
298 assert_eq!(true, Value::Float(5.0).is_float());
299 assert_eq!(false, Value::Integer(5).is_float());
300 }
301
302 #[test]
303 fn test_is_string() {
304 assert_eq!(true, Value::String("5.0".to_string()).is_string());
305 assert_eq!(false, Value::Integer(5).is_string());
306 }
307
308 #[test]
309 fn test_is_array() {
310 assert_eq!(true, Value::Array(vec![Value::Integer(5)]).is_array());
311 assert_eq!(false, Value::Integer(5).is_array());
312 }
313
314 #[test]
315 fn test_is_identifier() {
316 assert_eq!(false, Value::Array(vec![Value::Integer(5)]).is_identifier());
317 assert_eq!(false, Value::Integer(5).is_array());
318 }
319
320 #[test]
321 fn test_eq() {
322 assert_eq!(false, Value::Float(5.0) == Value::Float(5.1));
323 assert_eq!(true, Value::Float(5.0) == Value::Float(5.0));
324 assert_eq!(true, Value::Integer(5) == Value::Integer(5));
325 assert_eq!(false, Value::Integer(6) == Value::Integer(5));
326 assert_eq!(true, Value::None == Value::None);
327 assert_eq!(true, Value::String("test".to_string()) == Value::String("test".to_string()));
328 assert_eq!(false, Value::String("test".to_string()) == Value::String("test2".to_string()));
329 }
330}