rdf_fusion_functions/scalar/numeric/
floor.rs1use 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 FloorSparqlOp;
13
14impl Default for FloorSparqlOp {
15 fn default() -> Self {
16 Self::new()
17 }
18}
19
20impl FloorSparqlOp {
21 const NAME: FunctionName = FunctionName::Builtin(BuiltinName::Floor);
22
23 pub fn new() -> Self {
24 Self {}
25 }
26}
27
28impl ScalarSparqlOp for FloorSparqlOp {
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.floor())),
47 Numeric::Double(v) => Ok(Numeric::Double(v.floor())),
48 Numeric::Decimal(v) => {
49 v.checked_floor().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}