1use serde_json::Value;
2
3use crate::{
4 Error, OutputFormat, apply_pipeline_operation, format_output, parse_array_segment,
5 parse_query_segments, value_to_string,
6};
7
8pub fn execute_query(json: &Value, query: &str, format: OutputFormat) -> Result<(), Error> {
9 if query.contains('|') {
10 let parts = split_pipeline_respecting_parentheses(query)?;
13
14 if parts.len() < 2 {
15 return Err(Error::InvalidQuery("Invalid pipeline syntax".into()));
16 }
17
18 let initial_query = parts[0].clone();
21 let mut current_data = execute_basic_query_as_json(json, &initial_query)?;
22
23 for operation in &parts[1..] {
26 current_data = apply_pipeline_operation(current_data, operation)?;
27 }
28
29 format_output(¤t_data, format)?;
32 } else {
33 let result_data = execute_basic_query_as_json(json, query)?;
34 format_output(&result_data, format)?;
35 }
36
37 Ok(())
38}
39
40pub fn execute_basic_query(json: &Value, query: &str) -> Result<Vec<String>, Error> {
41 let (segment, fields) = parse_query_segments(query)?;
42
43 if segment.contains('[') && segment.contains(']') {
44 let (idx, ridx) = parse_array_segment(segment)?; let key = segment
47 .get(..idx)
48 .ok_or(Error::InvalidQuery("Invalid segment format".into()))?;
49 let index_str = segment
50 .get(idx + 1..ridx)
51 .ok_or(Error::InvalidQuery("Invalid bracket content".into()))?;
52
53 if index_str.is_empty() {
54 let result = handle_array_access(json, key, fields)?;
55 Ok(result)
56 } else {
57 let index = index_str.parse::<usize>().map_err(Error::StrToInt)?;
58 let result = handle_single_access(json, key, index, fields)?;
59 Ok(result)
60 }
61 } else {
62 let key = segment;
63 let result = handle_array_access(json, key, fields)?;
64 Ok(result)
65 }
66}
67
68pub fn execute_basic_query_as_json(json: &Value, query: &str) -> Result<Vec<Value>, Error> {
69 let (segment, fields) = parse_query_segments(query)?;
70
71 if segment.is_empty() && fields.is_empty() {
72 if let Value::Array(arr) = json {
73 return Ok(arr.clone());
74 } else {
75 return Ok(vec![json.clone()]);
76 }
77 }
78
79 if segment.is_empty() && !fields.is_empty() {
81 let first_field = fields[0];
82
83 if first_field.starts_with('[') && first_field.ends_with(']') {
84 let bracket_content = &first_field[1..first_field.len() - 1];
85
86 if bracket_content.is_empty() {
88 if let Value::Array(arr) = json {
89 if fields.len() > 1 {
90 let remaining_fields = fields[1..].to_vec();
91 let mut results = Vec::new();
92
93 for item in arr {
94 if let Ok(mut item_results) =
95 handle_nested_field_access(item, remaining_fields.clone())
96 {
97 results.append(&mut item_results);
98 }
99 }
100 return Ok(results);
101 } else {
102 return Ok(arr.clone());
103 }
104 } else {
105 return Err(Error::InvalidQuery(
106 "Cannot iterate over non-array value".into(),
107 ));
108 }
109 } else {
110 let index = bracket_content
112 .parse::<usize>()
113 .map_err(Error::StrToInt)?;
114
115 if let Value::Array(arr) = json {
116 let item = arr.get(index).ok_or(Error::IndexOutOfBounds(index))?;
117
118 if fields.len() > 1 {
119 let remaining_fields = fields[1..].to_vec();
120 return handle_nested_field_access(item, remaining_fields);
121 } else {
122 return Ok(vec![item.clone()]);
123 }
124 } else {
125 return Err(Error::InvalidQuery("Cannot index non-array value".into()));
126 }
127 }
128 }
129 }
130
131 if segment.contains('[') && segment.contains(']') {
133 let (idx, ridx) = parse_array_segment(segment)?;
134 let key = segment
135 .get(..idx)
136 .ok_or(Error::InvalidQuery("Invalid segment format".into()))?;
137 let bracket_content = segment
138 .get(idx + 1..ridx)
139 .ok_or(Error::InvalidQuery("Invalid bracket content".into()))?;
140
141 if bracket_content.is_empty() {
142 let result = handle_array_access_as_json(json, key, fields)?;
143 Ok(result)
144 } else {
145 let index = bracket_content
146 .parse::<usize>()
147 .map_err(Error::StrToInt)?;
148
149 let result = handle_single_access_as_json(json, key, index, fields)?;
151 if let Value::Array(arr) = result {
152 Ok(arr) } else {
154 Ok(vec![result]) }
156 }
157 } else {
158 let result = handle_array_access_as_json(json, segment, fields)?;
160 Ok(result)
161 }
162}
163
164pub fn handle_nested_field_access(json: &Value, fields: Vec<&str>) -> Result<Vec<Value>, Error> {
165 if fields.is_empty() {
170 return Ok(vec![json.clone()]);
171 }
172
173 let field = fields[0];
174 let remaining_fields = if fields.len() > 1 {
177 fields[1..].to_vec()
178 } else {
179 vec![]
180 };
181
182 if field.contains('[') && field.contains(']') {
186 let (idx, ridx) = parse_array_segment(field)?;
188 let key = &field[..idx];
189 let bracket_content = &field[idx + 1..ridx];
190
191 if let Some(array_or_object) = json.get(key) {
194 if bracket_content.is_empty() {
195 if let Value::Array(arr) = array_or_object {
197 if remaining_fields.is_empty() {
198 Ok(arr.clone())
200 } else {
201 let mut all_results = Vec::new();
203 for item in arr {
204 if let Ok(mut item_results) =
206 handle_nested_field_access(item, remaining_fields.clone())
207 {
208 all_results.append(&mut item_results);
210 }
211 }
212 Ok(all_results)
214 }
215 } else {
216 Err(Error::InvalidQuery(
217 format!("Cannot iterate over non-array field '{}'", key),
218 ))
219 }
220 } else {
221 let index = bracket_content.parse::<usize>().map_err(|e| {
223 Error::InvalidQuery(
224 format!("Invalid array index '{}': {}", bracket_content, e),
225 )
226 })?;
227
228 if let Value::Array(arr) = array_or_object {
229 if let Some(item) = arr.get(index) {
230 if remaining_fields.is_empty() {
231 Ok(vec![item.clone()])
232 } else {
233 handle_nested_field_access(item, remaining_fields)
234 }
235 } else {
236 Err(Error::IndexOutOfBounds(index))
237 }
238 } else {
239 Err(Error::InvalidQuery(
240 format!("Cannot index non-array field '{}'", key),
241 ))
242 }
243 }
244 } else {
245 Err(Error::InvalidQuery(
246 format!("Field '{}' not found", key),
247 ))
248 }
249 } else {
250 if let Some(value) = json.get(field) {
253 if remaining_fields.is_empty() {
255 Ok(vec![value.clone()])
256 } else {
257 handle_nested_field_access(value, remaining_fields)
259 }
260 } else {
261 Err(Error::InvalidQuery(
262 format!("Field '{}' not found", field),
263 ))
264 }
265 }
266}
267
268pub fn handle_single_access_as_json(
269 json: &Value,
270 key: &str,
271 index: usize,
272 fields: Vec<&str>,
273) -> Result<Value, Error> {
274 let values = json
278 .get(key)
279 .ok_or(Error::InvalidQuery(format!("Key '{}' not found", key)))?;
280 let mut current = values.get(index).ok_or(Error::IndexOutOfBounds(index))?;
281
282 for (field_idx, field) in fields.iter().enumerate() {
283 if field.contains('[') && field.contains(']') {
286 let (idx, ridx) = parse_array_segment(field)?;
288 let field_key = field
289 .get(..idx)
290 .ok_or(Error::InvalidQuery("Invalid field".into()))?;
291 let index_str = field
292 .get(idx + 1..ridx)
293 .ok_or(Error::InvalidQuery("Invalid bracket content".into()))?;
294
295 let array = current.get(field_key).ok_or(Error::InvalidQuery(format!(
299 "Field '{}' not found",
300 field_key
301 )))?;
302
303 if index_str.is_empty() {
304 if let Value::Array(arr) = array {
306 let remaining_fields = if field_idx + 1 < fields.len() {
308 fields[field_idx + 1..].to_vec()
309 } else {
310 vec![]
311 };
312
313 if remaining_fields.is_empty() {
319 return Ok(Value::Array(arr.clone()));
321 } else {
322 let mut expanded_results = Vec::new();
324 for item in arr {
325 if let Ok(mut item_results) =
327 handle_nested_field_access(item, remaining_fields.clone())
328 {
329 expanded_results.append(&mut item_results);
330 }
331 }
332 return Ok(Value::Array(expanded_results));
333 }
334 } else {
335 return Err(Error::InvalidQuery(
336 format!("Field '{}' is not an array", field_key),
337 ));
338 }
339 } else {
340 let field_index = index_str.parse::<usize>().map_err(Error::StrToInt)?;
342 current = array
343 .get(field_index)
344 .ok_or(Error::IndexOutOfBounds(field_index))?;
345 }
346 } else {
347 current = current
350 .get(field)
351 .ok_or(Error::InvalidQuery(format!("Field '{}' not found", field)))?;
352 }
353 }
354
355 Ok(current.clone())
356}
357
358pub fn handle_array_access_as_json(
359 json: &Value,
360 key: &str,
361 fields: Vec<&str>,
362) -> Result<Vec<Value>, Error> {
363 let values = json
364 .get(key)
365 .ok_or(Error::InvalidQuery(format!("Key '{}' not found", key)))?;
366 let values_arr = values
367 .as_array()
368 .ok_or(Error::InvalidQuery("Expected array".into()))?;
369
370 let res: Vec<Value> = values_arr
371 .iter()
372 .filter_map(|array_item| {
373 let mut current = array_item;
375
376 for field in &fields {
377 if field.contains('[') && field.contains(']') {
378 if let Ok((idx, ridx)) = parse_array_segment(field) {
380 if let Some(field_key) = field.get(..idx) {
381 if let Some(index_str) = field.get(idx + 1..ridx) {
382 if let Ok(field_index) = index_str.parse::<usize>() {
383 if let Some(array) = current.get(field_key) {
384 if let Some(item) = array.get(field_index) {
385 current = item;
386 continue;
387 }
388 }
389 }
390 }
391 }
392 }
393 return None;
395 } else {
396 if let Some(next) = current.get(field) {
398 current = next;
399 } else {
400 return None;
402 }
403 }
404 }
405
406 Some(current.clone())
408 })
409 .collect();
410
411 Ok(res)
412}
413
414pub fn handle_single_access(
415 json: &Value,
416 key: &str,
417 index: usize,
418 fields: Vec<&str>,
419) -> Result<Vec<String>, Error> {
420 let values = json
423 .get(key)
424 .ok_or(Error::InvalidQuery(format!("Key '{}' not found", key)))?;
425 let mut current = values.get(index).ok_or(Error::IndexOutOfBounds(index))?;
426
427 for field in fields {
430 if field.contains('[') && field.contains(']') {
431 let (idx, ridx) = parse_array_segment(field)?;
434 let field_key = field
435 .get(..idx)
436 .ok_or(Error::InvalidQuery("Invalid field".into()))?;
437 let index_str = field
438 .get(idx + 1..ridx)
439 .ok_or(Error::InvalidQuery("Invalid bracket content".into()))?;
440 let field_index = index_str.parse::<usize>().map_err(Error::StrToInt)?;
441
442 let array = current.get(field_key).ok_or(Error::InvalidQuery(format!(
445 "Field '{}' not found",
446 field_key
447 )))?;
448 current = array
449 .get(field_index)
450 .ok_or(Error::IndexOutOfBounds(field_index))?;
451 } else {
452 current = current
454 .get(field)
455 .ok_or(Error::InvalidQuery(format!("Field '{}' not found", field)))?;
456 }
457 }
458
459 Ok(vec![value_to_string(current)])
460}
461
462pub fn handle_array_access(
463 json: &Value,
464 key: &str,
465 fields: Vec<&str>,
466) -> Result<Vec<String>, Error> {
467 let values = json
468 .get(key)
469 .ok_or(Error::InvalidQuery(format!("Key '{}' not found", key)))?;
470 let values_arr = values
471 .as_array()
472 .ok_or(Error::InvalidQuery("Expected array".into()))?;
473
474 let res: Vec<String> = values_arr
475 .iter()
476 .filter_map(|array_item| {
477 let mut current = array_item;
480
481 for field in &fields {
482 if field.contains('[') && field.contains(']') {
483 if let Ok((idx, ridx)) = parse_array_segment(field) {
486 if let Some(field_key) = field.get(..idx) {
487 if let Some(index_str) = field.get(idx + 1..ridx) {
488 if let Ok(field_index) = index_str.parse::<usize>() {
489 if let Some(array) = current.get(field_key) {
490 if let Some(item) = array.get(field_index) {
491 current = item;
492 continue;
493 }
494 }
495 }
496 }
497 }
498 }
499 return None;
502 } else {
503 if let Some(next) = current.get(field) {
506 current = next;
507 } else {
508 return None;
511 }
512 }
513 }
514
515 Some(value_to_string(current))
516 })
517 .collect();
518
519 Ok(res)
520}
521
522fn split_pipeline_respecting_parentheses(query: &str) -> Result<Vec<String>, Error> {
523
524 let mut parts = Vec::new();
525 let mut current_part = String::new();
526 let mut paren_depth = 0;
527 let chars = query.chars().peekable();
528
529 for ch in chars {
530 match ch {
531 '(' => {
532 paren_depth += 1;
533 current_part.push(ch);
534 },
535 ')' => {
536 paren_depth -= 1;
537 current_part.push(ch);
538 },
539 '|' if paren_depth == 0 => {
540 if !current_part.trim().is_empty() {
542 parts.push(current_part.trim().to_string());
543 current_part.clear();
544 }
545 },
546 _ => {
547 current_part.push(ch);
548 }
549 }
550 }
551
552 if !current_part.trim().is_empty() {
554 parts.push(current_part.trim().to_string());
555 }
556
557 if paren_depth != 0 {
558 return Err(Error::InvalidQuery("Unmatched parentheses in query".to_string()));
559 }
560
561 Ok(parts)
562}
563
564
565#[cfg(test)]
566mod tests {
567 use super::*;
568 use serde_json::{Value, json};
569
570 fn create_test_json() -> Value {
571 json!({
572 "users": [
573 {"name": "Alice", "age": 30, "active": true},
574 {"name": "Bob", "age": 25, "active": false},
575 {"name": "Carol", "age": 35}
576 ],
577 "products": [
578 {"title": "Laptop", "price": 1200},
579 {"title": "Mouse", "price": 25}
580 ],
581 "empty_array": [],
582 "not_array": "string_value"
583 })
584 }
585
586 #[test]
587 fn test_handle_array_access_normal_case() {
588 let json = create_test_json();
590 let result = handle_array_access(&json, "users", vec!["name"]);
591
592 assert!(result.is_ok());
593 let names = result.unwrap();
594 assert_eq!(names, vec!["Alice", "Bob", "Carol"]);
595 }
596
597 #[test]
598 fn test_handle_array_access_with_missing_field() {
599 let json = create_test_json();
601 let result = handle_array_access(&json, "users", vec!["active"]);
602
603 assert!(result.is_ok());
604 let actives = result.unwrap();
605 assert_eq!(actives, vec!["true", "false"]); }
607
608 #[test]
609 fn test_handle_array_access_different_types() {
610 let json = create_test_json();
612 let result = handle_array_access(&json, "users", vec!["age"]);
613
614 assert!(result.is_ok());
615 let ages = result.unwrap();
616 assert_eq!(ages, vec!["30", "25", "35"]);
617 }
618
619 #[test]
620 fn test_handle_array_access_empty_array() {
621 let json = create_test_json();
623 let result = handle_array_access(&json, "empty_array", vec!["name"]);
624
625 assert!(result.is_ok());
626 let names = result.unwrap();
627 assert!(names.is_empty());
628 }
629
630 #[test]
631 fn test_handle_array_access_key_not_found() {
632 let json = create_test_json();
634 let result = handle_array_access(&json, "nonexistent", vec!["name"]);
635
636 assert!(result.is_err());
637 match result.unwrap_err() {
638 Error::InvalidQuery(msg) => {
639 assert!(msg.contains("Key 'nonexistent' not found"));
640 }
641 _ => panic!("Expected InvalidQuery error"),
642 }
643 }
644
645 #[test]
646 fn test_handle_array_access_not_array() {
647 let json = create_test_json();
649 let result = handle_array_access(&json, "not_array", vec!["name"]);
650
651 assert!(result.is_err());
652 match result.unwrap_err() {
653 Error::InvalidQuery(msg) => {
654 assert!(msg.contains("Expected array"));
655 }
656 _ => panic!("Expected InvalidQuery error"),
657 }
658 }
659
660 #[test]
661 fn test_handle_array_access_field_not_in_any_element() {
662 let json = create_test_json();
664 let result = handle_array_access(&json, "users", vec!["nonexistent_field"]);
665
666 assert!(result.is_ok());
667 let values = result.unwrap();
668 assert!(values.is_empty()); }
670
671 #[test]
672 fn test_handle_single_access_normal_case() {
673 let json = create_test_json();
675 let result = handle_single_access(&json, "users", 0, vec!["name"]);
676
677 assert!(result.is_ok());
678 let names = result.unwrap();
679 assert_eq!(names, vec!["Alice"]);
680 }
681
682 #[test]
683 fn test_handle_single_access_different_index() {
684 let json = create_test_json();
686 let result = handle_single_access(&json, "users", 1, vec!["name"]);
687
688 assert!(result.is_ok());
689 let names = result.unwrap();
690 assert_eq!(names, vec!["Bob"]);
691 }
692
693 #[test]
694 fn test_handle_single_access_different_field() {
695 let json = create_test_json();
697 let result = handle_single_access(&json, "users", 0, vec!["age"]);
698
699 assert!(result.is_ok());
700 let ages = result.unwrap();
701 assert_eq!(ages, vec!["30"]);
702 }
703
704 #[test]
705 fn test_handle_single_access_boolean_field() {
706 let json = create_test_json();
708 let result = handle_single_access(&json, "users", 0, vec!["active"]);
709
710 assert!(result.is_ok());
711 let actives = result.unwrap();
712 assert_eq!(actives, vec!["true"]);
713 }
714
715 #[test]
716 fn test_handle_single_access_key_not_found() {
717 let json = create_test_json();
719 let result = handle_single_access(&json, "nonexistent", 0, vec!["name"]);
720
721 assert!(result.is_err());
722 match result.unwrap_err() {
723 Error::InvalidQuery(msg) => {
724 assert!(msg.contains("Key 'nonexistent' not found"));
725 }
726 _ => panic!("Expected InvalidQuery error"),
727 }
728 }
729
730 #[test]
731 fn test_handle_single_access_index_out_of_bounds() {
732 let json = create_test_json();
734 let result = handle_single_access(&json, "users", 999, vec!["name"]);
735
736 assert!(result.is_err());
737 match result.unwrap_err() {
738 Error::IndexOutOfBounds(index) => {
739 assert_eq!(index, 999);
740 }
741 _ => panic!("Expected IndexOutOfBounds error"),
742 }
743 }
744
745 #[test]
746 fn test_handle_single_access_field_not_found() {
747 let json = create_test_json();
749 let result = handle_single_access(&json, "users", 0, vec!["nonexistent_field"]);
750
751 assert!(result.is_err());
752 match result.unwrap_err() {
753 Error::InvalidQuery(msg) => {
754 assert!(msg.contains("Field 'nonexistent_field' not found"));
755 }
756 _ => panic!("Expected InvalidQuery error"),
757 }
758 }
759
760 #[test]
761 fn test_handle_single_access_not_array() {
762 let json = create_test_json();
764 let result = handle_single_access(&json, "not_array", 0, vec!["name"]);
765
766 assert!(result.is_err());
767 match result.unwrap_err() {
768 Error::IndexOutOfBounds(_) => {
769 }
771 _ => panic!("Expected IndexOutOfBounds error"),
772 }
773 }
774
775 #[test]
776 fn test_handle_single_access_empty_array() {
777 let json = create_test_json();
779 let result = handle_single_access(&json, "empty_array", 0, vec!["name"]);
780
781 assert!(result.is_err());
782 match result.unwrap_err() {
783 Error::IndexOutOfBounds(index) => {
784 assert_eq!(index, 0);
785 }
786 _ => panic!("Expected IndexOutOfBounds error"),
787 }
788 }
789
790 fn create_nested_test_json() -> Value {
791 json!({
792 "users": [
793 {
794 "name": "Alice",
795 "age": 30,
796 "address": {"city": "Tokyo", "country": "Japan"},
797 "projects": [
798 {"name": "Project A", "status": "active"},
799 {"name": "Project B", "status": "completed"}
800 ]
801 },
802 {
803 "name": "Bob",
804 "age": 25,
805 "address": {"city": "Osaka", "country": "Japan"},
806 "projects": [
807 {"name": "Project C", "status": "planning"}
808 ]
809 }
810 ]
811 })
812 }
813
814 #[test]
815 fn test_handle_single_access_simple() {
816 let json = create_nested_test_json();
817 let result = handle_single_access(&json, "users", 0, vec!["name"]);
818 assert!(result.is_ok());
819 assert_eq!(result.unwrap(), vec!["Alice"]);
820 }
821
822 #[test]
823 fn test_handle_single_access_nested_object() {
824 let json = create_nested_test_json();
825 let result = handle_single_access(&json, "users", 0, vec!["address", "city"]);
826 assert!(result.is_ok());
827 assert_eq!(result.unwrap(), vec!["Tokyo"]);
828 }
829
830 #[test]
831 fn test_handle_single_access_nested_array() {
832 let json = create_nested_test_json();
833 let result = handle_single_access(&json, "users", 0, vec!["projects[0]", "name"]);
834 assert!(result.is_ok());
835 assert_eq!(result.unwrap(), vec!["Project A"]);
836 }
837
838 #[test]
839 fn test_handle_single_access_deep_nesting() {
840 let json = create_nested_test_json();
841 let result = handle_single_access(&json, "users", 1, vec!["projects[0]", "status"]);
842 assert!(result.is_ok());
843 assert_eq!(result.unwrap(), vec!["planning"]);
844 }
845
846 #[test]
847 fn test_handle_single_access_nested_array_out_of_bounds() {
848 let json = create_nested_test_json();
849 let result = handle_single_access(&json, "users", 0, vec!["projects[999]", "name"]);
850 assert!(result.is_err());
851 }
852
853 #[test]
854 fn test_handle_array_access_simple() {
855 let json = create_nested_test_json();
856 let result = handle_array_access(&json, "users", vec!["name"]);
857 assert!(result.is_ok());
858 assert_eq!(result.unwrap(), vec!["Alice", "Bob"]);
859 }
860
861 #[test]
862 fn test_handle_array_access_nested_object() {
863 let json = create_nested_test_json();
864 let result = handle_array_access(&json, "users", vec!["address", "city"]);
865 assert!(result.is_ok());
866 assert_eq!(result.unwrap(), vec!["Tokyo", "Osaka"]);
867 }
868
869 #[test]
870 fn test_handle_array_access_nested_array() {
871 let json = create_nested_test_json();
872 let result = handle_array_access(&json, "users", vec!["projects[0]", "name"]);
873 assert!(result.is_ok());
874 assert_eq!(result.unwrap(), vec!["Project A", "Project C"]);
875 }
876
877 #[test]
878 fn test_handle_array_access_partial_data() {
879 let json = json!({
881 "items": [
882 {"details": {"name": "Item1"}},
883 {"other": "data"}, {"details": {"name": "Item3"}}
885 ]
886 });
887 let result = handle_array_access(&json, "items", vec!["details", "name"]);
888 assert!(result.is_ok());
889 assert_eq!(result.unwrap(), vec!["Item1", "Item3"]); }
891}