1use serde_json::Value;
4
5use crate::error::Error;
6use crate::value::{Evaluated, Parsed};
7use crate::NULL;
8
9pub fn if_(data: &Value, args: &Vec<&Value>) -> Result<Value, Error> {
16 match args.len() {
19 0 => {
20 return Ok(NULL);
21 }
22 1 => {
27 let parsed = Parsed::from_value(args[0])?;
28 let evaluated = parsed.evaluate(&data)?;
29 return Ok(evaluated.into());
30 }
31 _ => {}
32 }
33
34 args.into_iter()
35 .enumerate()
36 .fold(Ok((NULL, false, false)), |last_res, (i, val)| {
41 let (last_eval, was_truthy, should_return) = last_res?;
42 if should_return {
44 Ok((last_eval, was_truthy, should_return))
45 }
46 else if i % 2 == 0 {
48 let parsed = Parsed::from_value(val)?;
49 let eval = parsed.evaluate(data)?;
50 let is_truthy = match eval {
51 Evaluated::New(ref v) => truthy(v),
52 Evaluated::Raw(v) => truthy(v),
53 };
54 Ok((eval.into(), is_truthy, false))
57 }
58 else {
60 if was_truthy {
63 let parsed = Parsed::from_value(val)?;
64 let t_eval = parsed.evaluate(data)?;
65 Ok((Value::from(t_eval), true, true))
66 } else {
67 Ok((NULL, was_truthy, should_return))
70 }
71 }
72 })
73 .map(|rv| rv.0)
74}
75
76pub fn or(data: &Value, args: &Vec<&Value>) -> Result<Value, Error> {
78 enum OrResult {
79 Uninitialized,
80 Truthy(Value),
81 Current(Value),
82 }
83
84 let eval =
85 args.into_iter()
86 .fold(Ok(OrResult::Uninitialized), |last_res, current| {
87 let last_eval = last_res?;
88
89 if let OrResult::Truthy(_) = last_eval {
91 return Ok(last_eval);
92 }
93
94 let parsed = Parsed::from_value(current)?;
95 let evaluated = parsed.evaluate(data)?;
96
97 if truthy_from_evaluated(&evaluated) {
98 return Ok(OrResult::Truthy(evaluated.into()));
99 }
100
101 Ok(OrResult::Current(evaluated.into()))
102 })?;
103
104 match eval {
105 OrResult::Truthy(v) => Ok(v),
106 OrResult::Current(v) => Ok(v),
107 _ => Err(Error::UnexpectedError(
108 "Or operation had no values to operate on".into(),
109 )),
110 }
111}
112
113pub fn and(data: &Value, args: &Vec<&Value>) -> Result<Value, Error> {
115 enum AndResult {
116 Uninitialized,
117 Falsey(Value),
118 Current(Value),
119 }
120
121 let eval =
122 args.into_iter()
123 .fold(Ok(AndResult::Uninitialized), |last_res, current| {
124 let last_eval = last_res?;
125
126 if let AndResult::Falsey(_) = last_eval {
127 return Ok(last_eval);
128 }
129
130 let parsed = Parsed::from_value(current)?;
131 let evaluated = parsed.evaluate(data)?;
132
133 if !truthy_from_evaluated(&evaluated) {
134 return Ok(AndResult::Falsey(evaluated.into()));
135 }
136
137 Ok(AndResult::Current(evaluated.into()))
138 })?;
139
140 match eval {
141 AndResult::Falsey(v) => Ok(v),
142 AndResult::Current(v) => Ok(v),
143 _ => Err(Error::UnexpectedError(
144 "And operation had no values to operate on".into(),
145 )),
146 }
147}
148
149pub fn truthy_from_evaluated(evaluated: &Evaluated) -> bool {
150 match evaluated {
151 Evaluated::New(ref v) => truthy(v),
152 Evaluated::Raw(v) => truthy(v),
153 }
154}
155
156pub fn truthy(val: &Value) -> bool {
167 match val {
168 Value::Null => false,
169 Value::Bool(v) => *v,
170 Value::Number(v) => v
171 .as_f64()
172 .map(|v_num| if v_num == 0.0 { false } else { true })
173 .unwrap_or(false),
174 Value::String(v) => {
175 if v == "" {
176 false
177 } else {
178 true
179 }
180 }
181 Value::Array(v) => {
182 if v.len() == 0 {
183 false
184 } else {
185 true
186 }
187 }
188 Value::Object(_) => true,
189 }
190}
191
192#[cfg(test)]
193mod test_truthy {
194 use super::*;
195 use serde_json::json;
196
197 #[test]
198 fn test_truthy() {
199 let trues = [
200 json!(true),
201 json!([1]),
202 json!([1, 2]),
203 json!({}),
204 json!({"a": 1}),
205 json!(1),
206 json!(-1),
207 json!("foo"),
208 ];
209
210 let falses = [json!(false), json!([]), json!(""), json!(0), json!(null)];
211
212 trues.iter().for_each(|v| assert!(truthy(&v)));
213 falses.iter().for_each(|v| assert!(!truthy(&v)));
214 }
215}