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 results: Vec<Result<Value, JqlRunnerError>> = groups
80 .par_iter()
81 .map(|group| group_runner(group, json))
82 .collect();
83
84 let result = results.into_iter().collect::<Result<Vec<Value>, _>>()?;
85
86 Ok(json!(result))
87}
88
89pub(crate) fn group_runner(tokens: &[&Token], json: &Value) -> Result<Value, JqlRunnerError> {
94 tokens
95 .iter()
96 .try_fold((json.clone(), false), |mut outer_acc, &token| {
97 if outer_acc.1 {
98 let piped = outer_acc.1;
99 let array = outer_acc.0.as_array_mut().unwrap();
100 let mut values = Vec::with_capacity(array.len());
101 let mut last_piped = piped;
102
103 for inner_value in array.iter() {
104 let result = matcher((inner_value.clone(), piped), token)?;
105
106 values.push(result.0);
107 last_piped = result.1;
108 }
109
110 Ok((json!(values), last_piped))
111 } else {
112 matcher(outer_acc, token)
113 }
114 })
115 .map(|(value, _)| value)
117}
118
119fn matcher(
123 (mut acc, mut piped): (Value, bool),
124 token: &Token,
125) -> Result<(Value, bool), JqlRunnerError> {
126 let result = match token {
127 Token::ArrayIndexSelector(indexes) => get_array_indexes(indexes, &acc),
128 Token::ArrayRangeSelector(range) => get_array_range(range, &mut acc),
129 Token::FlattenOperator => match acc {
130 Value::Array(_) => get_flattened_array(&acc),
131 Value::Object(_) => Ok(get_flattened_object(&acc)),
132 _ => Err(JqlRunnerError::FlattenError(acc)),
133 },
134 Token::KeyOperator => match acc {
135 Value::Array(_) => get_array_as_indexes(&acc),
136 Value::Object(_) => get_object_as_keys(&mut acc),
137 Value::Bool(bool) => Ok(json!(bool)),
139 Value::Number(number) => Ok(json!(number)),
140 Value::String(string) => Ok(json!(string)),
141 Value::Null => Ok(json!(null)),
142 },
143 Token::GroupSeparator => unreachable!(),
144 Token::KeySelector(key) => get_object_key(key, &acc),
145 Token::LensSelector(lenses) => get_array_lenses(lenses, &mut acc),
146 Token::MultiKeySelector(keys) => get_object_multi_key(keys, &mut acc),
147 Token::ObjectIndexSelector(indexes) => get_object_indexes(indexes, &mut acc),
148 Token::ObjectRangeSelector(range) => get_object_range(range, &mut acc),
149 Token::PipeInOperator => {
150 if !acc.is_array() {
151 return Err(JqlRunnerError::PipeInError(acc));
152 }
153
154 piped = true;
155
156 Ok(acc)
157 }
158 Token::PipeOutOperator => {
159 if !piped {
160 return Err(JqlRunnerError::PipeOutError);
161 }
162
163 piped = false;
164
165 Ok(acc)
166 }
167 Token::TruncateOperator => match acc {
168 Value::Array(_) => Ok(json!([])),
169 Value::Object(_) => Ok(json!({})),
170 Value::Bool(_) | Value::Number(_) | Value::String(_) | Value::Null => Ok(acc),
171 },
172 };
173
174 result.map(|value| (value, piped))
175}
176
177#[cfg(test)]
178mod tests {
179 use jql_parser::{
180 errors::JqlParserError,
181 tokens::{
182 Token,
183 View,
184 },
185 };
186 use serde_json::json;
187
188 use super::raw;
189 use crate::errors::JqlRunnerError;
190
191 #[test]
192 fn check_runner_empty_input_error() {
193 assert_eq!(raw("", &json!("")), Err(JqlRunnerError::EmptyQueryError));
194 }
195
196 #[test]
197 fn check_runner_parsing_error() {
198 assert_eq!(
199 raw(r#""a"b"#, &json!({ "a": 1 })),
200 Err(JqlRunnerError::ParsingError(JqlParserError::ParsingError {
201 tokens: [Token::KeySelector("a".into())].stringify(),
202 unparsed: "b".to_string(),
203 }))
204 );
205 }
206
207 #[test]
208 fn check_runner_no_key_found_error() {
209 let parent = json!({ "a": 1 });
210
211 assert_eq!(
212 raw(r#""b""#, &parent),
213 Err(JqlRunnerError::KeyNotFoundError {
214 key: "b".to_string(),
215 parent
216 })
217 );
218 }
219
220 #[test]
221 fn check_runner_index_not_found_error() {
222 let parent = json!(["a"]);
223
224 assert_eq!(
225 raw("[1]", &parent),
226 Err(JqlRunnerError::IndexOutOfBoundsError { index: 1, parent })
227 );
228 }
229
230 #[test]
231 fn check_runner_success() {
232 assert_eq!(
233 raw(r#""a","b""#, &json!({ "a": 1, "b": 2 })),
234 Ok(json!([1, 2]))
235 );
236 assert_eq!(raw(r#""a""b""#, &json!({ "a": { "b": 2 } })), Ok(json!(2)));
237 assert_eq!(
238 raw("[4,2,0]", &json!(["a", "b", "c", "d", "e"])),
239 Ok(json!(["e", "c", "a"]))
240 );
241 }
242
243 #[test]
244 fn check_runner_pipes() {
245 let value = json!({ "a": [{ "b": { "c": 1 } }, { "b": { "c": 2 }}]});
246
247 assert_eq!(raw(r#""a"|>"b""c"<|[1]"#, &value), Ok(json!(2)));
248 }
249
250 #[test]
251 fn check_runner_truncate() {
252 assert_eq!(raw(r#""a"!"#, &json!({ "a": [1, 2, 3] })), Ok(json!([])));
253 assert_eq!(raw(r#""a"!"#, &json!({ "a": { "b": 1 } })), Ok(json!({})));
254 assert_eq!(raw(r#""a"!"#, &json!({ "a": true })), Ok(json!(true)));
255 assert_eq!(raw(r#""a"!"#, &json!({ "a": 1 })), Ok(json!(1)));
256 assert_eq!(raw(r#""a"!"#, &json!({ "a": "b" })), Ok(json!("b")));
257 assert_eq!(raw(r#""a"!"#, &json!({ "a": null })), Ok(json!(null)));
258 assert_eq!(raw("!", &json!({ "a": null })), Ok(json!({})));
259 assert_eq!(
260 raw(r#""a"!"b""#, &json!({ "a": [1, 2, 3] })),
261 Err(JqlRunnerError::ParsingError(JqlParserError::TruncateError(
262 [
263 Token::KeySelector("a".into()),
264 Token::TruncateOperator,
265 Token::KeySelector("b".into())
266 ]
267 .stringify(),
268 )))
269 );
270 }
271
272 #[test]
273 fn check_runner_lens() {
274 let value = json!([
275 { "a": { "b": { "c": 1 }}},
276 { "a": { "b": { "c": 2 }}},
277 ]);
278
279 assert_eq!(
280 raw(r#"|={"a""b""c"=2}"#, &value),
281 Ok(json!([
282 { "a": { "b": { "c": 2 }}}
283 ]))
284 );
285 }
286
287 #[test]
288 fn check_runner_keys() {
289 let value = json!({ "a": { "b": { "c": { "d": 1 }}}});
290
291 assert_eq!(raw(r#""a""b""c"@"#, &value), Ok(json!(["d"])));
292 }
293
294 #[test]
295 fn check_runner_reports_the_first_failing_group() {
296 let parent = json!({ "a": 1 });
299 let expected = Err(JqlRunnerError::KeyNotFoundError {
300 key: "x".to_string(),
301 parent: parent.clone(),
302 });
303
304 for _ in 0..64 {
305 assert_eq!(
306 raw(r#""a","x","a","y","a","z","a","w","a""#, &parent),
307 expected
308 );
309 }
310 }
311}