drasi_core/evaluation/functions/numeric/
abs.rs

1// Copyright 2024 The Drasi Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use async_trait::async_trait;
16use drasi_query_ast::ast;
17
18use crate::evaluation::functions::ScalarFunction;
19use crate::evaluation::variable_value::float::Float;
20use crate::evaluation::variable_value::VariableValue;
21use crate::evaluation::{ExpressionEvaluationContext, FunctionError, FunctionEvaluationError};
22
23#[derive(Debug)]
24pub struct Abs {}
25
26#[async_trait]
27impl ScalarFunction for Abs {
28    async fn call(
29        &self,
30        _context: &ExpressionEvaluationContext,
31        expression: &ast::FunctionExpression,
32        args: Vec<VariableValue>,
33    ) -> Result<VariableValue, FunctionError> {
34        if args.len() != 1 {
35            return Err(FunctionError {
36                function_name: expression.name.to_string(),
37                error: FunctionEvaluationError::InvalidArgumentCount,
38            });
39        }
40        match &args[0] {
41            VariableValue::Null => Ok(VariableValue::Null),
42            VariableValue::Integer(n) => Ok(VariableValue::Integer(match n.as_i64() {
43                Some(i) => i.abs().into(),
44                None => {
45                    return Err(FunctionError {
46                        function_name: expression.name.to_string(),
47                        error: FunctionEvaluationError::OverflowError,
48                    })
49                }
50            })),
51            VariableValue::Float(n) => Ok(VariableValue::Float(
52                match Float::from_f64(match n.as_f64() {
53                    Some(f) => f.abs(),
54                    None => {
55                        return Err(FunctionError {
56                            function_name: expression.name.to_string(),
57                            error: FunctionEvaluationError::OverflowError,
58                        })
59                    }
60                }) {
61                    Some(f) => f,
62                    None => {
63                        return Err(FunctionError {
64                            function_name: expression.name.to_string(),
65                            error: FunctionEvaluationError::OverflowError,
66                        })
67                    }
68                },
69            )),
70            _ => Err(FunctionError {
71                function_name: expression.name.to_string(),
72                error: FunctionEvaluationError::InvalidArgument(0),
73            }),
74        }
75    }
76}