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#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21#[derive(Debug, PartialEq, Eq, Hash, Clone)]
22pub enum Value {
23 None,
27 Bool(bool),
31 Unsigned(u64),
35 Signed(i64),
39 Float(NotNan<f64>),
43 Tuple(Box<[Value]>),
49 Str(Box<str>),
53 Bytes(Box<[u8]>),
57 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 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 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 pub(crate) fn is_bool(&self) -> bool {
153 matches!(self, Bool(_))
154 }
155
156 pub(crate) fn as_bool(&self) -> bool {
158 if let Bool(b) = *self {
159 b
160 } else {
161 unreachable!()
162 }
163 }
164
165 pub fn and_then(self, other: Value) -> Value {
167 match self {
168 None => other,
169 _ => self,
170 }
171 }
172
173 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 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 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), 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
449impl 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)]
688pub enum ValueConvertError {
690 TypeMismatch(Value),
692 NotUtf8(Vec<u8>),
694 ParseError(Type, String),
696 ValueNotSupported(Box<dyn std::fmt::Debug + Send>),
698 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}