kcl_lib/std/
assert.rs

1//! Standard library assert functions.
2
3use anyhow::Result;
4use kcl_derive_docs::stdlib;
5
6use crate::{
7    errors::{KclError, KclErrorDetails},
8    execution::{ExecState, KclValue},
9    std::Args,
10};
11
12async fn _assert(value: bool, message: &str, args: &Args) -> Result<(), KclError> {
13    if !value {
14        return Err(KclError::Type(KclErrorDetails {
15            message: format!("assert failed: {}", message),
16            source_ranges: vec![args.source_range],
17        }));
18    }
19    Ok(())
20}
21
22/// Check that the provided value is true, or raise a [KclError]
23/// with the provided description.
24pub async fn assert(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
25    let (data, description): (bool, String) = args.get_data()?;
26    inner_assert(data, &description, &args).await?;
27    Ok(KclValue::none())
28}
29
30/// Check a value at runtime, and raise an error if the argument provided
31/// is false.
32///
33/// ```no_run
34/// myVar = true
35/// assert(myVar, "should always be true")
36/// ```
37#[stdlib {
38    name = "assert",
39}]
40async fn inner_assert(data: bool, message: &str, args: &Args) -> Result<(), KclError> {
41    _assert(data, message, args).await
42}
43
44pub async fn assert_lt(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
45    let (left, right, description): (f64, f64, String) = args.get_data()?;
46    inner_assert_lt(left, right, &description, &args).await?;
47    Ok(KclValue::none())
48}
49
50/// Check that a numerical value is less than to another at runtime,
51/// otherwise raise an error.
52///
53/// ```no_run
54/// assertLessThan(1, 2, "1 is less than 2")
55/// ```
56#[stdlib {
57    name = "assertLessThan",
58}]
59async fn inner_assert_lt(left: f64, right: f64, message: &str, args: &Args) -> Result<(), KclError> {
60    _assert(left < right, message, args).await
61}
62
63pub async fn assert_gt(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
64    let (left, right, description): (f64, f64, String) = args.get_data()?;
65    inner_assert_gt(left, right, &description, &args).await?;
66    Ok(KclValue::none())
67}
68
69/// Check that a numerical value equals another at runtime,
70/// otherwise raise an error.
71///
72/// ```no_run
73/// n = 1.0285
74/// o = 1.0286
75/// assertEqual(n, o, 0.01, "n is within the given tolerance for o")
76/// ```
77#[stdlib {
78    name = "assertEqual",
79}]
80async fn inner_assert_equal(left: f64, right: f64, epsilon: f64, message: &str, args: &Args) -> Result<(), KclError> {
81    if epsilon <= 0.0 {
82        Err(KclError::Type(KclErrorDetails {
83            message: "assertEqual epsilon must be greater than zero".to_owned(),
84            source_ranges: vec![args.source_range],
85        }))
86    } else if (right - left).abs() < epsilon {
87        Ok(())
88    } else {
89        Err(KclError::Type(KclErrorDetails {
90            message: format!("assert failed because {left} != {right}: {message}"),
91            source_ranges: vec![args.source_range],
92        }))
93    }
94}
95
96pub async fn assert_equal(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
97    let (left, right, epsilon, description): (f64, f64, f64, String) = args.get_data()?;
98    inner_assert_equal(left, right, epsilon, &description, &args).await?;
99    Ok(KclValue::none())
100}
101
102/// Check that a numerical value is greater than another at runtime,
103/// otherwise raise an error.
104///
105/// ```no_run
106/// assertGreaterThan(2, 1, "2 is greater than 1")
107/// ```
108#[stdlib {
109    name = "assertGreaterThan",
110}]
111async fn inner_assert_gt(left: f64, right: f64, message: &str, args: &Args) -> Result<(), KclError> {
112    _assert(left > right, message, args).await
113}
114
115pub async fn assert_lte(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
116    let (left, right, description): (f64, f64, String) = args.get_data()?;
117    inner_assert_lte(left, right, &description, &args).await?;
118    Ok(KclValue::none())
119}
120
121/// Check that a numerical value is less than or equal to another at runtime,
122/// otherwise raise an error.
123///
124/// ```no_run
125/// assertLessThanOrEq(1, 2, "1 is less than 2")
126/// assertLessThanOrEq(1, 1, "1 is equal to 1")
127/// ```
128#[stdlib {
129    name = "assertLessThanOrEq",
130}]
131async fn inner_assert_lte(left: f64, right: f64, message: &str, args: &Args) -> Result<(), KclError> {
132    _assert(left <= right, message, args).await
133}
134
135pub async fn assert_gte(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
136    let (left, right, description): (f64, f64, String) = args.get_data()?;
137    inner_assert_gte(left, right, &description, &args).await?;
138    Ok(KclValue::none())
139}
140
141/// Check that a numerical value is greater than or equal to another at runtime,
142/// otherwise raise an error.
143///
144/// ```no_run
145/// assertGreaterThanOrEq(2, 1, "2 is greater than 1")
146/// assertGreaterThanOrEq(1, 1, "1 is equal to 1")
147/// ```
148#[stdlib {
149    name = "assertGreaterThanOrEq",
150}]
151async fn inner_assert_gte(left: f64, right: f64, message: &str, args: &Args) -> Result<(), KclError> {
152    _assert(left >= right, message, args).await
153}