rtlola_interpreter/storage/
value.rs

1use std::cmp::Ordering;
2use std::error::Error;
3use std::fmt::{Display, Formatter};
4use std::ops;
5use std::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
6
7use num::ToPrimitive;
8use num_traits::Pow;
9use ordered_float::NotNan;
10use rtlola_frontend::mir::Type;
11use rust_decimal::Decimal;
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14
15use self::Value::*;
16
17/**
18The general type for holding all kinds of values.
19*/
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21#[derive(Debug, PartialEq, Eq, Hash, Clone)]
22pub enum Value {
23    /**
24    Expresses the absence of a value.
25    */
26    None,
27    /**
28    A boolean value.
29    */
30    Bool(bool),
31    /**
32    An unsigned integer with 64 bits.
33    */
34    Unsigned(u64),
35    /**
36    A signed integer with 64 bits.
37    */
38    Signed(i64),
39    /**
40    A double-precision floating-point number that is not NaN.
41    */
42    Float(NotNan<f64>),
43    /**
44    A tuple of `Value`s.
45
46    The nested values can be of different type.
47    */
48    Tuple(Box<[Value]>),
49    /**
50    A string that must be utf-8 encoded.
51    */
52    Str(Box<str>),
53    /**
54    A slice of bytes.
55    */
56    Bytes(Box<[u8]>),
57    /**
58    A signed fixed-point number
59    */
60    Decimal(Decimal),
61}
62
63impl Display for Value {
64    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
65        match self {
66            None => write!(f, "None"),
67            Bool(b) => write!(f, "{}", *b),
68            Unsigned(u) => write!(f, "{}", *u),
69            Signed(s) => write!(f, "{}", *s),
70            Float(fl) => write!(f, "{}", *fl),
71            Tuple(t) => {
72                write!(f, "(")?;
73                if let Some(e) = t.first() {
74                    write!(f, "{}", e)?;
75                    for b in &t[1..] {
76                        write!(f, ", {}", b)?;
77                    }
78                }
79                write!(f, ")")
80            }
81            Str(str) => write!(f, "{}", *str),
82            Bytes(b) => {
83                let hex = hex::encode_upper(b);
84                write!(f, "{}", hex)
85            }
86            Decimal(i) => write!(f, "{i}"),
87        }
88    }
89}
90
91impl Value {
92    /// Returns the interpreted values of an byte representation, if possible:
93    /// # Arguments
94    /// * 'source' - A byte slice that holds the value
95    /// * 'ty' - the type of the interpretation
96    pub fn try_from_bytes(source: &[u8], ty: &Type) -> Result<Value, ValueConvertError> {
97        if let Ok(source) = std::str::from_utf8(source) {
98            if source == "#" {
99                return Ok(None);
100            }
101            match ty {
102                Type::Bool => source
103                    .parse::<bool>()
104                    .map(Bool)
105                    .map_err(|_| ValueConvertError::ParseError(ty.clone(), source.to_string())),
106                Type::Bytes => hex::decode(source)
107                    .map(|bytes| Bytes(bytes.into_boxed_slice()))
108                    .map_err(|_| ValueConvertError::ParseError(ty.clone(), source.to_string())),
109                Type::Int(_) => source
110                    .parse::<i64>()
111                    .map(Signed)
112                    .map_err(|_| ValueConvertError::ParseError(ty.clone(), source.to_string())),
113                Type::UInt(_) => {
114                    // TODO: This is just a quickfix!! Think of something more general.
115                    if source == "0.0" {
116                        Ok(Unsigned(0))
117                    } else {
118                        source.parse::<u64>().map(Unsigned).map_err(|_| {
119                            ValueConvertError::ParseError(ty.clone(), source.to_string())
120                        })
121                    }
122                }
123                Type::Float(_) => source
124                    .parse::<f64>()
125                    .map_err(|_| ValueConvertError::ParseError(ty.clone(), source.to_string()))
126                    .and_then(Value::try_from),
127                Type::String => Ok(Str(source.into())),
128                Type::Tuple(inner) => {
129                    if inner.is_empty() {
130                        (source == "()")
131                            .then_some(Tuple(Box::new([])))
132                            .ok_or_else(|| {
133                                ValueConvertError::ParseError(ty.clone(), source.to_string())
134                            })
135                    } else {
136                        unimplemented!()
137                    }
138                }
139
140                Type::Option(_) | Type::Function { args: _, ret: _ } => unreachable!(),
141                Type::Fixed(_) | Type::UFixed(_) => source
142                    .parse::<Decimal>()
143                    .map(Decimal)
144                    .map_err(|_| ValueConvertError::ParseError(ty.clone(), source.to_string())),
145            }
146        } else {
147            Err(ValueConvertError::NotUtf8(source.to_vec()))
148        }
149    }
150
151    /// Decides if a value is of type bool
152    pub(crate) fn is_bool(&self) -> bool {
153        matches!(self, Bool(_))
154    }
155
156    /// Returns the boolean value of a 'Bool' value type
157    pub(crate) fn as_bool(&self) -> bool {
158        if let Bool(b) = *self {
159            b
160        } else {
161            unreachable!()
162        }
163    }
164
165    /// Returns self if self is not `Value::None` and other otherwise
166    pub fn and_then(self, other: Value) -> Value {
167        match self {
168            None => other,
169            _ => self,
170        }
171    }
172
173    /// Returns the value for the given type.
174    pub fn from_int(ty: &Type, val: i64) -> Value {
175        match ty {
176            Type::Int(_) => Signed(val),
177            Type::UInt(_) => Unsigned(val as u64),
178            Type::Float(_) => Float(NotNan::new(val as f64).unwrap()),
179            Type::Fixed(_) | Type::UFixed(_) => Decimal(Decimal::from(val)),
180            _ => unreachable!("Incompatible Value Type."),
181        }
182    }
183
184    /// Returns the value in the same variant as self.
185    pub fn for_int(&self, val: i64) -> Value {
186        match self {
187            Signed(_) => Signed(val),
188            Unsigned(_) => Unsigned(val as u64),
189            Float(_) => Float(NotNan::new(val as f64).unwrap()),
190            Decimal(_) => Decimal(Decimal::from(val)),
191            _ => unreachable!("Incompatible Value Type."),
192        }
193    }
194}
195
196impl ops::Add for Value {
197    type Output = Value;
198
199    fn add(self, other: Value) -> Value {
200        match (self, other) {
201            (Unsigned(v1), Unsigned(v2)) => Unsigned(v1 + v2),
202            (Signed(v1), Signed(v2)) => Signed(v1 + v2),
203            (Float(v1), Float(v2)) => Float(v1 + v2),
204            (Decimal(v1), Decimal(v2)) => Decimal(v1 + v2),
205            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
206        }
207    }
208}
209
210impl AddAssign for Value {
211    fn add_assign(&mut self, rhs: Self) {
212        match (self, rhs) {
213            (Unsigned(v1), Unsigned(v2)) => v1.add_assign(v2),
214            (Signed(v1), Signed(v2)) => v1.add_assign(v2),
215            (Float(v1), Float(v2)) => v1.add_assign(v2),
216            (Decimal(v1), Decimal(v2)) => v1.add_assign(v2),
217            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
218        }
219    }
220}
221
222impl ops::Sub for Value {
223    type Output = Value;
224
225    fn sub(self, other: Value) -> Value {
226        match (self, other) {
227            (Unsigned(v1), Unsigned(v2)) => Unsigned(v1 - v2),
228            (Signed(v1), Signed(v2)) => Signed(v1 - v2),
229            (Float(v1), Float(v2)) => Float(v1 - v2),
230            (Decimal(v1), Decimal(v2)) => Decimal(v1 - v2),
231            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
232        }
233    }
234}
235
236impl SubAssign for Value {
237    fn sub_assign(&mut self, rhs: Self) {
238        match (self, rhs) {
239            (Unsigned(v1), Unsigned(v2)) => v1.sub_assign(v2),
240            (Signed(v1), Signed(v2)) => v1.sub_assign(v2),
241            (Float(v1), Float(v2)) => v1.sub_assign(v2),
242            (Decimal(v1), Decimal(v2)) => v1.sub_assign(v2),
243            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
244        }
245    }
246}
247
248impl ops::Mul for Value {
249    type Output = Value;
250
251    fn mul(self, other: Value) -> Value {
252        match (self, other) {
253            (Unsigned(v1), Unsigned(v2)) => Unsigned(v1 * v2),
254            (Signed(v1), Signed(v2)) => Signed(v1 * v2),
255            (Float(v1), Float(v2)) => Float(v1 * v2),
256            (Decimal(v1), Decimal(v2)) => Decimal(v1 * v2),
257            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
258        }
259    }
260}
261
262impl MulAssign for Value {
263    fn mul_assign(&mut self, rhs: Self) {
264        match (self, rhs) {
265            (Unsigned(v1), Unsigned(v2)) => v1.mul_assign(v2),
266            (Signed(v1), Signed(v2)) => v1.mul_assign(v2),
267            (Float(v1), Float(v2)) => v1.mul_assign(v2),
268            (Decimal(v1), Decimal(v2)) => v1.mul_assign(v2),
269            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
270        }
271    }
272}
273
274impl ops::Div for Value {
275    type Output = Value;
276
277    fn div(self, other: Value) -> Value {
278        match (self, other) {
279            (Unsigned(v1), Unsigned(v2)) => Unsigned(v1 / v2),
280            (Signed(v1), Signed(v2)) => Signed(v1 / v2),
281            (Float(v1), Float(v2)) => Float(v1 / v2),
282            (Decimal(v1), Decimal(v2)) => Decimal(v1 / v2),
283            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
284        }
285    }
286}
287
288impl DivAssign for Value {
289    fn div_assign(&mut self, rhs: Self) {
290        match (self, rhs) {
291            (Unsigned(v1), Unsigned(v2)) => v1.div_assign(v2),
292            (Signed(v1), Signed(v2)) => v1.div_assign(v2),
293            (Float(v1), Float(v2)) => v1.div_assign(v2),
294            (Decimal(v1), Decimal(v2)) => v1.div_assign(v2),
295            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
296        }
297    }
298}
299
300impl ops::Rem for Value {
301    type Output = Value;
302
303    fn rem(self, other: Value) -> Value {
304        match (self, other) {
305            (Unsigned(v1), Unsigned(v2)) => Unsigned(v1 % v2),
306            (Signed(v1), Signed(v2)) => Signed(v1 % v2),
307            (Float(v1), Float(v2)) => Float(v1 % v2),
308            (Decimal(v1), Decimal(v2)) => Decimal(v1 % v2),
309            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
310        }
311    }
312}
313
314impl RemAssign for Value {
315    fn rem_assign(&mut self, rhs: Self) {
316        match (self, rhs) {
317            (Unsigned(v1), Unsigned(v2)) => v1.rem_assign(v2),
318            (Signed(v1), Signed(v2)) => v1.rem_assign(v2),
319            (Float(v1), Float(v2)) => v1.rem_assign(v2),
320            (Decimal(v1), Decimal(v2)) => v1.rem_assign(v2),
321            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
322        }
323    }
324}
325
326impl Value {
327    /// Returns the powered value of a value type, with:
328    /// # Arguments:
329    /// * 'exp' - The exponent given as a 'Value'
330    pub(crate) fn pow(self, exp: Value) -> Value {
331        match (self, exp) {
332            (Unsigned(v1), Unsigned(v2)) => Unsigned(v1.pow(v2 as u32)),
333            (Signed(v1), Signed(v2)) => Signed(v1.pow(v2 as u32)),
334            (Float(v1), Float(v2)) => Value::try_from(v1.powf(v2.into())).unwrap(),
335            (Float(v1), Signed(v2)) => Value::try_from(v1.powi(v2 as i32)).unwrap(),
336            (Decimal(v1), Decimal(v2)) => Decimal(v1.pow(v2)),
337            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
338        }
339    }
340}
341
342impl ops::BitAnd for Value {
343    type Output = Value;
344
345    fn bitand(self, other: Value) -> Value {
346        match (self, other) {
347            (Bool(v1), Bool(v2)) => Bool(v1 && v2),
348            (Unsigned(u1), Unsigned(u2)) => Unsigned(u1 & u2),
349            (Signed(s1), Signed(s2)) => Signed(s1 & s2),
350            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
351        }
352    }
353}
354
355impl ops::BitOr for Value {
356    type Output = Value;
357
358    fn bitor(self, other: Value) -> Value {
359        match (self, other) {
360            (Bool(v1), Bool(v2)) => Bool(v1 || v2),
361            (Unsigned(u1), Unsigned(u2)) => Unsigned(u1 | u2),
362            (Signed(s1), Signed(s2)) => Signed(s1 | s2),
363            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
364        }
365    }
366}
367
368impl ops::BitXor for Value {
369    type Output = Value;
370
371    fn bitxor(self, other: Value) -> Value {
372        match (self, other) {
373            (Unsigned(u1), Unsigned(u2)) => Unsigned(u1 ^ u2),
374            (Signed(s1), Signed(s2)) => Signed(s1 ^ s2),
375            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
376        }
377    }
378}
379
380impl ops::Shl for Value {
381    type Output = Value;
382
383    fn shl(self, other: Value) -> Value {
384        match (self, other) {
385            (Unsigned(u1), Unsigned(u2)) => Unsigned(u1 << u2),
386            (Signed(s1), Unsigned(u)) => Signed(s1 << u),
387            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
388        }
389    }
390}
391
392impl ops::Shr for Value {
393    type Output = Value;
394
395    fn shr(self, other: Value) -> Value {
396        match (self, other) {
397            (Unsigned(u1), Unsigned(u2)) => Unsigned(u1 >> u2),
398            (Signed(s1), Unsigned(u)) => Signed(s1 >> u),
399            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
400        }
401    }
402}
403
404impl ops::Not for Value {
405    type Output = Value;
406
407    fn not(self) -> Value {
408        match self {
409            Bool(v) => Bool(!v),
410            Unsigned(u) => Unsigned(!u),
411            Signed(s) => Signed(!s),
412            a => panic!("Incompatible type: {:?}", a),
413        }
414    }
415}
416
417impl ops::Neg for Value {
418    type Output = Value;
419
420    fn neg(self) -> Value {
421        match self {
422            Signed(v) => Signed(-v), // TODO Check
423            Float(v) => Float(-v),
424            Decimal(v1) => Decimal(-v1),
425            a => panic!("Incompatible type: {:?}", a),
426        }
427    }
428}
429
430impl PartialOrd for Value {
431    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
432        Some(self.cmp(other))
433    }
434}
435
436impl Ord for Value {
437    fn cmp(&self, other: &Self) -> Ordering {
438        match (self, other) {
439            (Unsigned(u1), Unsigned(u2)) => u1.cmp(u2),
440            (Signed(i1), Signed(i2)) => i1.cmp(i2),
441            (Float(f1), Float(f2)) => f1.cmp(f2),
442            (Str(s1), Str(s2)) => s1.cmp(s2),
443            (Decimal(v1), Decimal(v2)) => v1.cmp(v2),
444            (a, b) => panic!("Incompatible types: ({:?},{:?})", a, b),
445        }
446    }
447}
448
449// Implement From for Value
450
451impl From<bool> for Value {
452    fn from(b: bool) -> Self {
453        Bool(b)
454    }
455}
456
457impl From<i16> for Value {
458    fn from(i: i16) -> Self {
459        Signed(i as i64)
460    }
461}
462
463impl From<i32> for Value {
464    fn from(i: i32) -> Self {
465        Signed(i as i64)
466    }
467}
468
469impl From<i64> for Value {
470    fn from(i: i64) -> Self {
471        Signed(i)
472    }
473}
474
475impl From<u16> for Value {
476    fn from(u: u16) -> Self {
477        Unsigned(u as u64)
478    }
479}
480
481impl From<u32> for Value {
482    fn from(u: u32) -> Self {
483        Unsigned(u as u64)
484    }
485}
486
487impl From<u64> for Value {
488    fn from(u: u64) -> Self {
489        Unsigned(u)
490    }
491}
492
493impl From<String> for Value {
494    fn from(value: String) -> Self {
495        Str(value.into_boxed_str())
496    }
497}
498
499impl From<&str> for Value {
500    fn from(value: &str) -> Self {
501        Value::from(value.to_string())
502    }
503}
504
505impl From<Vec<u8>> for Value {
506    fn from(value: Vec<u8>) -> Self {
507        Bytes(value.into_boxed_slice())
508    }
509}
510
511impl From<&[u8]> for Value {
512    fn from(value: &[u8]) -> Self {
513        Value::from(value.to_vec())
514    }
515}
516
517impl TryFrom<f64> for Value {
518    type Error = ValueConvertError;
519
520    fn try_from(value: f64) -> Result<Self, Self::Error> {
521        let val = NotNan::try_from(value).map_err(|_| ValueConvertError::FloatIsNan)?;
522        Ok(Float(val))
523    }
524}
525
526impl TryFrom<f32> for Value {
527    type Error = ValueConvertError;
528
529    fn try_from(value: f32) -> Result<Self, Self::Error> {
530        let val = NotNan::try_from(value as f64).map_err(|_| ValueConvertError::FloatIsNan)?;
531        Ok(Float(val))
532    }
533}
534
535impl From<Decimal> for Value {
536    fn from(value: Decimal) -> Self {
537        Self::Decimal(value)
538    }
539}
540
541impl From<usize> for Value {
542    fn from(value: usize) -> Self {
543        Unsigned(value as u64)
544    }
545}
546
547impl<T: Into<Value>> From<Option<T>> for Value {
548    fn from(value: Option<T>) -> Self {
549        value.map(T::into).unwrap_or(None)
550    }
551}
552
553impl TryInto<bool> for Value {
554    type Error = ValueConvertError;
555
556    fn try_into(self) -> Result<bool, Self::Error> {
557        if let Bool(b) = self {
558            Ok(b)
559        } else {
560            Err(ValueConvertError::TypeMismatch(self))
561        }
562    }
563}
564
565impl TryInto<u64> for Value {
566    type Error = ValueConvertError;
567
568    fn try_into(self) -> Result<u64, Self::Error> {
569        if let Unsigned(v) = self {
570            Ok(v)
571        } else {
572            Err(ValueConvertError::TypeMismatch(self))
573        }
574    }
575}
576
577impl TryInto<i64> for Value {
578    type Error = ValueConvertError;
579
580    fn try_into(self) -> Result<i64, Self::Error> {
581        if let Signed(v) = self {
582            Ok(v)
583        } else {
584            Err(ValueConvertError::TypeMismatch(self))
585        }
586    }
587}
588
589impl TryInto<f64> for Value {
590    type Error = ValueConvertError;
591
592    fn try_into(self) -> Result<f64, Self::Error> {
593        if let Float(v) = self {
594            Ok(v.into_inner())
595        } else {
596            Err(ValueConvertError::TypeMismatch(self))
597        }
598    }
599}
600
601impl TryInto<Box<[Value]>> for Value {
602    type Error = ValueConvertError;
603
604    fn try_into(self) -> Result<Box<[Value]>, Self::Error> {
605        if let Tuple(v) = self {
606            Ok(v)
607        } else {
608            Err(ValueConvertError::TypeMismatch(self))
609        }
610    }
611}
612
613impl TryInto<Vec<Value>> for Value {
614    type Error = ValueConvertError;
615
616    fn try_into(self) -> Result<Vec<Value>, Self::Error> {
617        if let Tuple(v) = self {
618            Ok(v.to_vec())
619        } else {
620            Err(ValueConvertError::TypeMismatch(self))
621        }
622    }
623}
624
625impl TryInto<Box<str>> for Value {
626    type Error = ValueConvertError;
627
628    fn try_into(self) -> Result<Box<str>, Self::Error> {
629        if let Str(v) = self {
630            Ok(v)
631        } else {
632            Err(ValueConvertError::TypeMismatch(self))
633        }
634    }
635}
636
637impl TryInto<String> for Value {
638    type Error = ValueConvertError;
639
640    fn try_into(self) -> Result<String, Self::Error> {
641        if let Str(v) = self {
642            Ok(v.to_string())
643        } else {
644            Err(ValueConvertError::TypeMismatch(self))
645        }
646    }
647}
648
649impl TryInto<Box<[u8]>> for Value {
650    type Error = ValueConvertError;
651
652    fn try_into(self) -> Result<Box<[u8]>, Self::Error> {
653        if let Bytes(v) = self {
654            Ok(v)
655        } else {
656            Err(ValueConvertError::TypeMismatch(self))
657        }
658    }
659}
660
661impl TryInto<Vec<u8>> for Value {
662    type Error = ValueConvertError;
663
664    fn try_into(self) -> Result<Vec<u8>, Self::Error> {
665        if let Bytes(v) = self {
666            Ok(v.to_vec())
667        } else {
668            Err(ValueConvertError::TypeMismatch(self))
669        }
670    }
671}
672
673impl TryInto<Decimal> for Value {
674    type Error = ValueConvertError;
675
676    fn try_into(self) -> Result<Decimal, Self::Error> {
677        match self {
678            Unsigned(v) => Ok(v.into()),
679            Signed(v) => Ok(v.into()),
680            Float(v) => Ok(v.to_f64().unwrap().try_into().unwrap()),
681            Decimal(v) => Ok(v),
682            _ => Err(ValueConvertError::ValueNotSupported(Box::new(self))),
683        }
684    }
685}
686
687#[derive(Debug)]
688/// Describes an error occurring when converting from or into a value.
689pub enum ValueConvertError {
690    /// The target type could not be created from the given value.
691    TypeMismatch(Value),
692    /// Given bytes are expected to be utf-8 coded.
693    NotUtf8(Vec<u8>),
694    /// Could not parse value given as string into type.
695    ParseError(Type, String),
696    /// The given value is not supported by the interpreter.
697    ValueNotSupported(Box<dyn std::fmt::Debug + Send>),
698    /// The given float is NaN.
699    FloatIsNan,
700}
701
702impl Display for ValueConvertError {
703    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
704        match self {
705            ValueConvertError::TypeMismatch(val) => write!(f, "Failed to convert Value: {val}"),
706            ValueConvertError::NotUtf8(bytes) => {
707                write!(f, "UTF-8 decoding failed for bytes: {bytes:?}")
708            }
709            ValueConvertError::ParseError(ty, val) => {
710                write!(f, "Failed to parse Value of type {ty} from: {val}")
711            }
712            ValueConvertError::FloatIsNan => write!(f, "The given Float is not a number (NaN)"),
713            ValueConvertError::ValueNotSupported(v) => {
714                write!(f, "The value {v:?} is not supported by the interpreter.")
715            }
716        }
717    }
718}
719
720impl Error for ValueConvertError {}
721
722#[cfg(test)]
723mod tests {
724
725    use std::mem::size_of;
726
727    use super::*;
728
729    #[test]
730    fn size_of_value() {
731        let result = size_of::<Value>();
732        let expected = 24;
733        assert!(
734            result == expected,
735            "Size of `Value` should be {} bytes, was `{}`",
736            expected,
737            result
738        );
739    }
740}