slac/
value.rs

1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize, de::Visitor, ser::SerializeSeq};
3
4use std::{
5    cmp::Ordering,
6    fmt::Display,
7    hash::{Hash, Hasher},
8    ops::{Add, BitXor, Div, Mul, Neg, Not, Rem, Sub},
9};
10
11use crate::{
12    Operator,
13    error::{self, Error},
14};
15
16/// A Wrapper for the four different possible variable types.
17#[derive(Debug, Clone)]
18pub enum Value {
19    Boolean(bool),
20    String(String),
21    Number(f64),
22    Array(Vec<Value>),
23}
24impl Eq for Value {}
25
26impl PartialOrd for Value {
27    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
28        Some(self.cmp(other))
29    }
30}
31
32impl Ord for Value {
33    fn cmp(&self, other: &Self) -> Ordering {
34        let partial_ord = match (self, other) {
35            (Value::Boolean(left), Value::Boolean(right)) => left.partial_cmp(right),
36            (Value::String(left), Value::String(right)) => left.partial_cmp(right),
37            (Value::Number(left), Value::Number(right)) => left.partial_cmp(right),
38            (Value::Array(left), Value::Array(right)) => left.partial_cmp(right),
39
40            // allow comparison of strings and numbers if the string parses to a number
41            (left @ Value::String(_), Value::Number(right)) => {
42                left.as_num().and_then(|parsed| parsed.partial_cmp(right))
43            }
44            (Value::Number(left), right @ Value::String(_)) => {
45                right.as_num().and_then(|parsed| left.partial_cmp(&parsed))
46            }
47
48            _ => None,
49        };
50
51        partial_ord.unwrap_or_else(|| self.ordinal().cmp(&other.ordinal()))
52    }
53}
54
55impl PartialEq for Value {
56    fn eq(&self, other: &Self) -> bool {
57        match (self, other) {
58            (Self::Boolean(l0), Self::Boolean(r0)) => l0 == r0,
59            (Self::String(l0), Self::String(r0)) => l0 == r0,
60            (Self::Number(l0), Self::Number(r0)) => l0 == r0,
61            (Self::Array(l0), Self::Array(r0)) => l0 == r0,
62
63            // allow equality of `Value::Boolean` and non-empty values of other types
64            (Value::Boolean(bool), value) | (value, Value::Boolean(bool)) => {
65                *bool == value.as_bool()
66            }
67
68            // allow equality of `Value::Number` with other types
69            (Value::Number(number), value) | (value, Value::Number(number)) => {
70                Some(*number) == value.as_num()
71            }
72
73            _ => self.cmp(other) == Ordering::Equal,
74        }
75    }
76}
77
78impl Hash for Value {
79    fn hash<H: Hasher>(&self, state: &mut H) {
80        core::mem::discriminant(self).hash(state);
81    }
82}
83
84impl Neg for Value {
85    type Output = error::Result<Value>;
86
87    fn neg(self) -> Self::Output {
88        match self {
89            Value::Number(value) => Ok(Value::Number(-value)),
90            _ => Err(Error::InvalidUnaryOperator(Operator::Minus)),
91        }
92    }
93}
94
95impl Not for Value {
96    type Output = error::Result<Value>;
97
98    fn not(self) -> Self::Output {
99        Ok(Value::Boolean(!self.as_bool()))
100    }
101}
102
103impl Add for Value {
104    type Output = error::Result<Value>;
105
106    fn add(self, rhs: Self) -> Self::Output {
107        match (self, rhs) {
108            (Value::String(lhs), Value::String(rhs)) => Ok(Value::String(lhs + &rhs)),
109            (Value::Number(lhs), Value::Number(rhs)) => Ok(Value::Number(lhs + rhs)),
110            (Value::Array(lhs), Value::Array(rhs)) => Ok(Value::Array([lhs, rhs].concat())),
111            _ => Err(Error::InvalidBinaryOperator(Operator::Plus)),
112        }
113    }
114}
115
116impl Sub for Value {
117    type Output = error::Result<Value>;
118
119    fn sub(self, rhs: Self) -> Self::Output {
120        match (self, rhs) {
121            (Value::Number(lhs), Value::Number(rhs)) => Ok(Value::Number(lhs - rhs)),
122            _ => Err(Error::InvalidBinaryOperator(Operator::Minus)),
123        }
124    }
125}
126
127impl Mul for Value {
128    type Output = error::Result<Value>;
129
130    fn mul(self, rhs: Self) -> Self::Output {
131        match (self, rhs) {
132            (Value::Number(lhs), Value::Number(rhs)) => Ok(Value::Number(lhs * rhs)),
133            _ => Err(Error::InvalidBinaryOperator(Operator::Multiply)),
134        }
135    }
136}
137
138impl Div for Value {
139    type Output = error::Result<Value>;
140
141    fn div(self, rhs: Self) -> Self::Output {
142        match (self, rhs) {
143            (Value::Number(lhs), Value::Number(rhs)) => Ok(Value::Number(lhs / rhs)),
144            _ => Err(Error::InvalidBinaryOperator(Operator::Divide)),
145        }
146    }
147}
148
149impl Rem for Value {
150    type Output = error::Result<Value>;
151
152    fn rem(self, rhs: Self) -> Self::Output {
153        match (self, rhs) {
154            (Value::Number(lhs), Value::Number(rhs)) => Ok(Value::Number(lhs % rhs)),
155            _ => Err(Error::InvalidBinaryOperator(Operator::Mod)),
156        }
157    }
158}
159
160impl BitXor for Value {
161    type Output = error::Result<Value>;
162
163    fn bitxor(self, rhs: Self) -> Self::Output {
164        match (self, rhs) {
165            (Value::Boolean(lhs), Value::Boolean(rhs)) => Ok(Value::Boolean(lhs ^ rhs)),
166            _ => Err(Error::InvalidBinaryOperator(Operator::Xor)),
167        }
168    }
169}
170
171impl Display for Value {
172    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
173        match self {
174            Value::Boolean(v) => write!(f, "{v}"),
175            Value::String(v) => write!(f, "{v}"),
176            Value::Number(v) => write!(f, "{v}"),
177            Value::Array(v) => write!(f, "{v:?}"),
178        }
179    }
180}
181
182impl Value {
183    /// Integer division between two operands. Returns the whole number quotient,
184    /// discarding any fractional part.
185    ///
186    /// # Examples
187    /// ```
188    /// use slac::Value;
189    ///
190    /// let a = Value::Number(10.0);
191    /// let b = Value::Number(3.0);
192    ///
193    /// assert_eq!(Ok(Value::Number(3.0)), a.div_int(b));
194    /// ```
195    ///
196    /// # Errors
197    ///
198    /// Returns [`Error::InvalidBinaryOperator`] if any side of the operator is not a Number.
199    pub fn div_int(self, rhs: Self) -> error::Result<Self> {
200        match (self, rhs) {
201            (Value::Number(lhs), Value::Number(rhs)) => Ok(Value::Number((lhs / rhs).trunc())),
202            _ => Err(Error::InvalidBinaryOperator(Operator::Div)),
203        }
204    }
205
206    /// Returns the length of a `String` or `Array` `Value`.
207    /// `Boolean` and `Number` have a length of 0.
208    #[must_use]
209    pub fn len(&self) -> usize {
210        match self {
211            Value::String(v) => v.len(),
212            Value::Array(v) => v.len(),
213            _ => 0,
214        }
215    }
216
217    /// Checks if the value is equal to the result of [`Value::empty()`].
218    #[must_use]
219    pub fn is_empty(&self) -> bool {
220        self == &Value::empty(self)
221    }
222
223    /// Returns an new empty `Value` of the same type as the callee.
224    /// * `Value::Boolean` -> `false`
225    /// * `Value::String` -> `''`
226    /// * `Value::Number` -> `0`
227    /// * `Value::Array` -> `[]`
228    #[must_use]
229    pub fn empty(&self) -> Self {
230        match self {
231            Value::Boolean(_) => Value::Boolean(false),
232            Value::String(_) => Value::String(String::new()),
233            Value::Number(_) => Value::Number(0.0),
234            Value::Array(_) => Value::Array(vec![]),
235        }
236    }
237
238    /// Returns the boolean representation of the `Value`.
239    /// Returns Booleans _as is_. Other `Value` kinds are based on
240    /// if the contained value is not [`Value::is_empty()`].
241    #[must_use]
242    pub fn as_bool(&self) -> bool {
243        match self {
244            Value::Boolean(v) => *v,
245            value => !value.is_empty(),
246        }
247    }
248
249    /// Returns the number representation of the `Value`.
250    #[must_use]
251    fn as_num(&self) -> Option<f64> {
252        match self {
253            Value::Number(v) => Some(*v),
254            Value::Boolean(v) => Some(f64::from(*v)),
255            Value::String(v) => v.parse::<f64>().ok(),
256            Value::Array(v) => Some(v.len() as f64),
257        }
258    }
259
260    /// Returns an ordinal value for each [`Value`] kind.
261    #[must_use]
262    fn ordinal(&self) -> u8 {
263        match self {
264            Value::Boolean(_) => 0,
265            Value::String(_) => 1,
266            Value::Number(_) => 2,
267            Value::Array(_) => 3,
268        }
269    }
270}
271
272#[cfg(feature = "serde")]
273impl Serialize for Value {
274    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
275    where
276        S: serde::Serializer,
277    {
278        match self {
279            Value::Boolean(v) => serializer.serialize_bool(*v),
280            Value::String(v) => serializer.serialize_str(v),
281            Value::Number(v) => serializer.serialize_f64(*v),
282            Value::Array(v) => {
283                let mut seq = serializer.serialize_seq(Some(v.len()))?;
284                for element in v {
285                    seq.serialize_element(element)?;
286                }
287                seq.end()
288            }
289        }
290    }
291}
292
293#[cfg(feature = "serde")]
294impl<'de> Deserialize<'de> for Value {
295    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
296    where
297        D: serde::Deserializer<'de>,
298    {
299        deserializer.deserialize_any(ValueVisitor)
300    }
301}
302
303#[cfg(feature = "serde")]
304struct ValueVisitor;
305
306#[cfg(feature = "serde")]
307impl<'de> Visitor<'de> for ValueVisitor {
308    type Value = Value;
309
310    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
311        write!(formatter, "a primitive value or list")
312    }
313
314    fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
315    where
316        E: serde::de::Error,
317    {
318        Ok(Value::Boolean(v))
319    }
320
321    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
322    where
323        E: serde::de::Error,
324    {
325        self.visit_string(v.to_string())
326    }
327
328    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
329    where
330        E: serde::de::Error,
331    {
332        Ok(Value::String(v))
333    }
334
335    #[allow(clippy::cast_precision_loss)]
336    fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
337    where
338        E: serde::de::Error,
339    {
340        self.visit_f64(v as f64)
341    }
342
343    #[allow(clippy::cast_precision_loss)]
344    fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
345    where
346        E: serde::de::Error,
347    {
348        self.visit_f64(v as f64)
349    }
350
351    fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
352    where
353        E: serde::de::Error,
354    {
355        Ok(Value::Number(v))
356    }
357
358    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
359    where
360        A: serde::de::SeqAccess<'de>,
361    {
362        let mut values = vec![];
363        while let Some(value) = seq.next_element()? {
364            values.push(value);
365        }
366
367        Ok(Value::Array(values))
368    }
369}
370
371#[cfg(test)]
372mod test {
373    use crate::{Error, Operator};
374
375    use super::Value;
376
377    fn test_div_int(divisor: f64) -> Value {
378        let a = Value::Number(10.0);
379        let b = Value::Number(divisor);
380
381        a.div_int(b).unwrap()
382    }
383
384    #[test]
385    fn number_div() {
386        assert_eq!(Value::Number(f64::INFINITY), test_div_int(0.0));
387        assert_eq!(Value::Number(10.0), test_div_int(1.0));
388        assert_eq!(Value::Number(5.0), test_div_int(2.0));
389        assert_eq!(Value::Number(3.0), test_div_int(3.0));
390        assert_eq!(Value::Number(2.0), test_div_int(4.0));
391        assert_eq!(Value::Number(2.0), test_div_int(5.0));
392        assert_eq!(Value::Number(1.0), test_div_int(6.0));
393        assert_eq!(Value::Number(1.0), test_div_int(7.0));
394        assert_eq!(Value::Number(1.0), test_div_int(9.0));
395        assert_eq!(Value::Number(1.0), test_div_int(10.0));
396        assert_eq!(Value::Number(0.0), test_div_int(11.0));
397    }
398
399    fn test_mod_int(divisor: f64) -> Value {
400        let a = Value::Number(10.0);
401        let b = Value::Number(divisor);
402
403        (a % b).unwrap()
404    }
405
406    #[test]
407    fn number_mod() {
408        match test_mod_int(0.0) {
409            Value::Number(value) => assert!(value.is_nan()),
410            _ => panic!(),
411        }
412        assert_eq!(Value::Number(0.0), test_mod_int(1.0));
413        assert_eq!(Value::Number(0.0), test_mod_int(2.0));
414        assert_eq!(Value::Number(1.0), test_mod_int(3.0));
415        assert_eq!(Value::Number(2.0), test_mod_int(4.0));
416        assert_eq!(Value::Number(0.0), test_mod_int(5.0));
417        assert_eq!(Value::Number(4.0), test_mod_int(6.0));
418        assert_eq!(Value::Number(3.0), test_mod_int(7.0));
419        assert_eq!(Value::Number(2.0), test_mod_int(8.0));
420        assert_eq!(Value::Number(1.0), test_mod_int(9.0));
421        assert_eq!(Value::Number(0.0), test_mod_int(10.0));
422    }
423
424    #[test]
425    fn is_empty() {
426        assert_eq!(true, Value::Boolean(false).is_empty());
427        assert_eq!(false, Value::Boolean(true).is_empty());
428        assert_eq!(true, Value::Number(0.0).is_empty());
429        assert_eq!(false, Value::Number(1.0).is_empty());
430
431        assert_eq!(true, Value::String(String::new()).is_empty());
432        assert_eq!(false, Value::String(String::from("something")).is_empty());
433
434        assert_eq!(true, Value::Array(vec![]).is_empty());
435        assert_eq!(false, Value::Array(vec![Value::Boolean(true)]).is_empty());
436    }
437
438    #[test]
439    fn invalid_operations() {
440        assert_eq!(
441            Err(Error::InvalidUnaryOperator(Operator::Minus)),
442            -Value::String(String::from("a string"))
443        );
444        assert_eq!(
445            Err(Error::InvalidBinaryOperator(Operator::Plus)),
446            Value::Number(10.0) + Value::String(String::from("a string"))
447        );
448        assert_eq!(
449            Err(Error::InvalidBinaryOperator(Operator::Minus)),
450            Value::Number(10.0) - Value::String(String::from("a string"))
451        );
452        assert_eq!(
453            Err(Error::InvalidBinaryOperator(Operator::Multiply)),
454            Value::Number(10.0) * Value::String(String::from("a string"))
455        );
456        assert_eq!(
457            Err(Error::InvalidBinaryOperator(Operator::Divide)),
458            Value::Number(10.0) / Value::String(String::from("a string"))
459        );
460        assert_eq!(
461            Err(Error::InvalidBinaryOperator(Operator::Mod)),
462            Value::Number(10.0) % Value::String(String::from("a string"))
463        );
464        assert_eq!(
465            Err(Error::InvalidBinaryOperator(Operator::Div)),
466            Value::Number(10.0).div_int(Value::Boolean(false))
467        );
468        assert_eq!(
469            Err(Error::InvalidBinaryOperator(Operator::Xor)),
470            Value::Number(10.0) ^ Value::Boolean(false)
471        );
472    }
473
474    #[test]
475    fn test_cmp_string_number() {
476        assert!(Value::Number(5.0) > Value::String(String::from("1")));
477        assert!(Value::Number(5.0) < Value::String(String::from("6")));
478        assert!(Value::Number(5.0) == Value::String(String::from("5")));
479        assert!(Value::Number(5.0) >= Value::String(String::from("5")));
480        assert!(Value::Number(5.0) >= Value::String(String::from("4")));
481        assert!(Value::Number(5.0) <= Value::String(String::from("5")));
482        assert!(Value::Number(5.0) <= Value::String(String::from("6")));
483
484        assert!(Value::String(String::from("1")) < Value::Number(5.0));
485        assert!(Value::String(String::from("6")) > Value::Number(5.0));
486        assert!(Value::String(String::from("5")) == Value::Number(5.0));
487        assert!(Value::String(String::from("5")) <= Value::Number(5.0));
488        assert!(Value::String(String::from("4")) <= Value::Number(5.0));
489        assert!(Value::String(String::from("5")) >= Value::Number(5.0));
490        assert!(Value::String(String::from("6")) >= Value::Number(5.0));
491    }
492
493    #[test]
494    fn test_eq_number_string() {
495        assert_eq!(Value::Number(0.0), Value::String(String::from("0")));
496        assert_eq!(Value::Number(1.0), Value::String(String::from("1")));
497        assert_eq!(Value::Number(2.5), Value::String(String::from("2.5")));
498        assert_ne!(Value::Number(0.0), Value::String(String::from("1000")));
499        assert_ne!(Value::Number(1.5), Value::String(String::from("1,5")));
500    }
501
502    #[test]
503    fn test_eq_boolean_number() {
504        assert_eq!(Value::Boolean(false), Value::Number(0.0));
505        assert_ne!(Value::Boolean(false), Value::Number(1.0));
506        assert_ne!(Value::Boolean(false), Value::Number(2.0));
507
508        assert_ne!(Value::Boolean(true), Value::Number(0.0));
509        assert_eq!(Value::Boolean(true), Value::Number(1.0));
510        assert_eq!(Value::Boolean(true), Value::Number(2.0));
511    }
512
513    #[test]
514    fn test_eq_array() {
515        assert_eq!(
516            Value::Array(vec![Value::Boolean(true), Value::Boolean(false)]),
517            Value::Array(vec![Value::Boolean(true), Value::Boolean(false)])
518        );
519
520        assert_ne!(
521            Value::Array(vec![Value::Boolean(true), Value::Boolean(false)]),
522            Value::Array(vec![Value::Boolean(true)])
523        );
524
525        assert_ne!(
526            Value::Array(vec![Value::Boolean(true), Value::Boolean(false)]),
527            Value::Array(vec![Value::Boolean(false), Value::Boolean(true)])
528        );
529
530        assert_eq!(
531            Value::Array(vec![Value::Boolean(true), Value::Boolean(false)]),
532            Value::Array(vec![Value::Number(3.0), Value::Number(0.0)])
533        );
534
535        assert_ne!(
536            Value::Array(vec![Value::Boolean(true), Value::Boolean(false)]),
537            Value::Array(vec![Value::Number(3.0), Value::Number(2.0)])
538        );
539    }
540
541    #[test]
542    fn test_eq_boolean_string() {
543        assert_eq!(Value::Boolean(false), Value::String(String::from("")));
544        assert_ne!(Value::Boolean(false), Value::String(String::from("abc")));
545
546        assert_eq!(Value::Boolean(true), Value::String(String::from("abc")));
547        assert_ne!(Value::Boolean(true), Value::String(String::from("")));
548    }
549}
550
551#[cfg(all(test, feature = "serde"))]
552mod test_serde_json {
553    use std::vec;
554
555    use serde_json::json;
556
557    use crate::value::Value;
558
559    #[test]
560    fn convert_from_json() {
561        assert!(serde_json::from_value::<Value>(json!(null)).is_err());
562
563        assert_eq!(
564            Value::Boolean(true),
565            serde_json::from_value(json!(true)).unwrap()
566        );
567        assert_eq!(
568            Value::String(String::from("ab")),
569            serde_json::from_value(json!("ab")).unwrap()
570        );
571        assert_eq!(
572            Value::Number(19.9),
573            serde_json::from_value(json!(19.9)).unwrap()
574        );
575        assert_eq!(
576            Value::Array(vec![Value::Boolean(true), Value::Boolean(false)]),
577            serde_json::from_value(json!(vec![true, false])).unwrap()
578        );
579    }
580
581    #[test]
582    fn convert_to_json() {
583        assert_eq!(json!(true), json!(Value::Boolean(true)));
584        assert_eq!(
585            json!(String::from("ab")),
586            json!(Value::String(String::from("ab")))
587        );
588        assert_eq!(json!(19.9), json!(Value::Number(19.9)));
589        assert_eq!(
590            json!(["hallo", 42.0, false]),
591            json!(Value::Array(vec![
592                Value::String(String::from("hallo")),
593                Value::Number(42.0),
594                Value::Boolean(false)
595            ]))
596        );
597    }
598}