1use crate::value_ops::{is_truthy, value_to_display_string};
4use nodedb_types::Value;
5
6pub fn eval_cast(val: &Value, to_type: &crate::expr::CastType) -> Value {
7 use crate::expr::CastType;
8 match to_type {
9 CastType::Int => match val {
10 Value::Integer(_) => val.clone(),
11 Value::Float(f) => Value::Integer(*f as i64),
12 Value::String(s) => s.parse::<i64>().map(Value::Integer).unwrap_or(Value::Null),
13 Value::Bool(b) => Value::Integer(*b as i64),
14 Value::Decimal(d) => {
15 use rust_decimal::prelude::ToPrimitive;
16 d.to_i64().map(Value::Integer).unwrap_or(Value::Null)
17 }
18 _ => Value::Null,
19 },
20 CastType::Float => match val {
21 Value::Float(_) => val.clone(),
22 Value::Integer(i) => Value::Float(*i as f64),
23 Value::String(s) => s
24 .parse::<f64>()
25 .map(Value::Float)
26 .ok()
27 .unwrap_or(Value::Null),
28 Value::Decimal(d) => {
29 use rust_decimal::prelude::ToPrimitive;
30 d.to_f64().map(Value::Float).unwrap_or(Value::Null)
31 }
32 _ => Value::Null,
33 },
34 CastType::String => Value::String(value_to_display_string(val)),
35 CastType::Bool => Value::Bool(is_truthy(val)),
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42 use crate::expr::CastType;
43
44 #[test]
45 fn cast_string_to_int() {
46 assert_eq!(
47 eval_cast(&Value::String("42".into()), &CastType::Int),
48 Value::Integer(42)
49 );
50 }
51
52 #[test]
53 fn cast_float_to_int() {
54 assert_eq!(
55 eval_cast(&Value::Float(3.7), &CastType::Int),
56 Value::Integer(3)
57 );
58 }
59
60 #[test]
61 fn cast_int_to_string() {
62 assert_eq!(
63 eval_cast(&Value::Integer(42), &CastType::String),
64 Value::String("42".into())
65 );
66 }
67
68 #[test]
69 fn cast_to_bool() {
70 assert_eq!(
71 eval_cast(&Value::Integer(1), &CastType::Bool),
72 Value::Bool(true)
73 );
74 assert_eq!(
75 eval_cast(&Value::Integer(0), &CastType::Bool),
76 Value::Bool(false)
77 );
78 assert_eq!(
79 eval_cast(&Value::String(String::new()), &CastType::Bool),
80 Value::Bool(false)
81 );
82 assert_eq!(
83 eval_cast(&Value::String("x".into()), &CastType::Bool),
84 Value::Bool(true)
85 );
86 }
87}