1use jql_parser::{
2 group::split,
3 parser::parse,
4 tokens::Token,
5};
6use rayon::prelude::*;
7use serde_json::{
8 Value,
9 json,
10};
11
12use crate::{
13 array::{
14 get_array_as_indexes,
15 get_array_indexes,
16 get_array_lenses,
17 get_array_range,
18 get_flattened_array,
19 },
20 errors::JqlRunnerError,
21 object::{
22 get_flattened_object,
23 get_object_as_keys,
24 get_object_indexes,
25 get_object_key,
26 get_object_multi_key,
27 get_object_range,
28 },
29};
30
31pub fn raw(input: &str, json: &Value) -> Result<Value, JqlRunnerError> {
39 if input.is_empty() {
40 return Err(JqlRunnerError::EmptyQueryError);
41 }
42
43 let tokens = parse(input)?;
44
45 token(&tokens, json)
46}
47
48pub fn token(tokens: &[Token], json: &Value) -> Result<Value, JqlRunnerError> {
56 let groups = split(tokens);
57
58 if groups.len() == 1 {
59 return group_runner(&groups[0], json);
60 }
61
62 if groups.len() < 8 {
63 let result =
64 groups
65 .iter()
66 .try_fold(Vec::with_capacity(groups.len()), |mut acc, group| {
67 acc.push(group_runner(group, json)?);
68
69 Ok::<Vec<Value>, JqlRunnerError>(acc)
70 })?;
71
72 return Ok(json!(result));
73 }
74
75 let result = groups
76 .par_iter()
77 .try_fold_with(vec![], |mut acc: Vec<Value>, group| {
78 acc.push(group_runner(group, json)?);
79
80 Ok::<Vec<Value>, JqlRunnerError>(acc)
81 })
82 .try_reduce(Vec::new, |mut a, b| {
83 a.extend(b);
84
85 Ok(a)
86 });
87
88 result.map(|group| json!(group))
89}
90
91pub(crate) fn group_runner(tokens: &[&Token], json: &Value) -> Result<Value, JqlRunnerError> {
96 tokens
97 .iter()
98 .try_fold((json.clone(), false), |mut outer_acc, &token| {
101 if outer_acc.1 {
102 let piped = outer_acc.1;
103 let array = outer_acc.0.as_array_mut().unwrap();
104
105 if array.len() < 128 {
112 let mut values = Vec::with_capacity(array.len());
113 let mut last_piped = piped;
114
115 for inner_value in array.iter() {
116 let r = matcher((inner_value.clone(), piped), token)?;
117
118 values.push(r.0);
119 last_piped = r.1;
120 }
121
122 return Ok((json!(values), last_piped));
123 }
124
125 let result = array
126 .par_iter()
127 .try_fold_with(
128 (vec![], piped),
129 |mut inner_acc: (Vec<Value>, bool), inner_value| {
130 let result = matcher((inner_value.clone(), piped), token)?;
131
132 inner_acc.0.push(result.0);
133 inner_acc.1 = result.1;
134
135 Ok::<(Vec<Value>, bool), JqlRunnerError>(inner_acc)
136 },
137 )
138 .try_reduce(
139 || (vec![], false),
140 |mut a, b| {
141 a.0.extend(b.0);
142
143 Ok((a.0, b.1))
144 },
145 )?;
146
147 Ok((json!(result.0), result.1))
148 } else {
149 matcher(outer_acc, token)
150 }
151 })
152 .map(|(value, _)| value)
154}
155
156fn matcher(
160 (mut acc, mut piped): (Value, bool),
161 token: &Token,
162) -> Result<(Value, bool), JqlRunnerError> {
163 let result = match token {
164 Token::ArrayIndexSelector(indexes) => get_array_indexes(indexes, &acc),
165 Token::ArrayRangeSelector(range) => get_array_range(range, &mut acc),
166 Token::FlattenOperator => match acc {
167 Value::Array(_) => get_flattened_array(&acc),
168 Value::Object(_) => Ok(get_flattened_object(&acc)),
169 _ => Err(JqlRunnerError::FlattenError(acc)),
170 },
171 Token::KeyOperator => match acc {
172 Value::Array(_) => get_array_as_indexes(&acc),
173 Value::Object(_) => get_object_as_keys(&mut acc),
174 Value::Bool(bool) => Ok(json!(bool)),
176 Value::Number(number) => Ok(json!(number)),
177 Value::String(string) => Ok(json!(string)),
178 Value::Null => Ok(json!(null)),
179 },
180 Token::GroupSeparator => unreachable!(),
181 Token::KeySelector(key) => get_object_key(key, &acc),
182 Token::LensSelector(lenses) => get_array_lenses(lenses, &mut acc),
183 Token::MultiKeySelector(keys) => get_object_multi_key(keys, &mut acc),
184 Token::ObjectIndexSelector(indexes) => get_object_indexes(indexes, &mut acc),
185 Token::ObjectRangeSelector(range) => get_object_range(range, &mut acc),
186 Token::PipeInOperator => {
187 if !acc.is_array() {
188 return Err(JqlRunnerError::PipeInError(acc));
189 }
190
191 piped = true;
192
193 Ok(acc)
194 }
195 Token::PipeOutOperator => {
196 if !piped {
197 return Err(JqlRunnerError::PipeOutError);
198 }
199
200 piped = false;
201
202 Ok(acc)
203 }
204 Token::TruncateOperator => match acc {
205 Value::Array(_) => Ok(json!([])),
206 Value::Object(_) => Ok(json!({})),
207 Value::Bool(_) | Value::Number(_) | Value::String(_) | Value::Null => Ok(acc),
208 },
209 };
210
211 result.map(|value| (value, piped))
212}
213
214#[cfg(test)]
215mod tests {
216 use jql_parser::{
217 errors::JqlParserError,
218 tokens::{
219 Token,
220 View,
221 },
222 };
223 use serde_json::json;
224
225 use super::raw;
226 use crate::errors::JqlRunnerError;
227
228 #[test]
229 fn check_runner_empty_input_error() {
230 assert_eq!(raw("", &json!("")), Err(JqlRunnerError::EmptyQueryError));
231 }
232
233 #[test]
234 fn check_runner_parsing_error() {
235 assert_eq!(
236 raw(r#""a"b"#, &json!({ "a": 1 })),
237 Err(JqlRunnerError::ParsingError(JqlParserError::ParsingError {
238 tokens: [Token::KeySelector("a")].stringify(),
239 unparsed: "b".to_string(),
240 }))
241 );
242 }
243
244 #[test]
245 fn check_runner_no_key_found_error() {
246 let parent = json!({ "a": 1 });
247
248 assert_eq!(
249 raw(r#""b""#, &parent),
250 Err(JqlRunnerError::KeyNotFoundError {
251 key: "b".to_string(),
252 parent
253 })
254 );
255 }
256
257 #[test]
258 fn check_runner_index_not_found_error() {
259 let parent = json!(["a"]);
260
261 assert_eq!(
262 raw("[1]", &parent),
263 Err(JqlRunnerError::IndexOutOfBoundsError { index: 1, parent })
264 );
265 }
266
267 #[test]
268 fn check_runner_success() {
269 assert_eq!(
270 raw(r#""a","b""#, &json!({ "a": 1, "b": 2 })),
271 Ok(json!([1, 2]))
272 );
273 assert_eq!(raw(r#""a""b""#, &json!({ "a": { "b": 2 } })), Ok(json!(2)));
274 assert_eq!(
275 raw("[4,2,0]", &json!(["a", "b", "c", "d", "e"])),
276 Ok(json!(["e", "c", "a"]))
277 );
278 }
279
280 #[test]
281 fn check_runner_pipes() {
282 let value = json!({ "a": [{ "b": { "c": 1 } }, { "b": { "c": 2 }}]});
283
284 assert_eq!(raw(r#""a"|>"b""c"<|[1]"#, &value), Ok(json!(2)));
285 }
286
287 #[test]
288 fn check_runner_truncate() {
289 assert_eq!(raw(r#""a"!"#, &json!({ "a": [1, 2, 3] })), Ok(json!([])));
290 assert_eq!(raw(r#""a"!"#, &json!({ "a": { "b": 1 } })), Ok(json!({})));
291 assert_eq!(raw(r#""a"!"#, &json!({ "a": true })), Ok(json!(true)));
292 assert_eq!(raw(r#""a"!"#, &json!({ "a": 1 })), Ok(json!(1)));
293 assert_eq!(raw(r#""a"!"#, &json!({ "a": "b" })), Ok(json!("b")));
294 assert_eq!(raw(r#""a"!"#, &json!({ "a": null })), Ok(json!(null)));
295 assert_eq!(raw("!", &json!({ "a": null })), Ok(json!({})));
296 assert_eq!(
297 raw(r#""a"!"b""#, &json!({ "a": [1, 2, 3] })),
298 Err(JqlRunnerError::ParsingError(JqlParserError::TruncateError(
299 [
300 Token::KeySelector("a"),
301 Token::TruncateOperator,
302 Token::KeySelector("b")
303 ]
304 .stringify(),
305 )))
306 );
307 }
308
309 #[test]
310 fn check_runner_lens() {
311 let value = json!([
312 { "a": { "b": { "c": 1 }}},
313 { "a": { "b": { "c": 2 }}},
314 ]);
315
316 assert_eq!(
317 raw(r#"|={"a""b""c"=2}"#, &value),
318 Ok(json!([
319 { "a": { "b": { "c": 2 }}}
320 ]))
321 );
322 }
323
324 #[test]
325 fn check_runner_keys() {
326 let value = json!({ "a": { "b": { "c": { "d": 1 }}}});
327
328 assert_eq!(raw(r#""a""b""c"@"#, &value), Ok(json!(["d"])));
329 }
330}