drasi_core/evaluation/functions/aggregation/
last.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 std::{fmt::Debug, sync::Arc};
16
17use crate::{
18    evaluation::{FunctionError, FunctionEvaluationError},
19    interface::ResultIndex,
20    models::ElementValue,
21};
22
23use async_trait::async_trait;
24
25use drasi_query_ast::ast;
26
27use crate::evaluation::{variable_value::VariableValue, ExpressionEvaluationContext};
28
29use super::{super::AggregatingFunction, Accumulator, ValueAccumulator};
30
31pub struct Last {}
32
33#[async_trait]
34impl AggregatingFunction for Last {
35    fn initialize_accumulator(
36        &self,
37        _context: &ExpressionEvaluationContext,
38        _expression: &ast::FunctionExpression,
39        _grouping_keys: &Vec<VariableValue>,
40        _index: Arc<dyn ResultIndex>,
41    ) -> Accumulator {
42        Accumulator::Value(ValueAccumulator::Value(ElementValue::Null))
43    }
44
45    fn accumulator_is_lazy(&self) -> bool {
46        false
47    }
48
49    async fn apply(
50        &self,
51        _context: &ExpressionEvaluationContext,
52        args: Vec<VariableValue>,
53        accumulator: &mut Accumulator,
54    ) -> Result<VariableValue, FunctionError> {
55        if args.len() != 1 {
56            return Err(FunctionError {
57                function_name: "Last".to_string(),
58                error: FunctionEvaluationError::InvalidArgumentCount,
59            });
60        }
61
62        let value = match accumulator {
63            Accumulator::Value(super::ValueAccumulator::Value(value)) => value,
64            _ => {
65                return Err(FunctionError {
66                    function_name: "Last".to_string(),
67                    error: FunctionEvaluationError::CorruptData,
68                });
69            }
70        };
71
72        *value = match (&args[0]).try_into() {
73            Ok(value) => value,
74            Err(_) => {
75                return Err(FunctionError {
76                    function_name: "Last".to_string(),
77                    error: FunctionEvaluationError::InvalidType {
78                        expected: "ElementValue".to_string(),
79                    },
80                })
81            }
82        };
83
84        Ok((&value.clone()).into())
85    }
86
87    async fn revert(
88        &self,
89        _context: &ExpressionEvaluationContext,
90        args: Vec<VariableValue>,
91        accumulator: &mut Accumulator,
92    ) -> Result<VariableValue, FunctionError> {
93        if args.len() != 1 {
94            return Err(FunctionError {
95                function_name: "Last".to_string(),
96                error: FunctionEvaluationError::InvalidArgumentCount,
97            });
98        }
99        let value = match accumulator {
100            Accumulator::Value(super::ValueAccumulator::Value(value)) => value,
101            _ => {
102                return Err(FunctionError {
103                    function_name: "Last".to_string(),
104                    error: FunctionEvaluationError::CorruptData,
105                })
106            }
107        };
108
109        *value = ElementValue::Null;
110        Ok(VariableValue::Null)
111    }
112
113    async fn snapshot(
114        &self,
115        _context: &ExpressionEvaluationContext,
116        _args: Vec<VariableValue>,
117        accumulator: &Accumulator,
118    ) -> Result<VariableValue, FunctionError> {
119        let value = match accumulator {
120            Accumulator::Value(super::ValueAccumulator::Value(value)) => value,
121            _ => {
122                return Err(FunctionError {
123                    function_name: "Last".to_string(),
124                    error: FunctionEvaluationError::CorruptData,
125                })
126            }
127        };
128        Ok((&value.clone()).into())
129    }
130}
131
132impl Debug for Last {
133    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134        write!(f, "Last")
135    }
136}