rhai_sci/
assertions.rs

1use rhai::plugin::*;
2
3#[export_module]
4pub mod assert_functions {
5    use rhai::{Array, Dynamic, EvalAltResult, Position, FLOAT};
6
7    use crate::if_list_convert_to_vec_float_and_do;
8
9    /// Assert that a statement is true and throw an error if it is not.
10    /// ```typescript
11    /// assert(2==2);
12    /// ```
13    #[rhai_fn(name = "assert", return_raw)]
14    pub fn assert(comparison: bool) -> Result<bool, Box<EvalAltResult>> {
15        if comparison {
16            Ok(comparison)
17        } else {
18            Err(EvalAltResult::ErrorArithmetic(
19                "The comparison is not true".to_string(),
20                Position::NONE,
21            )
22            .into())
23        }
24    }
25
26    /// Assert that two arguments are equal and throw an error if they are not.
27    /// ```typescript
28    /// assert_eq(2, 2);
29    /// ```
30    #[rhai_fn(name = "assert_eq", return_raw)]
31    pub fn assert_eq(lhs: Dynamic, rhs: Dynamic) -> Result<bool, Box<EvalAltResult>> {
32        let lhs_type = lhs.type_name();
33        let rhs_type = rhs.type_name();
34        if lhs_type != rhs_type {
35            return Err(EvalAltResult::ErrorArithmetic(
36                format!(
37                    "The left-hand side ({}) and right-hand side ({}) do not have the same type",
38                    lhs_type, rhs_type
39                ),
40                Position::NONE,
41            )
42            .into());
43        }
44
45        let comparison = format!("{:?}", lhs) == format!("{:?}", rhs);
46
47        if comparison {
48            Ok(comparison)
49        } else {
50            println!("LHS: {:?}", lhs);
51            println!("RHS: {:?}", rhs);
52            Err(EvalAltResult::ErrorArithmetic(
53                "The left-hand side and right-hand side are not equal".to_string(),
54                Position::NONE,
55            )
56            .into())
57        }
58    }
59
60    /// Assert that two arguments are unequal and throw an error if they are not.
61    /// ```typescript
62    /// assert_ne(2, 1);
63    /// ```
64    #[rhai_fn(name = "assert_ne", return_raw)]
65    pub fn assert_ne(lhs: Dynamic, rhs: Dynamic) -> Result<bool, Box<EvalAltResult>> {
66        let lhs_type = lhs.type_name();
67        let rhs_type = rhs.type_name();
68        if lhs_type != rhs_type {
69            return Err(EvalAltResult::ErrorArithmetic(
70                format!(
71                    "The left-hand side ({}) and right-hand side ({}) do not have the same type",
72                    lhs_type, rhs_type
73                ),
74                Position::NONE,
75            )
76            .into());
77        }
78
79        let comparison = format!("{:?}", lhs) != format!("{:?}", rhs);
80
81        if comparison {
82            Ok(comparison)
83        } else {
84            println!("LHS: {:?}", lhs);
85            println!("RHS: {:?}", rhs);
86            Err(EvalAltResult::ErrorArithmetic(
87                "The left-hand side and right-hand side are equal".to_string(),
88                Position::NONE,
89            )
90            .into())
91        }
92    }
93
94    /// Assert that two floats are approximately equal (within `eps`) and return an error if they
95    /// are not.
96    /// ```typescript
97    /// assert_approx_eq(2.0, 2.000000000000000001, 1e-10);
98    /// ```
99    #[rhai_fn(name = "assert_approx_eq", return_raw)]
100    pub fn assert_approx_eq(
101        lhs: FLOAT,
102        rhs: FLOAT,
103        eps: FLOAT,
104    ) -> Result<bool, Box<EvalAltResult>> {
105        if (lhs - rhs).abs() < eps {
106            Ok(true)
107        } else {
108            println!("LHS: {:?}", lhs);
109            println!("RHS: {:?}", rhs);
110            Err(EvalAltResult::ErrorArithmetic(
111                "The left-hand side and right-hand side are not equal".to_string(),
112                Position::NONE,
113            )
114            .into())
115        }
116    }
117
118    /// Assert that two floats are approximately equal and return an error if they
119    /// are not. Use the default tolerance of 1e-10 for the comparison.
120    /// ```typescript
121    /// assert_approx_eq(2.0, 2.000000000000000001);
122    /// ```
123    #[rhai_fn(name = "assert_approx_eq", return_raw)]
124    pub fn assert_approx_eq_with_default(
125        lhs: FLOAT,
126        rhs: FLOAT,
127    ) -> Result<bool, Box<EvalAltResult>> {
128        assert_approx_eq(lhs, rhs, 1e-10)
129    }
130
131    /// Assert that two arrays are approximately equal (within `eps`) and return an error if they
132    /// are not.
133    /// ```typescript
134    /// assert_approx_eq([2.0, 2.0], [2.0, 2.000000000000000001], 1e-10);
135    /// ```
136    #[rhai_fn(name = "assert_approx_eq", return_raw)]
137    pub fn assert_approx_eq_list(
138        lhs: Array,
139        rhs: Array,
140        eps: FLOAT,
141    ) -> Result<bool, Box<EvalAltResult>> {
142        if_list_convert_to_vec_float_and_do(&mut rhs.clone(), |rhs_as_vec_float| {
143            if_list_convert_to_vec_float_and_do(&mut lhs.clone(), |lhs_as_vec_float| {
144                let mut result = Ok(true);
145                for i in 0..rhs_as_vec_float.len() {
146                    result = result.and(assert_approx_eq(
147                        lhs_as_vec_float[i],
148                        rhs_as_vec_float[i],
149                        eps,
150                    ))
151                }
152                result
153            })
154        })
155    }
156
157    /// Assert that two arrays are approximately equal and return an error if they
158    /// are not. Use the default tolerance of 1e-10 for the comparison.
159    /// ```typescript
160    /// assert_approx_eq([2.0, 2.0], [2.0, 2.000000000000000001]);
161    /// ```
162    #[rhai_fn(name = "assert_approx_eq", return_raw)]
163    pub fn assert_approx_eq_list_with_default(
164        lhs: Array,
165        rhs: Array,
166    ) -> Result<bool, Box<EvalAltResult>> {
167        assert_approx_eq_list(lhs, rhs, 1e-10)
168    }
169}