bracket/helper/
comparison.rs

1//! Helpers for numerical comparisons.
2//!
3//! Arguments must be numerical values otherwise a type assertion
4//! error is returned.
5//!
6//! Values are compared as `f64`.
7use crate::{
8    error::HelperError,
9    helper::{Helper, HelperValue},
10    parser::ast::Node,
11    render::{Context, Render, Type},
12};
13
14use serde_json::Value;
15
16fn cmp<'call, F>(ctx: &Context<'call>, cmp: F) -> HelperValue
17where
18    F: FnOnce(f64, f64) -> bool,
19{
20    ctx.arity(2..2)?;
21
22    let lhs = ctx.try_get(0, &[Type::Number])?;
23    let rhs = ctx.try_get(1, &[Type::Number])?;
24
25    match (lhs, rhs) {
26        (Value::Number(lhs), Value::Number(rhs)) => {
27            if let (Some(lhs), Some(rhs)) = (lhs.as_f64(), rhs.as_f64()) {
28                Ok(Some(Value::Bool(cmp(lhs, rhs))))
29            } else {
30                Err(HelperError::InvalidNumericalOperand(
31                    ctx.name().to_string(),
32                ))
33            }
34        }
35        _ => Err(HelperError::InvalidNumericalOperand(ctx.name().to_string())),
36    }
37}
38
39/// Perform an equality comparison.
40pub struct Equal;
41
42impl Helper for Equal {
43    fn call<'render, 'call>(
44        &self,
45        _rc: &mut Render<'render>,
46        ctx: &Context<'call>,
47        _template: Option<&'render Node<'render>>,
48    ) -> HelperValue {
49        cmp(ctx, |lhs: f64, rhs: f64| lhs == rhs)
50    }
51}
52
53/// Perform a negated equality comparison.
54pub struct NotEqual;
55
56impl Helper for NotEqual {
57    fn call<'render, 'call>(
58        &self,
59        _rc: &mut Render<'render>,
60        ctx: &Context<'call>,
61        _template: Option<&'render Node<'render>>,
62    ) -> HelperValue {
63        cmp(ctx, |lhs: f64, rhs: f64| lhs != rhs)
64    }
65}
66
67/// Perform a numerical greater than comparison.
68pub struct GreaterThan;
69
70impl Helper for GreaterThan {
71    fn call<'render, 'call>(
72        &self,
73        _rc: &mut Render<'render>,
74        ctx: &Context<'call>,
75        _template: Option<&'render Node<'render>>,
76    ) -> HelperValue {
77        cmp(ctx, |lhs: f64, rhs: f64| lhs > rhs)
78    }
79}
80
81/// Perform a numerical greater than or equal comparison.
82pub struct GreaterThanEqual;
83
84impl Helper for GreaterThanEqual {
85    fn call<'render, 'call>(
86        &self,
87        _rc: &mut Render<'render>,
88        ctx: &Context<'call>,
89        _template: Option<&'render Node<'render>>,
90    ) -> HelperValue {
91        cmp(ctx, |lhs: f64, rhs: f64| lhs >= rhs)
92    }
93}
94
95/// Perform a numerical less than comparison.
96pub struct LessThan;
97
98impl Helper for LessThan {
99    fn call<'render, 'call>(
100        &self,
101        _rc: &mut Render<'render>,
102        ctx: &Context<'call>,
103        _template: Option<&'render Node<'render>>,
104    ) -> HelperValue {
105        cmp(ctx, |lhs: f64, rhs: f64| lhs < rhs)
106    }
107}
108
109/// Perform a numerical less than comparison.
110pub struct LessThanEqual;
111
112impl Helper for LessThanEqual {
113    fn call<'render, 'call>(
114        &self,
115        _rc: &mut Render<'render>,
116        ctx: &Context<'call>,
117        _template: Option<&'render Node<'render>>,
118    ) -> HelperValue {
119        cmp(ctx, |lhs: f64, rhs: f64| lhs <= rhs)
120    }
121}