1use crate::compiler::prelude::*;
2
3fn boolean(value: Value) -> Resolved {
4 match value {
5 v @ Value::Boolean(_) => Ok(v),
6 v => Err(format!("expected boolean, got {}", v.kind()).into()),
7 }
8}
9
10#[derive(Clone, Copy, Debug)]
11pub struct Boolean;
12
13impl Function for Boolean {
14 fn identifier(&self) -> &'static str {
15 "bool"
16 }
17
18 fn usage(&self) -> &'static str {
19 indoc! {"
20 Returns `value` if it is a Boolean, otherwise returns an error. This enables the type
21 checker to guarantee that the returned value is a Boolean and can be used in any
22 function that expects a Boolean.
23 "}
24 }
25
26 fn category(&self) -> &'static str {
27 Category::Type.as_ref()
28 }
29
30 fn internal_failure_reasons(&self) -> &'static [&'static str] {
31 &["`value` is not a Boolean."]
32 }
33
34 fn return_kind(&self) -> u16 {
35 kind::BOOLEAN
36 }
37
38 fn return_rules(&self) -> &'static [&'static str] {
39 &[
40 "Returns `value` if it's a Boolean.",
41 "Raises an error if not a Boolean.",
42 ]
43 }
44
45 fn parameters(&self) -> &'static [Parameter] {
46 const PARAMETERS: &[Parameter] = &[Parameter::required(
47 "value",
48 kind::ANY,
49 "The value to check if it is a Boolean.",
50 )];
51 PARAMETERS
52 }
53
54 fn examples(&self) -> &'static [Example] {
55 &[
56 example! {
57 title: "Valid Boolean",
58 source: "bool(false)",
59 result: Ok("false"),
60 },
61 example! {
62 title: "Invalid Boolean",
63 source: "bool!(42)",
64 result: Err(
65 r#"function call error for "bool" at (0:9): expected boolean, got integer"#,
66 ),
67 },
68 example! {
69 title: "Valid Boolean from path",
70 source: "bool!(.value)",
71 input: r#"{ "value": true }"#,
72 result: Ok("true"),
73 },
74 ]
75 }
76
77 fn compile(
78 &self,
79 _state: &state::TypeState,
80 _ctx: &mut FunctionCompileContext,
81 arguments: ArgumentList,
82 ) -> Compiled {
83 let value = arguments.required("value");
84
85 Ok(BooleanFn { value }.as_expr())
86 }
87}
88
89#[derive(Debug, Clone)]
90struct BooleanFn {
91 value: Box<dyn Expression>,
92}
93
94impl FunctionExpression for BooleanFn {
95 fn resolve(&self, ctx: &mut Context) -> Resolved {
96 boolean(self.value.resolve(ctx)?)
97 }
98
99 fn type_def(&self, state: &state::TypeState) -> TypeDef {
100 let non_boolean = !self.value.type_def(state).is_boolean();
101
102 TypeDef::boolean().maybe_fallible(non_boolean)
103 }
104}