Skip to main content

linkrs_query/executor/expression/functions/builtin/
conversion.rs

1//! Implementation of type conversion functions
2
3use crate::executor::expression::ExpressionError;
4use linkrs_core::value::NullType;
5use linkrs_core::Value;
6
7define_function_enum! {
8    /// Type conversion function enumeration
9    pub enum ConversionFunction {
10        ToString => {
11            name: "to_string",
12            arity: 1,
13            variadic: false,
14            description: "Convert to String",
15            handler: execute_to_string
16        },
17        ToInt => {
18            name: "to_int",
19            arity: 1,
20            variadic: false,
21            description: "convert to an integer (math.)",
22            handler: execute_to_int
23        },
24        ToFloat => {
25            name: "to_float",
26            arity: 1,
27            variadic: false,
28            description: "convert to floating point",
29            handler: execute_to_float
30        },
31        ToBool => {
32            name: "to_bool",
33            arity: 1,
34            variadic: false,
35            description: "Convert to Boolean",
36            handler: execute_to_bool
37        },
38    }
39}
40
41fn execute_to_string(args: &[Value]) -> Result<Value, ExpressionError> {
42    match &args[0] {
43        Value::Null(_) => Ok(Value::Null(NullType::Null)),
44        _ => args[0]
45            .to_string()
46            .map(Value::string)
47            .map_err(ExpressionError::type_error),
48    }
49}
50
51fn execute_to_int(args: &[Value]) -> Result<Value, ExpressionError> {
52    match &args[0] {
53        Value::Null(_) => Ok(Value::Null(NullType::Null)),
54        _ => {
55            let result = args[0].to_int();
56            if let Value::Null(NullType::BadData) = result {
57                Err(ExpressionError::type_error(
58                    "The to_int function does not support this type",
59                ))
60            } else {
61                Ok(result)
62            }
63        }
64    }
65}
66
67fn execute_to_float(args: &[Value]) -> Result<Value, ExpressionError> {
68    match &args[0] {
69        Value::Null(_) => Ok(Value::Null(NullType::Null)),
70        _ => {
71            let result = args[0].to_float();
72            if let Value::Null(NullType::BadData) = result {
73                Err(ExpressionError::type_error(
74                    "The to_float function does not support the type",
75                ))
76            } else {
77                Ok(result)
78            }
79        }
80    }
81}
82
83fn execute_to_bool(args: &[Value]) -> Result<Value, ExpressionError> {
84    match &args[0] {
85        Value::Null(_) => Ok(Value::Null(NullType::Null)),
86        _ => {
87            let result = args[0].to_bool();
88            if let Value::Null(NullType::BadData) = result {
89                Err(ExpressionError::type_error(
90                    "The to_bool function does not support this type",
91                ))
92            } else {
93                Ok(result)
94            }
95        }
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102
103    #[test]
104    fn test_to_string() {
105        let func = ConversionFunction::ToString;
106        let result = func
107            .execute(&[Value::Int(42)])
108            .expect("Implementation should not fail");
109        assert_eq!(result, Value::string("42"));
110    }
111
112    #[test]
113    fn test_to_int() {
114        let func = ConversionFunction::ToInt;
115        let result = func
116            .execute(&[Value::string("42")])
117            .expect("Implementation should not fail");
118        assert_eq!(result, Value::Int(42));
119    }
120
121    #[test]
122    fn test_to_float() {
123        let func = ConversionFunction::ToFloat;
124        let result = func
125            .execute(&[Value::Int(42)])
126            .expect("Implementation should not fail");
127        assert_eq!(result, Value::Float(42.0));
128    }
129
130    #[test]
131    fn test_to_bool() {
132        let func = ConversionFunction::ToBool;
133        let result = func
134            .execute(&[Value::Int(1)])
135            .expect("Implementation should not fail");
136        assert_eq!(result, Value::Bool(true));
137    }
138
139    #[test]
140    fn test_null_handling() {
141        let func = ConversionFunction::ToString;
142        let result = func
143            .execute(&[Value::Null(NullType::Null)])
144            .expect("Implementation should not fail");
145        assert_eq!(result, Value::Null(NullType::Null));
146    }
147}