datex_core/values/
core_value.rs

1use datex_macros::FromCoreValue;
2
3use crate::values::core_values::array::Array;
4use crate::values::core_values::boolean::Boolean;
5use crate::values::core_values::decimal::decimal::Decimal;
6use crate::values::core_values::decimal::typed_decimal::TypedDecimal;
7use crate::values::core_values::endpoint::Endpoint;
8use crate::values::core_values::integer::integer::Integer;
9use crate::values::core_values::integer::typed_integer::TypedInteger;
10use crate::values::core_values::object::Object;
11use crate::values::core_values::text::Text;
12use crate::values::core_values::tuple::Tuple;
13use crate::values::datex_type::CoreValueType;
14use crate::values::traits::structural_eq::StructuralEq;
15use crate::values::traits::value_eq::ValueEq;
16use crate::values::value_container::{ValueContainer, ValueError};
17use std::fmt::{Display, Formatter};
18use std::ops::{Add, AddAssign, Not, Sub};
19
20#[derive(Clone, Debug, PartialEq, Eq, Hash, FromCoreValue)]
21pub enum CoreValue {
22    Null,
23    Bool(Boolean),
24    Integer(Integer),
25    TypedInteger(TypedInteger),
26    Decimal(Decimal),
27    TypedDecimal(TypedDecimal),
28    Text(Text),
29    Endpoint(Endpoint),
30    Array(Array),
31    Object(Object),
32    Tuple(Tuple),
33}
34impl StructuralEq for CoreValue {
35    fn structural_eq(&self, other: &Self) -> bool {
36        match (self, other) {
37            (CoreValue::Bool(a), CoreValue::Bool(b)) => a.structural_eq(b),
38
39            // Integers + TypedIntegers
40            (
41                CoreValue::Integer(Integer(a)) | CoreValue::TypedInteger(a),
42                CoreValue::Integer(Integer(b)) | CoreValue::TypedInteger(b),
43            ) => a.structural_eq(b),
44
45            // Decimals
46            (CoreValue::Decimal(a), CoreValue::Decimal(b)) => {
47                a.structural_eq(b)
48            }
49
50            // TypedDecimals
51            (CoreValue::TypedDecimal(a), CoreValue::TypedDecimal(b)) => {
52                a.structural_eq(b)
53            }
54
55            // Decimal + TypedDecimal
56            (CoreValue::Decimal(a), CoreValue::TypedDecimal(b))
57            | (CoreValue::TypedDecimal(b), CoreValue::Decimal(a)) => {
58                TypedDecimal::Decimal(a.clone()).structural_eq(b)
59            }
60
61            (CoreValue::Text(a), CoreValue::Text(b)) => a.structural_eq(b),
62            (CoreValue::Null, CoreValue::Null) => true,
63            (CoreValue::Endpoint(a), CoreValue::Endpoint(b)) => {
64                a.structural_eq(b)
65            }
66            (CoreValue::Array(a), CoreValue::Array(b)) => a.structural_eq(b),
67            (CoreValue::Object(a), CoreValue::Object(b)) => a.structural_eq(b),
68            (CoreValue::Tuple(a), CoreValue::Tuple(b)) => a.structural_eq(b),
69
70            _ => false,
71        }
72    }
73}
74
75/// value equality corresponds to partial equality for values
76impl ValueEq for CoreValue {
77    fn value_eq(&self, other: &Self) -> bool {
78        self == other
79    }
80}
81
82impl From<&str> for CoreValue {
83    fn from(value: &str) -> Self {
84        CoreValue::Text(value.into())
85    }
86}
87impl From<String> for CoreValue {
88    fn from(value: String) -> Self {
89        CoreValue::Text(Text(value))
90    }
91}
92
93impl<T> From<Vec<T>> for CoreValue
94where
95    T: Into<ValueContainer>,
96{
97    fn from(vec: Vec<T>) -> Self {
98        CoreValue::Array(vec.into())
99    }
100}
101
102impl<T> FromIterator<T> for CoreValue
103where
104    T: Into<ValueContainer>,
105{
106    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
107        CoreValue::Array(Array(iter.into_iter().map(Into::into).collect()))
108    }
109}
110
111impl From<bool> for CoreValue {
112    fn from(value: bool) -> Self {
113        CoreValue::Bool(value.into())
114    }
115}
116
117impl From<i8> for CoreValue {
118    fn from(value: i8) -> Self {
119        CoreValue::TypedInteger(value.into())
120    }
121}
122impl From<i16> for CoreValue {
123    fn from(value: i16) -> Self {
124        CoreValue::TypedInteger(value.into())
125    }
126}
127impl From<i32> for CoreValue {
128    fn from(value: i32) -> Self {
129        CoreValue::TypedInteger(value.into())
130    }
131}
132impl From<i64> for CoreValue {
133    fn from(value: i64) -> Self {
134        CoreValue::TypedInteger(value.into())
135    }
136}
137impl From<i128> for CoreValue {
138    fn from(value: i128) -> Self {
139        CoreValue::TypedInteger(value.into())
140    }
141}
142
143impl From<u8> for CoreValue {
144    fn from(value: u8) -> Self {
145        CoreValue::TypedInteger(value.into())
146    }
147}
148impl From<u16> for CoreValue {
149    fn from(value: u16) -> Self {
150        CoreValue::TypedInteger(value.into())
151    }
152}
153impl From<u32> for CoreValue {
154    fn from(value: u32) -> Self {
155        CoreValue::TypedInteger(value.into())
156    }
157}
158impl From<u64> for CoreValue {
159    fn from(value: u64) -> Self {
160        CoreValue::TypedInteger(value.into())
161    }
162}
163impl From<u128> for CoreValue {
164    fn from(value: u128) -> Self {
165        CoreValue::TypedInteger(value.into())
166    }
167}
168
169impl From<f32> for CoreValue {
170    fn from(value: f32) -> Self {
171        CoreValue::TypedDecimal(value.into())
172    }
173}
174impl From<f64> for CoreValue {
175    fn from(value: f64) -> Self {
176        CoreValue::TypedDecimal(value.into())
177    }
178}
179
180impl CoreValue {
181    pub fn new<T>(value: T) -> CoreValue
182    where
183        CoreValue: From<T>,
184    {
185        value.into()
186    }
187
188    pub fn get_default_type(&self) -> CoreValueType {
189        match self {
190            CoreValue::Bool(_) => CoreValueType::Bool,
191            CoreValue::TypedInteger(int) => match int {
192                TypedInteger::I8(_) => CoreValueType::I8,
193                TypedInteger::I16(_) => CoreValueType::I16,
194                TypedInteger::I32(_) => CoreValueType::I32,
195                TypedInteger::I64(_) => CoreValueType::I64,
196                TypedInteger::I128(_) => CoreValueType::I128,
197
198                TypedInteger::U8(_) => CoreValueType::U8,
199                TypedInteger::U16(_) => CoreValueType::U16,
200                TypedInteger::U32(_) => CoreValueType::U32,
201                TypedInteger::U64(_) => CoreValueType::U64,
202                TypedInteger::U128(_) => CoreValueType::U128,
203            },
204            CoreValue::TypedDecimal(decimal) => match decimal {
205                TypedDecimal::F32(_) => CoreValueType::F32,
206                TypedDecimal::F64(_) => CoreValueType::F64,
207                TypedDecimal::Decimal(_) => CoreValueType::Decimal,
208            },
209            CoreValue::Text(_) => CoreValueType::Text,
210            CoreValue::Null => CoreValueType::Null,
211            CoreValue::Endpoint(_) => CoreValueType::Endpoint,
212            CoreValue::Array(_) => CoreValueType::Array,
213            CoreValue::Object(_) => CoreValueType::Object,
214            CoreValue::Tuple(_) => CoreValueType::Tuple,
215            CoreValue::Integer(_) => CoreValueType::Integer,
216            CoreValue::Decimal(_) => CoreValueType::Decimal,
217        }
218    }
219
220    pub fn cast_to(&self, target_type: CoreValueType) -> Option<CoreValue> {
221        match target_type {
222            CoreValueType::Bool => Some(CoreValue::Bool(self.cast_to_bool()?)),
223            CoreValueType::I8
224            | CoreValueType::I16
225            | CoreValueType::I32
226            | CoreValueType::I64
227            | CoreValueType::I128
228            | CoreValueType::U8
229            | CoreValueType::U16
230            | CoreValueType::U32
231            | CoreValueType::U64
232            | CoreValueType::U128 => {
233                Some(CoreValue::TypedInteger(self.cast_to_integer()?))
234            }
235            CoreValueType::F32 | CoreValueType::F64 => {
236                Some(CoreValue::TypedDecimal(self.cast_to_float()?))
237            }
238            CoreValueType::Text => Some(CoreValue::Text(self.cast_to_text())),
239            CoreValueType::Null => Some(CoreValue::Null),
240            CoreValueType::Endpoint => {
241                Some(CoreValue::Endpoint(self.cast_to_endpoint()?))
242            }
243            CoreValueType::Array => {
244                Some(CoreValue::Array(self.cast_to_array()?))
245            }
246            CoreValueType::Object => {
247                Some(CoreValue::Object(self.cast_to_object()?))
248            }
249            CoreValueType::Tuple => {
250                Some(CoreValue::Tuple(self.cast_to_tuple()?))
251            }
252            CoreValueType::Integer => {
253                Some(CoreValue::Integer(self.cast_to_integer()?.into()))
254            }
255            CoreValueType::Decimal => Some(CoreValue::Decimal(
256                Decimal::from_string(self.cast_to_text().as_str()),
257            )),
258            _ => todo!("#116 Undescribed by author."),
259        }
260    }
261
262    pub fn cast_to_text(&self) -> Text {
263        match self {
264            CoreValue::Text(text) => text.clone(),
265            _ => Text(self.to_string()),
266        }
267    }
268
269    pub fn cast_to_bool(&self) -> Option<Boolean> {
270        match self {
271            CoreValue::Text(text) => Some(Boolean(!text.0.is_empty())),
272            CoreValue::Bool(bool) => Some(bool.clone()),
273            CoreValue::TypedInteger(int) => Some(Boolean(int.as_i128()? != 0)),
274            CoreValue::Null => Some(Boolean(false)),
275            _ => None,
276        }
277    }
278
279    pub fn cast_to_float(&self) -> Option<TypedDecimal> {
280        match self {
281            CoreValue::Text(text) => {
282                text.to_string().parse::<f64>().ok().map(TypedDecimal::from)
283            }
284            CoreValue::TypedInteger(int) => {
285                Some(TypedDecimal::from(int.as_i128()? as f64))
286            }
287            CoreValue::TypedDecimal(decimal) => Some(decimal.clone()),
288            _ => None,
289        }
290    }
291
292    pub fn cast_to_integer(&self) -> Option<TypedInteger> {
293        match self {
294            CoreValue::Text(text) => text
295                .to_string()
296                .parse::<i128>()
297                .ok()
298                .map(TypedInteger::from),
299            CoreValue::TypedInteger(int) => Some(*int),
300            CoreValue::Integer(Integer(int)) => Some(*int),
301            CoreValue::Decimal(decimal) => {
302                Some(TypedInteger::from(decimal.try_into_f64()? as i128)) // TODO #117: handle bigints once implemented
303            }
304            CoreValue::TypedDecimal(decimal) => {
305                Some(TypedInteger::from(decimal.as_f64() as i64))
306            }
307            _ => None,
308        }
309    }
310
311    pub fn cast_to_endpoint(&self) -> Option<Endpoint> {
312        match self {
313            CoreValue::Text(text) => Endpoint::try_from(text.as_str()).ok(),
314            CoreValue::Endpoint(endpoint) => Some(endpoint.clone()),
315            _ => None,
316        }
317    }
318
319    pub fn cast_to_array(&self) -> Option<Array> {
320        match self {
321            CoreValue::Array(array) => Some(array.clone()),
322            _ => None,
323        }
324    }
325
326    pub fn cast_to_object(&self) -> Option<Object> {
327        match self {
328            CoreValue::Tuple(tuple) => {
329                Some(Object::from(tuple.entries.clone()))
330            }
331            CoreValue::Object(object) => Some(object.clone()),
332            _ => None,
333        }
334    }
335
336    pub fn cast_to_tuple(&self) -> Option<Tuple> {
337        match self {
338            CoreValue::Object(object) => Some(Tuple::from(object.0.clone())),
339            CoreValue::Tuple(tuple) => Some(tuple.clone()),
340            _ => None,
341        }
342    }
343}
344
345impl Add for CoreValue {
346    type Output = Result<CoreValue, ValueError>;
347    fn add(self, rhs: CoreValue) -> Self::Output {
348        match (&self, &rhs) {
349            // x + text or text + x (order does not matter)
350            (CoreValue::Text(text), other) => {
351                let other = other.cast_to_text();
352                return Ok(CoreValue::Text(text + other));
353            }
354            (other, CoreValue::Text(text)) => {
355                let other = other.cast_to_text();
356                return Ok(CoreValue::Text(other + text));
357            }
358
359            // same type additions
360            (CoreValue::TypedInteger(lhs), CoreValue::TypedInteger(rhs)) => {
361                return Ok(CoreValue::TypedInteger(
362                    (lhs + rhs).ok_or(ValueError::IntegerOverflow)?,
363                ));
364            }
365            (CoreValue::Integer(lhs), CoreValue::Integer(rhs)) => {
366                return Ok(CoreValue::Integer(
367                    (lhs + rhs).ok_or(ValueError::IntegerOverflow)?,
368                ));
369            }
370            (CoreValue::TypedDecimal(lhs), CoreValue::TypedDecimal(rhs)) => {
371                return Ok(CoreValue::TypedDecimal(lhs + rhs));
372            }
373            (CoreValue::Decimal(lhs), CoreValue::Decimal(rhs)) => {
374                return Ok(CoreValue::Decimal(lhs + rhs));
375            }
376
377            _ => {}
378        }
379
380        // other cases
381        match &self {
382            // integer
383            CoreValue::Integer(lhs) => match &rhs {
384                CoreValue::TypedInteger(rhs) => {
385                    Ok(CoreValue::Integer(Integer::from(
386                        (&lhs.0 + rhs).ok_or(ValueError::IntegerOverflow)?,
387                    )))
388                }
389                CoreValue::Decimal(_) => {
390                    let integer = rhs
391                        .cast_to_integer()
392                        .ok_or(ValueError::InvalidOperation)?;
393                    Ok(CoreValue::Integer(Integer::from(
394                        (lhs.0 + integer).ok_or(ValueError::IntegerOverflow)?,
395                    )))
396                }
397                CoreValue::TypedDecimal(rhs) => {
398                    let decimal = rhs.as_f64();
399                    let integer = TypedInteger::from(decimal as i128);
400                    Ok(CoreValue::Integer(Integer::from(
401                        (lhs.0 + integer).ok_or(ValueError::IntegerOverflow)?,
402                    )))
403                }
404                _ => Err(ValueError::InvalidOperation),
405            },
406
407            // typed integer
408            CoreValue::TypedInteger(lhs) => match &rhs {
409                CoreValue::Integer(rhs) => Ok(CoreValue::TypedInteger(
410                    (lhs + &rhs.0).ok_or(ValueError::IntegerOverflow)?,
411                )),
412                CoreValue::Decimal(_) => {
413                    let integer = rhs
414                        .cast_to_integer()
415                        .ok_or(ValueError::InvalidOperation)?;
416                    Ok(CoreValue::TypedInteger(
417                        (lhs + &integer).ok_or(ValueError::IntegerOverflow)?,
418                    ))
419                }
420                CoreValue::TypedDecimal(rhs) => {
421                    let decimal = rhs.as_f64();
422                    let integer = TypedInteger::from(decimal as i128);
423                    Ok(CoreValue::TypedInteger(
424                        (lhs + &integer).ok_or(ValueError::IntegerOverflow)?,
425                    ))
426                }
427                _ => Err(ValueError::InvalidOperation),
428            },
429
430            // decimal
431            CoreValue::Decimal(lhs) => match rhs {
432                CoreValue::TypedDecimal(rhs) => {
433                    Ok(CoreValue::Decimal(lhs + &Decimal::from(rhs)))
434                }
435                CoreValue::TypedInteger(rhs) => {
436                    let decimal = Decimal::from(
437                        rhs.as_i128().ok_or(ValueError::IntegerOverflow)?
438                            as f64,
439                    );
440                    Ok(CoreValue::Decimal(lhs + &decimal))
441                }
442                CoreValue::Integer(rhs) => {
443                    let decimal = Decimal::from(
444                        rhs.0.as_i128().ok_or(ValueError::IntegerOverflow)?
445                            as f64,
446                    );
447                    Ok(CoreValue::Decimal(lhs + &decimal))
448                }
449                _ => Err(ValueError::InvalidOperation),
450            },
451
452            // typed decimal
453            CoreValue::TypedDecimal(lhs) => match rhs {
454                CoreValue::Decimal(rhs) => Ok(CoreValue::TypedDecimal(
455                    lhs + &TypedDecimal::Decimal(rhs),
456                )),
457                CoreValue::TypedInteger(rhs) => {
458                    let decimal = TypedDecimal::from(
459                        rhs.as_i128().ok_or(ValueError::IntegerOverflow)?
460                            as f64,
461                    );
462                    Ok(CoreValue::TypedDecimal(lhs + &decimal))
463                }
464                CoreValue::Integer(rhs) => {
465                    let decimal = TypedDecimal::from(
466                        rhs.0.as_i128().ok_or(ValueError::IntegerOverflow)?
467                            as f64,
468                    );
469                    Ok(CoreValue::TypedDecimal(lhs + &decimal))
470                }
471                _ => Err(ValueError::InvalidOperation),
472            },
473
474            _ => Err(ValueError::InvalidOperation),
475        }
476    }
477}
478
479impl Add for &CoreValue {
480    type Output = Result<CoreValue, ValueError>;
481    fn add(self, rhs: &CoreValue) -> Self::Output {
482        CoreValue::add(self.clone(), rhs.clone())
483    }
484}
485
486impl Sub for CoreValue {
487    type Output = Result<CoreValue, ValueError>;
488    fn sub(self, rhs: CoreValue) -> Self::Output {
489        // same type subtractions
490        match (&self, &rhs) {
491            (CoreValue::TypedInteger(lhs), CoreValue::TypedInteger(rhs)) => {
492                return Ok(CoreValue::TypedInteger(
493                    (lhs - rhs).ok_or(ValueError::IntegerOverflow)?,
494                ));
495            }
496            (CoreValue::Integer(lhs), CoreValue::Integer(rhs)) => {
497                return Ok(CoreValue::Integer(
498                    (lhs - rhs).ok_or(ValueError::IntegerOverflow)?,
499                ));
500            }
501            (CoreValue::TypedDecimal(lhs), CoreValue::TypedDecimal(rhs)) => {
502                return Ok(CoreValue::TypedDecimal(lhs - rhs));
503            }
504            (CoreValue::Decimal(lhs), CoreValue::Decimal(rhs)) => {
505                return Ok(CoreValue::Decimal(lhs - rhs));
506            }
507
508            _ => {}
509        }
510
511        // other cases
512        match &self {
513            // integer
514            CoreValue::Integer(lhs) => match &rhs {
515                CoreValue::TypedInteger(rhs) => {
516                    Ok(CoreValue::Integer(Integer::from(
517                        (&lhs.0 - rhs).ok_or(ValueError::IntegerOverflow)?,
518                    )))
519                }
520                CoreValue::Decimal(_) => {
521                    let integer = rhs
522                        .cast_to_integer()
523                        .ok_or(ValueError::InvalidOperation)?;
524                    Ok(CoreValue::Integer(Integer::from(
525                        (lhs.0 - integer).ok_or(ValueError::IntegerOverflow)?,
526                    )))
527                }
528                CoreValue::TypedDecimal(rhs) => {
529                    let decimal = rhs.as_f64();
530                    let integer = TypedInteger::from(decimal as i128);
531                    Ok(CoreValue::Integer(Integer::from(
532                        (lhs.0 - integer).ok_or(ValueError::IntegerOverflow)?,
533                    )))
534                }
535                _ => Err(ValueError::InvalidOperation),
536            },
537
538            // typed integer
539            CoreValue::TypedInteger(lhs) => match &rhs {
540                CoreValue::Integer(rhs) => Ok(CoreValue::TypedInteger(
541                    (lhs - &rhs.0).ok_or(ValueError::IntegerOverflow)?,
542                )),
543                CoreValue::Decimal(_) => {
544                    let integer = rhs
545                        .cast_to_integer()
546                        .ok_or(ValueError::InvalidOperation)?;
547                    Ok(CoreValue::TypedInteger(
548                        (lhs - &integer).ok_or(ValueError::IntegerOverflow)?,
549                    ))
550                }
551                CoreValue::TypedDecimal(rhs) => {
552                    let decimal = rhs.as_f64();
553                    let integer = TypedInteger::from(decimal as i128);
554                    Ok(CoreValue::TypedInteger(
555                        (lhs - &integer).ok_or(ValueError::IntegerOverflow)?,
556                    ))
557                }
558                _ => Err(ValueError::InvalidOperation),
559            },
560
561            // decimal
562            CoreValue::Decimal(lhs) => match rhs {
563                CoreValue::TypedDecimal(rhs) => {
564                    Ok(CoreValue::Decimal(lhs - &Decimal::from(rhs)))
565                }
566                CoreValue::TypedInteger(rhs) => {
567                    let decimal = Decimal::from(
568                        rhs.as_i128().ok_or(ValueError::IntegerOverflow)?
569                            as f64,
570                    );
571                    Ok(CoreValue::Decimal(lhs - &decimal))
572                }
573                CoreValue::Integer(rhs) => {
574                    let decimal = Decimal::from(
575                        rhs.0.as_i128().ok_or(ValueError::IntegerOverflow)?
576                            as f64,
577                    );
578                    Ok(CoreValue::Decimal(lhs - &decimal))
579                }
580                _ => Err(ValueError::InvalidOperation),
581            },
582
583            // typed decimal
584            CoreValue::TypedDecimal(lhs) => match rhs {
585                CoreValue::Decimal(rhs) => Ok(CoreValue::TypedDecimal(
586                    lhs - &TypedDecimal::Decimal(rhs),
587                )),
588                CoreValue::TypedInteger(rhs) => {
589                    let decimal = TypedDecimal::from(
590                        rhs.as_i128().ok_or(ValueError::IntegerOverflow)?
591                            as f64,
592                    );
593                    Ok(CoreValue::TypedDecimal(lhs - &decimal))
594                }
595                CoreValue::Integer(rhs) => {
596                    let decimal = TypedDecimal::from(
597                        rhs.0.as_i128().ok_or(ValueError::IntegerOverflow)?
598                            as f64,
599                    );
600                    Ok(CoreValue::TypedDecimal(lhs - &decimal))
601                }
602                _ => Err(ValueError::InvalidOperation),
603            },
604            _ => Err(ValueError::InvalidOperation),
605        }
606    }
607}
608
609impl Sub for &CoreValue {
610    type Output = Result<CoreValue, ValueError>;
611    fn sub(self, rhs: &CoreValue) -> Self::Output {
612        CoreValue::sub(self.clone(), rhs.clone())
613    }
614}
615
616impl AddAssign<CoreValue> for CoreValue {
617    fn add_assign(&mut self, rhs: CoreValue) {
618        let res = self.clone() + rhs;
619        if let Ok(value) = res {
620            *self = value;
621        } else {
622            panic!("Failed to add value: {res:?}");
623        }
624    }
625}
626
627impl Not for CoreValue {
628    type Output = Option<CoreValue>;
629
630    fn not(self) -> Self::Output {
631        match self {
632            CoreValue::Bool(bool) => Some(CoreValue::Bool(!bool)),
633            _ => None, // Not applicable for other types
634        }
635    }
636}
637
638impl Display for CoreValue {
639    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
640        match self {
641            CoreValue::Bool(bool) => write!(f, "{bool}"),
642            CoreValue::TypedInteger(int) => write!(f, "{int}"),
643            CoreValue::TypedDecimal(decimal) => write!(f, "{decimal}"),
644            CoreValue::Text(text) => write!(f, "{text}"),
645            CoreValue::Null => write!(f, "null"),
646            CoreValue::Endpoint(endpoint) => write!(f, "{endpoint}"),
647            CoreValue::Array(array) => write!(f, "{array}"),
648            CoreValue::Object(object) => write!(f, "{object}"),
649            CoreValue::Tuple(tuple) => write!(f, "{tuple}"),
650            CoreValue::Integer(integer) => write!(f, "{integer}"),
651            CoreValue::Decimal(decimal) => write!(f, "{decimal}"),
652        }
653    }
654}
655
656#[cfg(test)]
657/// This module contains tests for the CoreValue struct.
658/// Each CoreValue is a representation of a underlying native value.
659/// The tests cover addition, casting, and type conversions.
660mod tests {
661    use log::{debug, info};
662
663    use crate::logger::init_logger_debug;
664
665    use super::*;
666
667    #[test]
668    fn test_addition() {
669        init_logger_debug();
670        let a = CoreValue::from(42i32);
671        let b = CoreValue::from(11i32);
672        let c = CoreValue::from("11");
673
674        assert_eq!(a.get_default_type(), CoreValueType::I32);
675        assert_eq!(b.get_default_type(), CoreValueType::I32);
676        assert_eq!(c.get_default_type(), CoreValueType::Text);
677
678        let a_plus_b = (a.clone() + b.clone()).unwrap();
679        assert_eq!(a_plus_b.clone().get_default_type(), CoreValueType::I32);
680        assert_eq!(a_plus_b.clone(), CoreValue::from(53));
681        info!("{} + {} = {}", a.clone(), b.clone(), a_plus_b.clone());
682    }
683
684    #[test]
685    fn test_endpoint() {
686        let endpoint: Endpoint = CoreValue::from("@test").try_into().unwrap();
687        debug!("Endpoint: {endpoint}");
688        assert_eq!(endpoint.to_string(), "@test");
689    }
690
691    #[test]
692    fn test_integer_decimal_casting() {
693        let int_value = CoreValue::from(42);
694        assert_eq!(
695            int_value.cast_to(CoreValueType::Decimal).unwrap(),
696            CoreValue::from(Decimal::from(42.0))
697        );
698
699        let decimal_value = CoreValue::from(Decimal::from(42.7));
700        assert_eq!(
701            decimal_value.cast_to(CoreValueType::Integer).unwrap(),
702            CoreValue::from(Integer::from(42))
703        );
704    }
705
706    #[test]
707    fn test_boolean_casting() {
708        let bool_value = CoreValue::from(true);
709        assert_eq!(
710            bool_value.cast_to(CoreValueType::Bool).unwrap(),
711            CoreValue::from(true)
712        );
713
714        let int_value = CoreValue::from(1);
715        assert_eq!(
716            int_value.cast_to(CoreValueType::Bool).unwrap(),
717            CoreValue::from(true)
718        );
719
720        let zero_int_value = CoreValue::from(0);
721        assert_eq!(
722            zero_int_value.cast_to(CoreValueType::Bool).unwrap(),
723            CoreValue::from(false)
724        );
725
726        let invalid_text_value = CoreValue::from("sometext");
727        assert_eq!(
728            invalid_text_value.cast_to(CoreValueType::Bool),
729            Some(CoreValue::from(true))
730        );
731    }
732
733    #[test]
734    fn test_invalid_casting() {
735        let text_value = CoreValue::from("Hello, World!");
736        assert_eq!(text_value.cast_to(CoreValueType::Integer), None);
737        assert_eq!(text_value.cast_to(CoreValueType::I16), None);
738        assert_eq!(text_value.cast_to(CoreValueType::I32), None);
739        assert_eq!(text_value.cast_to(CoreValueType::I64), None);
740        assert_eq!(text_value.cast_to(CoreValueType::F32), None);
741        assert_eq!(text_value.cast_to(CoreValueType::F64), None);
742
743        let int_value = CoreValue::from(42);
744        assert_eq!(int_value.cast_to(CoreValueType::Endpoint), None);
745        assert_eq!(int_value.cast_to(CoreValueType::Array), None);
746        assert_eq!(int_value.cast_to(CoreValueType::Object), None);
747        assert_eq!(int_value.cast_to(CoreValueType::Tuple), None);
748    }
749}