rdf_fusion_functions/scalar/numeric/
round.rs

1use crate::scalar::dispatch::dispatch_unary_typed_value;
2use crate::scalar::sparql_op_impl::{
3    ScalarSparqlOpImpl, create_typed_value_sparql_op_impl,
4};
5use crate::scalar::{ScalarSparqlOp, ScalarSparqlOpSignature, SparqlOpArity};
6use rdf_fusion_encoding::typed_value::TypedValueEncoding;
7use rdf_fusion_extensions::functions::BuiltinName;
8use rdf_fusion_extensions::functions::FunctionName;
9use rdf_fusion_model::{Numeric, ThinError, TypedValueRef};
10
11#[derive(Debug, Hash, PartialEq, Eq)]
12pub struct RoundSparqlOp;
13
14impl Default for RoundSparqlOp {
15    fn default() -> Self {
16        Self::new()
17    }
18}
19
20impl RoundSparqlOp {
21    const NAME: FunctionName = FunctionName::Builtin(BuiltinName::Round);
22
23    pub fn new() -> Self {
24        Self {}
25    }
26}
27
28impl ScalarSparqlOp for RoundSparqlOp {
29    fn name(&self) -> &FunctionName {
30        &Self::NAME
31    }
32
33    fn signature(&self) -> ScalarSparqlOpSignature {
34        ScalarSparqlOpSignature::default_with_arity(SparqlOpArity::Fixed(1))
35    }
36
37    fn typed_value_encoding_op(
38        &self,
39    ) -> Option<Box<dyn ScalarSparqlOpImpl<TypedValueEncoding>>> {
40        Some(create_typed_value_sparql_op_impl(|args| {
41            dispatch_unary_typed_value(
42                &args.args[0],
43                |value| match value {
44                    TypedValueRef::NumericLiteral(numeric) => {
45                        let result = match numeric {
46                            Numeric::Float(v) => Ok(Numeric::Float(v.round())),
47                            Numeric::Double(v) => Ok(Numeric::Double(v.round())),
48                            Numeric::Decimal(v) => {
49                                v.checked_round().map(Numeric::Decimal)
50                            }
51                            _ => Ok(numeric),
52                        };
53                        result.map(TypedValueRef::NumericLiteral)
54                    }
55                    _ => ThinError::expected(),
56                },
57                ThinError::expected,
58            )
59        }))
60    }
61}