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