1use serde_json::Value;
2
3use crate::{Error, apply_stats_operation, print_data_info, string_ops, value_to_string};
4
5pub fn apply_simple_filter(data: Vec<Value>, filter: &str) -> Result<Vec<Value>, Error> {
6 if filter.starts_with("select(") && filter.ends_with(")") {
7 let condition = &filter[7..filter.len() - 1];
9
10 if condition.contains(" | ") {
12 apply_filter_with_string_operations(data, condition)
13 } else {
14 apply_existing_simple_filter(data, condition)
15 }
16 } else {
17 Err(Error::InvalidQuery(format!(
18 "Unsupported filter: {}",
19 filter
20 )))
21 }
22}
23
24fn apply_filter_with_string_operations(
26 data: Vec<Value>,
27 condition: &str,
28) -> Result<Vec<Value>, Error> {
29 let (condition, is_negated) = parse_not_condition_with_parentheses(condition)?;
31
32 let parts: Vec<&str> = condition.split(" | ").map(|s| s.trim()).collect();
33
34 if parts.len() < 2 {
35 return Err(Error::InvalidQuery("Invalid filter condition".to_string()));
36 }
37
38 let field_access = parts[0];
39 let string_operations: Vec<&str> = parts[1..].to_vec();
40
41 let last_operation = string_operations
43 .last()
44 .ok_or_else(|| Error::InvalidQuery("Missing comparison operation".to_string()))?;
45
46 if !is_comparison_operation(last_operation) {
47 return Err(Error::InvalidQuery(
48 "Last operation must be a comparison".to_string(),
49 ));
50 }
51
52 let mut results = Vec::new();
53
54 for item in data {
55 let field_value = extract_field_value(&item, field_access)?;
57
58 let final_value = string_ops::apply_string_pipeline(&field_value, &string_operations)?;
60
61 let condition_result = matches!(final_value, Value::Bool(true));
63 let final_result = if is_negated {
64 !condition_result
65 } else {
66 condition_result
67 };
68
69 if final_result {
70 results.push(item);
71 }
72 }
73
74 Ok(results)
75}
76
77fn is_comparison_operation(operation: &str) -> bool {
79 let trimmed = operation.trim();
80
81 trimmed.starts_with("contains(")
82 || trimmed.starts_with("starts_with(")
83 || trimmed.starts_with("ends_with(")
84 || trimmed == "=="
85 || trimmed == "!="
86 || trimmed.starts_with("== ")
87 || trimmed.starts_with("!= ")
88}
89
90fn apply_existing_simple_filter(data: Vec<Value>, condition: &str) -> Result<Vec<Value>, Error> {
92 let (condition, is_negated) = parse_not_condition_with_parentheses(condition)?;
94
95 let (field_path, operator, value) = parse_condition(&condition)?;
97
98 let filtered: Vec<Value> = data
100 .into_iter()
101 .filter(|item| {
102 let result = evaluate_condition(item, &field_path, &operator, &value);
103 if is_negated { !result } else { result }
104 })
105 .collect();
106
107 Ok(filtered)
108}
109
110fn parse_not_condition_with_parentheses(condition: &str) -> Result<(String, bool), Error> {
111 let trimmed = condition.trim();
112
113 if trimmed.starts_with("not ") {
114 let rest = trimmed[4..].trim();
115
116 if rest.starts_with('(') && rest.ends_with(')') {
118 let inner_condition = rest[1..rest.len() - 1].trim().to_string();
119 Ok((inner_condition, true))
120 } else {
121 Err(Error::InvalidQuery(
122 "not operator requires parentheses around condition: not (.condition)".to_string(),
123 ))
124 }
125 } else {
126 Ok((trimmed.to_string(), false))
127 }
128}
129
130pub fn apply_pipeline_operation(data: Vec<Value>, operation: &str) -> Result<Vec<Value>, Error> {
131 let trimmed_op = operation.trim();
132
133 if operation.starts_with(".[") && operation.ends_with("]") {
134 return apply_universal_slice_operation(data, operation);
135 }
136
137 if trimmed_op.starts_with("select(") && trimmed_op.ends_with(")") {
138 apply_simple_filter(data, trimmed_op)
140 } else if trimmed_op == "count" {
141 if is_grouped_data(&data) {
143 apply_aggregation_to_groups(data, "count", "")
144 } else {
145 let count = data.len();
146 let count_value = Value::Number(serde_json::Number::from(count));
147 Ok(vec![count_value])
148 }
149 } else if trimmed_op.starts_with("map(") && trimmed_op.ends_with(")") {
150 apply_map_operation(data, trimmed_op)
151 } else if trimmed_op.starts_with("select_fields(") && trimmed_op.ends_with(")") {
152 let fields_str = &trimmed_op[14..trimmed_op.len() - 1]; let field_list: Vec<String> = fields_str
155 .split(',')
156 .map(|s| s.trim().to_string())
157 .collect();
158
159 apply_field_selection(data, field_list)
160 } else if trimmed_op == "info" {
161 print_data_info(&data);
163 Ok(vec![]) } else if trimmed_op.starts_with("sum(") && trimmed_op.ends_with(")") {
165 let field = &trimmed_op[4..trimmed_op.len() - 1];
167 let field_name = field.trim_start_matches('.');
168
169 if is_grouped_data(&data) {
170 apply_aggregation_to_groups(data, "sum", field_name)
171 } else {
172 let sum: f64 = data
173 .iter()
174 .filter_map(|item| item.get(field_name))
175 .filter_map(|val| val.as_f64())
176 .sum();
177
178 let round_sum = if sum.fract() == 0.0 {
179 sum
180 } else {
181 (sum * 10.0).round() / 10.0
182 };
183 let sum_value = Value::Number(serde_json::Number::from_f64(round_sum).unwrap());
184 Ok(vec![sum_value])
185 }
186 } else if trimmed_op.starts_with("avg(") && trimmed_op.ends_with(")") {
187 let field = &trimmed_op[4..trimmed_op.len() - 1];
189 let field_name = field.trim_start_matches('.');
190
191 if is_grouped_data(&data) {
192 apply_aggregation_to_groups(data, "avg", field_name)
193 } else {
194 let values: Vec<f64> = data
195 .iter()
196 .filter_map(|item| item.get(field_name))
197 .filter_map(|val| val.as_f64())
198 .collect();
199
200 if values.is_empty() {
201 Ok(vec![Value::Null])
202 } else {
203 let avg = values.iter().sum::<f64>() / values.len() as f64;
204 let round_avg = (avg * 10.0).round() / 10.0;
205 let avg_value = Value::Number(serde_json::Number::from_f64(round_avg).unwrap());
206 Ok(vec![avg_value])
207 }
208 }
209 } else if trimmed_op.starts_with("min(") && trimmed_op.ends_with(")") {
210 let field = &trimmed_op[4..trimmed_op.len() - 1];
212 let field_name = field.trim_start_matches('.');
213
214 if is_grouped_data(&data) {
215 apply_aggregation_to_groups(data, "min", field_name)
216 } else {
217 let min_val = data
218 .iter()
219 .filter_map(|item| item.get(field_name))
220 .filter_map(|val| val.as_f64())
221 .fold(f64::INFINITY, f64::min);
222
223 if min_val == f64::INFINITY {
224 Ok(vec![Value::Null])
225 } else {
226 let min_value = Value::Number(serde_json::Number::from_f64(min_val).unwrap());
227 Ok(vec![min_value])
228 }
229 }
230 } else if trimmed_op.starts_with("max(") && trimmed_op.ends_with(")") {
231 let field = &trimmed_op[4..trimmed_op.len() - 1];
233 let field_name = field.trim_start_matches('.');
234
235 if is_grouped_data(&data) {
236 apply_aggregation_to_groups(data, "max", field_name)
237 } else {
238 let max_val = data
239 .iter()
240 .filter_map(|item| item.get(field_name))
241 .filter_map(|val| val.as_f64())
242 .fold(f64::NEG_INFINITY, f64::max);
243
244 if max_val == f64::NEG_INFINITY {
245 Ok(vec![Value::Null])
246 } else {
247 let max_value = Value::Number(serde_json::Number::from_f64(max_val).unwrap());
248 Ok(vec![max_value])
249 }
250 }
251 } else if trimmed_op.starts_with("group_by(") && trimmed_op.ends_with(")") {
252 let field = &trimmed_op[9..trimmed_op.len() - 1];
254 let field_name = field.trim_start_matches('.');
255
256 let grouped = group_data_by_field(data, field_name)?;
257 Ok(grouped)
258 } else if trimmed_op == "unique" {
259 let result = apply_stats_operation(&data, "unique", None)?;
261 if let Value::Array(arr) = result {
262 Ok(arr)
263 } else {
264 Ok(vec![result])
265 }
266 } else if trimmed_op == "sort" {
267 let result = apply_stats_operation(&data, "sort", None)?;
269 if let Value::Array(arr) = result {
270 Ok(arr)
271 } else {
272 Ok(vec![result])
273 }
274 } else if trimmed_op == "length" {
275 let result = apply_stats_operation(&data, "length", None)?;
277 Ok(vec![result])
278 } else if trimmed_op == "median" {
279 let result = apply_stats_operation(&data, "median", None)?;
281 Ok(vec![result])
282 } else if trimmed_op == "stddev" {
283 let result = apply_stats_operation(&data, "stddev", None)?;
285 Ok(vec![result])
286 } else if trimmed_op.starts_with("unique(") && trimmed_op.ends_with(")") {
287 let field = &trimmed_op[7..trimmed_op.len() - 1];
289 let field_name = field.trim_start_matches('.');
290 let result = apply_stats_operation(&data, "unique", Some(field_name))?;
291 if let Value::Array(arr) = result {
292 Ok(arr)
293 } else {
294 Ok(vec![result])
295 }
296 } else if trimmed_op.starts_with("sort(") && trimmed_op.ends_with(")") {
297 let field = &trimmed_op[5..trimmed_op.len() - 1];
299 let field_name = field.trim_start_matches('.');
300 let result = apply_stats_operation(&data, "sort", Some(field_name))?;
301 if let Value::Array(arr) = result {
302 Ok(arr)
303 } else {
304 Ok(vec![result])
305 }
306 } else if trimmed_op.starts_with("median(") && trimmed_op.ends_with(")") {
307 let field = &trimmed_op[7..trimmed_op.len() - 1];
309 let field_name = field.trim_start_matches('.');
310 let result = apply_stats_operation(&data, "median", Some(field_name))?;
311 Ok(vec![result])
312 } else if trimmed_op.starts_with("stddev(") && trimmed_op.ends_with(")") {
313 let field = &trimmed_op[7..trimmed_op.len() - 1];
315 let field_name = field.trim_start_matches('.');
316 let result = apply_stats_operation(&data, "stddev", Some(field_name))?;
317 Ok(vec![result])
318 } else {
319 Err(Error::InvalidQuery(format!(
321 "Unsupported operation: '{}' (length: {}, starts with 'map(': {}, ends with ')': {})",
322 trimmed_op,
323 trimmed_op.len(),
324 trimmed_op.starts_with("map("),
325 trimmed_op.ends_with(")")
326 )))
327 }
328}
329
330fn apply_map_operation(data: Vec<Value>, operation: &str) -> Result<Vec<Value>, Error> {
332 let content = &operation[4..operation.len() - 1]; if content.contains(',') && content.contains('|') {
337 apply_multi_field_map_operation(data, content)
339 } else {
340 apply_single_field_map_operation(data, content)
342 }
343}
344
345fn apply_single_field_map_operation(data: Vec<Value>, content: &str) -> Result<Vec<Value>, Error> {
347 let (field_access, string_operations) = parse_map_content(content)?;
348
349 let mut results = Vec::new();
350
351 for item in data {
352 let field_value = extract_field_value(&item, &field_access)?;
354
355 let transformed_value = apply_string_operations(&field_value, &string_operations)?;
357
358 let result = update_or_create_value(&item, &field_access, transformed_value)?;
360 results.push(result);
361 }
362
363 Ok(results)
364}
365
366fn apply_multi_field_map_operation(data: Vec<Value>, content: &str) -> Result<Vec<Value>, Error> {
368 let parts: Vec<&str> = content.split('|').map(|s| s.trim()).collect();
370
371 if parts.len() != 2 {
372 return Err(Error::InvalidQuery(
373 "Multi-field map must have format: (.field1, .field2 | operation)".to_string(),
374 ));
375 }
376
377 let fields_part = parts[0].trim();
378 let operation = parts[1].trim();
379
380 let field_paths: Vec<&str> = fields_part.split(',').map(|s| s.trim()).collect();
382
383 for field_path in &field_paths {
385 if !field_path.starts_with('.') {
386 return Err(Error::InvalidQuery(format!(
387 "Field path must start with '.': {}",
388 field_path
389 )));
390 }
391 }
392
393 let mut results = Vec::new();
394
395 for item in data {
396 let transformed_item =
398 crate::string_ops::apply_operation_to_multiple_fields(&item, &field_paths, operation)?;
399 results.push(transformed_item);
400 }
401
402 Ok(results)
403}
404
405fn parse_map_content(content: &str) -> Result<(String, Vec<String>), Error> {
407 let parts: Vec<&str> = content.split('|').map(|s| s.trim()).collect();
408
409 if parts.is_empty() {
410 return Err(Error::InvalidQuery("Empty map operation".to_string()));
411 }
412
413 let field_access = parts[0].to_string();
415
416 let string_operations: Vec<String> = parts[1..].iter().map(|s| s.to_string()).collect();
418
419 Ok((field_access, string_operations))
420}
421
422fn extract_field_value(item: &Value, field_access: &str) -> Result<Value, Error> {
424 if field_access == "." {
425 return Ok(item.clone());
427 }
428
429 if field_access.starts_with('.') {
430 let field_name = &field_access[1..]; if let Some(value) = item.get(field_name) {
433 Ok(value.clone())
434 } else {
435 Err(Error::InvalidQuery(format!(
436 "Field '{}' not found",
437 field_name
438 )))
439 }
440 } else {
441 Err(Error::InvalidQuery(format!(
442 "Invalid field access: {}",
443 field_access
444 )))
445 }
446}
447
448fn apply_string_operations(value: &Value, operations: &[String]) -> Result<Value, Error> {
450 if operations.is_empty() {
451 return Ok(value.clone());
452 }
453
454 let operations_str: Vec<&str> = operations.iter().map(|s| s.as_str()).collect();
455 string_ops::apply_string_pipeline(value, &operations_str)
456}
457
458fn update_or_create_value(
460 original: &Value,
461 field_access: &str,
462 new_value: Value,
463) -> Result<Value, Error> {
464 if field_access == "." {
465 Ok(new_value)
467 } else if field_access.starts_with('.') {
468 let field_name = &field_access[1..];
469
470 if let Value::Object(mut obj) = original.clone() {
472 obj.insert(field_name.to_string(), new_value);
473 Ok(Value::Object(obj))
474 } else {
475 let mut new_obj = serde_json::Map::new();
477 new_obj.insert(field_name.to_string(), new_value);
478 Ok(Value::Object(new_obj))
479 }
480 } else {
481 Err(Error::InvalidQuery(format!(
482 "Invalid field access: {}",
483 field_access
484 )))
485 }
486}
487
488fn apply_field_selection(data: Vec<Value>, field_list: Vec<String>) -> Result<Vec<Value>, Error> {
489 let mut results = Vec::new();
490
491 for item in data {
492 if let Value::Object(obj) = item {
493 let mut selected_obj = serde_json::Map::new();
494
495 for field_name in &field_list {
497 if let Some(value) = obj.get(field_name) {
498 selected_obj.insert(field_name.clone(), value.clone());
499 }
500 }
501
502 results.push(Value::Object(selected_obj));
503 } else {
504 return Err(Error::InvalidQuery(
506 "select_fields can only be applied to objects".into(),
507 ));
508 }
509 }
510
511 Ok(results)
512}
513
514fn group_data_by_field(data: Vec<Value>, field_name: &str) -> Result<Vec<Value>, Error> {
515 use std::collections::HashMap;
516
517 let mut groups: HashMap<String, Vec<Value>> = HashMap::new();
518
519 for item in data {
521 if let Some(field_value) = item.get(field_name) {
522 let key = value_to_string(field_value);
523 groups.entry(key).or_default().push(item);
524 }
525 }
526
527 let result: Vec<Value> = groups
529 .into_iter()
530 .map(|(group_name, group_items)| {
531 let mut group_obj = serde_json::Map::new();
532 group_obj.insert("group".to_string(), Value::String(group_name));
533 group_obj.insert("items".to_string(), Value::Array(group_items));
534 Value::Object(group_obj)
535 })
536 .collect();
537
538 Ok(result)
539}
540
541fn parse_condition(condition: &str) -> Result<(String, String, String), Error> {
542 let condition = condition.trim();
543
544 if let Some(pos) = condition.find(" >= ") {
546 let field = condition[..pos].trim().to_string();
547 let value = condition[pos + 4..].trim().to_string();
548 return Ok((field, ">=".to_string(), value));
549 }
550
551 if let Some(pos) = condition.find(" <= ") {
552 let field = condition[..pos].trim().to_string();
553 let value = condition[pos + 4..].trim().to_string();
554 return Ok((field, "<=".to_string(), value));
555 }
556
557 if let Some(pos) = condition.find(" > ") {
558 let field = condition[..pos].trim().to_string();
559 let value = condition[pos + 3..].trim().to_string();
560 return Ok((field, ">".to_string(), value));
561 }
562
563 if let Some(pos) = condition.find(" < ") {
564 let field = condition[..pos].trim().to_string();
565 let value = condition[pos + 3..].trim().to_string();
566 return Ok((field, "<".to_string(), value));
567 }
568
569 if let Some(pos) = condition.find(" == ") {
570 let field = condition[..pos].trim().to_string();
571 let value = condition[pos + 4..].trim().to_string();
572 return Ok((field, "==".to_string(), value));
573 }
574
575 if let Some(pos) = condition.find(" != ") {
576 let field = condition[..pos].trim().to_string();
577 let value = condition[pos + 4..].trim().to_string();
578 return Ok((field, "!=".to_string(), value));
579 }
580
581 Err(Error::InvalidQuery("Invalid condition format".into()))
582}
583
584fn evaluate_condition(item: &Value, field_path: &str, operator: &str, value: &str) -> bool {
585 let field_name = if field_path.starts_with('.') {
587 &field_path[1..]
588 } else {
589 field_path
590 };
591
592 let field_value = match item.get(field_name) {
593 Some(val) => val,
594 None => return false,
595 };
596
597 match operator {
598 ">" => compare_greater(field_value, value),
599 "<" => compare_less(field_value, value),
600 ">=" => compare_greater_equal(field_value, value),
601 "<=" => compare_less_equal(field_value, value),
602 "==" => compare_equal(field_value, value),
603 "!=" => !compare_equal(field_value, value),
604 _ => false,
605 }
606}
607
608fn compare_greater(field_value: &Value, target: &str) -> bool {
609 match field_value {
610 Value::Number(n) => {
611 if let Ok(target_num) = target.parse::<f64>() {
612 n.as_f64().unwrap_or(0.0) > target_num
613 } else {
614 false
615 }
616 }
617 _ => false,
618 }
619}
620
621fn compare_less(field_value: &Value, target: &str) -> bool {
622 match field_value {
623 Value::Number(n) => {
624 if let Ok(target_num) = target.parse::<f64>() {
625 n.as_f64().unwrap_or(0.0) < target_num
626 } else {
627 false
628 }
629 }
630 _ => false,
631 }
632}
633
634fn compare_equal(field_value: &Value, target: &str) -> bool {
635 match field_value {
636 Value::String(s) => {
637 let target_clean = target.trim_matches('"');
639 s == target_clean
640 }
641 Value::Number(n) => {
642 if let Ok(target_num) = target.parse::<f64>() {
643 n.as_f64().unwrap_or(0.0) == target_num
644 } else {
645 false
646 }
647 }
648 Value::Bool(b) => match target {
649 "true" => *b,
650 "false" => !*b,
651 _ => false,
652 },
653 _ => false,
654 }
655}
656
657fn compare_greater_equal(field_value: &Value, target: &str) -> bool {
658 match field_value {
659 Value::Number(n) => {
660 if let Ok(target_num) = target.parse::<f64>() {
661 n.as_f64().unwrap_or(0.0) >= target_num
662 } else {
663 false
664 }
665 }
666 _ => false,
667 }
668}
669
670fn compare_less_equal(field_value: &Value, target: &str) -> bool {
671 match field_value {
672 Value::Number(n) => {
673 if let Ok(target_num) = target.parse::<f64>() {
674 n.as_f64().unwrap_or(0.0) <= target_num
675 } else {
676 false
677 }
678 }
679 _ => false,
680 }
681}
682
683fn is_grouped_data(data: &[Value]) -> bool {
684 data.iter().all(|item| {
685 if let Value::Object(obj) = item {
686 obj.contains_key("group") && obj.contains_key("items")
687 } else {
688 false
689 }
690 })
691}
692
693fn apply_aggregation_to_groups(
694 data: Vec<Value>,
695 operation: &str,
696 field_name: &str,
697) -> Result<Vec<Value>, Error> {
698 let mut results = Vec::new();
699
700 for group_data in data {
701 if let Value::Object(group_obj) = group_data {
702 let group_name = group_obj.get("group").unwrap();
703 let items = group_obj.get("items").and_then(|v| v.as_array()).unwrap();
704
705 let aggregated_value = match operation {
707 "avg" => calculate_avg(items, field_name)?,
708 "sum" => calculate_sum(items, field_name)?,
709 "count" => Value::Number(serde_json::Number::from(items.len())),
710 "min" => calculate_min(items, field_name)?,
711 "max" => calculate_max(items, field_name)?,
712 _ => Value::Null,
713 };
714
715 let mut result_obj = serde_json::Map::new();
717 result_obj.insert("group".to_string(), group_name.clone());
718 result_obj.insert(operation.to_string(), aggregated_value);
719 results.push(Value::Object(result_obj));
720 }
721 }
722
723 Ok(results)
724}
725
726fn calculate_avg(items: &[Value], field_name: &str) -> Result<Value, Error> {
727 let values: Vec<f64> = items
728 .iter()
729 .filter_map(|item| item.get(field_name))
730 .filter_map(|val| val.as_f64())
731 .collect();
732
733 if values.is_empty() {
734 Ok(Value::Null)
735 } else {
736 let avg = values.iter().sum::<f64>() / values.len() as f64;
737 let rounded_avg = (avg * 10.0).round() / 10.0;
738 Ok(Value::Number(
739 serde_json::Number::from_f64(rounded_avg).unwrap(),
740 ))
741 }
742}
743
744fn calculate_sum(items: &[Value], field_name: &str) -> Result<Value, Error> {
745 let sum: f64 = items
746 .iter()
747 .filter_map(|item| item.get(field_name))
748 .filter_map(|val| val.as_f64())
749 .sum();
750
751 let rounded_sum = if sum.fract() == 0.0 {
752 sum
753 } else {
754 (sum * 10.0).round() / 10.0
755 };
756
757 Ok(Value::Number(
758 serde_json::Number::from_f64(rounded_sum).unwrap(),
759 ))
760}
761
762fn calculate_min(items: &[Value], field_name: &str) -> Result<Value, Error> {
763 let min_val = items
764 .iter()
765 .filter_map(|item| item.get(field_name))
766 .filter_map(|val| val.as_f64())
767 .fold(f64::INFINITY, f64::min);
768
769 if min_val == f64::INFINITY {
770 Ok(Value::Null)
771 } else {
772 Ok(Value::Number(
773 serde_json::Number::from_f64(min_val).unwrap(),
774 ))
775 }
776}
777
778fn calculate_max(items: &[Value], field_name: &str) -> Result<Value, Error> {
779 let max_val = items
780 .iter()
781 .filter_map(|item| item.get(field_name))
782 .filter_map(|val| val.as_f64())
783 .fold(f64::NEG_INFINITY, f64::max);
784
785 if max_val == f64::NEG_INFINITY {
786 Ok(Value::Null)
787 } else {
788 Ok(Value::Number(
789 serde_json::Number::from_f64(max_val).unwrap(),
790 ))
791 }
792}
793
794pub fn apply_array_slice(array: &[Value], start: Option<usize>, end: Option<usize>) -> Vec<Value> {
796 let len = array.len();
797
798 let start_idx = start.unwrap_or(0);
799 let end_idx = end.unwrap_or(len);
800
801 let start_idx = start_idx.min(len);
803 let end_idx = end_idx.min(len);
804
805 if start_idx >= end_idx {
806 return Vec::new(); }
808
809 array[start_idx..end_idx].to_vec()
810}
811
812pub fn apply_slice_to_grouped_data(
814 data: Vec<Value>,
815 start: Option<usize>,
816 end: Option<usize>,
817) -> Result<Vec<Value>, Error> {
818 let mut result = Vec::new();
819
820 for group in data {
821 if let Value::Array(group_items) = group {
822 let sliced_group = apply_array_slice(&group_items, start, end);
824
825 result.extend(sliced_group);
827 } else {
828 result.push(group);
830 }
831 }
832
833 Ok(result)
834}
835
836pub fn parse_slice_notation(
838 bracket_content: &str,
839) -> Result<(Option<usize>, Option<usize>), Error> {
840 if !bracket_content.contains(':') {
841 return Err(Error::InvalidQuery("Not a slice notation".to_string()));
842 }
843
844 let parts: Vec<&str> = bracket_content.split(':').collect();
845 if parts.len() != 2 {
846 return Err(Error::InvalidQuery(
847 "Invalid slice format, expected start:end".to_string(),
848 ));
849 }
850
851 let start = if parts[0].is_empty() {
852 None } else {
854 Some(
855 parts[0]
856 .parse::<usize>()
857 .map_err(|_| Error::InvalidQuery(format!("Invalid start index: {}", parts[0])))?,
858 )
859 };
860
861 let end = if parts[1].is_empty() {
862 None } else {
864 Some(
865 parts[1]
866 .parse::<usize>()
867 .map_err(|_| Error::InvalidQuery(format!("Invalid end index: {}", parts[1])))?,
868 )
869 };
870
871 Ok((start, end))
872}
873
874pub fn parse_slice_notation_with_negative(
876 bracket_content: &str,
877 data_len: usize,
878) -> Result<(Option<usize>, Option<usize>), Error> {
879 let parts: Vec<&str> = bracket_content.split(':').collect();
880 if parts.len() != 2 {
881 return Err(Error::InvalidQuery(
882 "Invalid slice format, expected start:end".to_string(),
883 ));
884 }
885
886 let start = if parts[0].is_empty() {
887 None
888 } else {
889 Some(parse_index_with_negative(parts[0], data_len)?)
890 };
891
892 let end = if parts[1].is_empty() {
893 None
894 } else {
895 Some(parse_index_with_negative(parts[1], data_len)?)
896 };
897
898 Ok((start, end))
899}
900
901pub fn parse_index_with_negative(index_str: &str, data_len: usize) -> Result<usize, Error> {
903 if index_str.starts_with('-') {
904 let negative_index = index_str[1..]
905 .parse::<usize>()
906 .map_err(|_| Error::InvalidQuery(format!("Invalid negative index: {}", index_str)))?;
907
908 if negative_index > data_len {
909 Ok(0) } else {
911 Ok(data_len - negative_index)
912 }
913 } else {
914 index_str
915 .parse::<usize>()
916 .map_err(|_| Error::InvalidQuery(format!("Invalid index: {}", index_str)))
917 }
918}
919
920#[derive(Debug, PartialEq)]
922pub enum DataStructure {
923 GroupedData, RegularArray, NestedArrays, Mixed, }
928
929pub fn detect_data_structure(data: &[Value]) -> DataStructure {
930 if data.is_empty() {
931 return DataStructure::RegularArray;
932 }
933
934 let all_arrays = data.iter().all(|item| item.is_array());
935 let all_objects = data.iter().all(|item| item.is_object());
936 let all_primitives = data.iter().all(|item| {
937 matches!(
938 item,
939 Value::String(_) | Value::Number(_) | Value::Bool(_) | Value::Null
940 )
941 });
942
943 if all_arrays {
944 if is_likely_grouped_data(data) {
946 DataStructure::GroupedData
947 } else {
948 DataStructure::NestedArrays
949 }
950 } else if all_objects || all_primitives {
951 DataStructure::RegularArray
952 } else {
953 DataStructure::Mixed
954 }
955}
956
957pub fn is_likely_grouped_data(data: &[Value]) -> bool {
959 if data.len() < 2 {
965 return false; }
967
968 for item in data {
969 if let Value::Array(arr) = item {
970 if arr.is_empty() {
971 return false;
972 }
973 if !arr[0].is_object() {
974 return false;
975 }
976 } else {
977 return false;
978 }
979 }
980
981 true
982}
983
984pub fn apply_universal_slice_operation(
986 data: Vec<Value>,
987 operation: &str,
988) -> Result<Vec<Value>, Error> {
989 let bracket_content = &operation[2..operation.len() - 1]; if bracket_content.starts_with('-') && !bracket_content.contains(':') {
993 return apply_negative_index_slice(data, bracket_content);
994 }
995
996 if !bracket_content.contains(':') {
998 let index = bracket_content
1000 .parse::<usize>()
1001 .map_err(|_| Error::InvalidQuery(format!("Invalid index: {}", bracket_content)))?;
1002
1003 if let Some(item) = data.get(index) {
1004 return Ok(vec![item.clone()]);
1005 } else {
1006 return Ok(vec![]); }
1008 }
1009
1010 let (start, end) = parse_slice_notation_with_negative(bracket_content, data.len())?;
1012
1013 match detect_data_structure(&data) {
1015 DataStructure::GroupedData => apply_slice_to_grouped_data(data, start, end),
1016 DataStructure::RegularArray => apply_slice_to_regular_array(data, start, end),
1017 DataStructure::NestedArrays => apply_slice_to_nested_arrays(data, start, end),
1018 DataStructure::Mixed => apply_slice_to_regular_array(data, start, end), }
1020}
1021
1022pub fn apply_negative_index_slice(data: Vec<Value>, index_str: &str) -> Result<Vec<Value>, Error> {
1024 let data_len = data.len();
1025 let negative_index = index_str[1..]
1026 .parse::<usize>()
1027 .map_err(|_| Error::InvalidQuery(format!("Invalid negative index: {}", index_str)))?;
1028
1029 if negative_index > data_len || negative_index == 0 {
1030 return Ok(vec![]); }
1032
1033 let actual_index = data_len - negative_index;
1034 if let Some(item) = data.get(actual_index) {
1035 Ok(vec![item.clone()])
1036 } else {
1037 Ok(vec![])
1038 }
1039}
1040
1041pub fn apply_slice_to_regular_array(
1043 data: Vec<Value>,
1044 start: Option<usize>,
1045 end: Option<usize>,
1046) -> Result<Vec<Value>, Error> {
1047 let sliced = apply_array_slice(&data, start, end);
1048 Ok(sliced)
1049}
1050
1051pub fn apply_slice_to_nested_arrays(
1053 data: Vec<Value>,
1054 start: Option<usize>,
1055 end: Option<usize>,
1056) -> Result<Vec<Value>, Error> {
1057 let sliced = apply_array_slice(&data, start, end);
1059 Ok(sliced)
1060}
1061
1062pub fn apply_sort_with_field_operation(
1064 data: Vec<Value>,
1065 operation: &str,
1066) -> Result<Vec<Value>, Error> {
1067 let field_path = &operation[5..operation.len() - 1]; let mut sorted_data = data;
1070 sorted_data.sort_by(|a, b| {
1071 let value_a = extract_sort_key(a, field_path);
1072 let value_b = extract_sort_key(b, field_path);
1073
1074 compare_sort_values(&value_a, &value_b)
1075 });
1076
1077 Ok(sorted_data)
1078}
1079
1080pub fn extract_sort_key(item: &Value, field_path: &str) -> Value {
1082 if field_path.starts_with('.') {
1083 let field_name = &field_path[1..];
1084 item.get(field_name).cloned().unwrap_or(Value::Null)
1085 } else {
1086 item.clone()
1087 }
1088}
1089
1090pub fn compare_sort_values(a: &Value, b: &Value) -> std::cmp::Ordering {
1092 use std::cmp::Ordering;
1093
1094 match (a, b) {
1095 (Value::Number(n1), Value::Number(n2)) => {
1096 let f1 = n1.as_f64().unwrap_or(0.0);
1097 let f2 = n2.as_f64().unwrap_or(0.0);
1098 f1.partial_cmp(&f2).unwrap_or(Ordering::Equal)
1099 }
1100 (Value::String(s1), Value::String(s2)) => s1.cmp(s2),
1101 (Value::Bool(b1), Value::Bool(b2)) => b1.cmp(b2),
1102 (Value::Null, Value::Null) => Ordering::Equal,
1103 (Value::Null, _) => Ordering::Less,
1104 (_, Value::Null) => Ordering::Greater,
1105 _ => Ordering::Equal,
1106 }
1107}
1108
1109#[cfg(test)]
1110mod tests {
1111 use super::*;
1112 use serde_json::json;
1113
1114 #[test]
1115 fn test_apply_array_slice_basic() {
1116 let array = vec![json!("a"), json!("b"), json!("c"), json!("d"), json!("e")];
1117
1118 let result = apply_array_slice(&array, Some(0), Some(3));
1120 assert_eq!(result.len(), 3);
1121 assert_eq!(result[0], json!("a"));
1122 assert_eq!(result[2], json!("c"));
1123
1124 let result = apply_array_slice(&array, Some(1), Some(4));
1126 assert_eq!(result.len(), 3);
1127 assert_eq!(result[0], json!("b"));
1128
1129 let result = apply_array_slice(&array, None, Some(3));
1131 assert_eq!(result.len(), 3);
1132 assert_eq!(result[0], json!("a"));
1133
1134 let result = apply_array_slice(&array, Some(2), None);
1136 assert_eq!(result.len(), 3);
1137 assert_eq!(result[0], json!("c"));
1138
1139 let result = apply_array_slice(&array, Some(10), Some(20));
1141 assert_eq!(result.len(), 0);
1142
1143 let result = apply_array_slice(&array, Some(3), Some(1));
1145 assert_eq!(result.len(), 0);
1146 }
1147
1148 #[test]
1149 fn test_apply_slice_to_grouped_data() {
1150 let grouped_data = vec![
1152 json!([
1153 {"category": "Electronics", "name": "Laptop", "price": 1200},
1154 {"category": "Electronics", "name": "Phone", "price": 800},
1155 {"category": "Electronics", "name": "Tablet", "price": 600},
1156 {"category": "Electronics", "name": "Mouse", "price": 25}
1157 ]),
1158 json!([
1159 {"category": "Books", "name": "Fiction", "price": 20},
1160 {"category": "Books", "name": "Science", "price": 30},
1161 {"category": "Books", "name": "History", "price": 25},
1162 {"category": "Books", "name": "Biography", "price": 35}
1163 ]),
1164 json!([
1165 {"category": "Clothing", "name": "Shirt", "price": 40},
1166 {"category": "Clothing", "name": "Pants", "price": 60},
1167 {"category": "Clothing", "name": "Shoes", "price": 80}
1168 ]),
1169 ];
1170
1171 let result = apply_slice_to_grouped_data(grouped_data.clone(), Some(0), Some(2)).unwrap();
1173
1174 assert_eq!(result.len(), 6);
1176
1177 assert_eq!(result[0].get("name").unwrap(), &json!("Laptop"));
1179 assert_eq!(result[1].get("name").unwrap(), &json!("Phone"));
1180
1181 assert_eq!(result[2].get("name").unwrap(), &json!("Fiction"));
1183 assert_eq!(result[3].get("name").unwrap(), &json!("Science"));
1184
1185 assert_eq!(result[4].get("name").unwrap(), &json!("Shirt"));
1187 assert_eq!(result[5].get("name").unwrap(), &json!("Pants"));
1188 }
1189
1190 #[test]
1191 fn test_apply_slice_to_grouped_data_different_ranges() {
1192 let grouped_data = vec![
1193 json!([
1194 {"id": 1, "group": "A"},
1195 {"id": 2, "group": "A"},
1196 {"id": 3, "group": "A"},
1197 {"id": 4, "group": "A"},
1198 {"id": 5, "group": "A"}
1199 ]),
1200 json!([
1201 {"id": 6, "group": "B"},
1202 {"id": 7, "group": "B"},
1203 {"id": 8, "group": "B"},
1204 {"id": 9, "group": "B"}
1205 ]),
1206 ];
1207
1208 let result = apply_slice_to_grouped_data(grouped_data.clone(), Some(1), Some(4)).unwrap();
1210
1211 assert_eq!(result.len(), 6);
1213
1214 assert_eq!(result[0].get("id").unwrap(), &json!(2));
1216 assert_eq!(result[1].get("id").unwrap(), &json!(3));
1217 assert_eq!(result[2].get("id").unwrap(), &json!(4));
1218
1219 assert_eq!(result[3].get("id").unwrap(), &json!(7));
1221 assert_eq!(result[4].get("id").unwrap(), &json!(8));
1222 assert_eq!(result[5].get("id").unwrap(), &json!(9));
1223 }
1224
1225 #[test]
1226 fn test_parse_slice_notation() {
1227 let (start, end) = parse_slice_notation("0:5").unwrap();
1229 assert_eq!(start, Some(0));
1230 assert_eq!(end, Some(5));
1231
1232 let (start, end) = parse_slice_notation(":5").unwrap();
1234 assert_eq!(start, None);
1235 assert_eq!(end, Some(5));
1236
1237 let (start, end) = parse_slice_notation("2:").unwrap();
1239 assert_eq!(start, Some(2));
1240 assert_eq!(end, None);
1241
1242 let (start, end) = parse_slice_notation(":").unwrap();
1244 assert_eq!(start, None);
1245 assert_eq!(end, None);
1246
1247 assert!(parse_slice_notation("abc:def").is_err());
1249 assert!(parse_slice_notation("0:5:10").is_err());
1250 }
1251
1252 #[test]
1253 fn test_parse_index_with_negative() {
1254 assert_eq!(parse_index_with_negative("5", 10).unwrap(), 5);
1256
1257 assert_eq!(parse_index_with_negative("-1", 10).unwrap(), 9);
1259 assert_eq!(parse_index_with_negative("-3", 10).unwrap(), 7);
1260
1261 assert_eq!(parse_index_with_negative("-15", 10).unwrap(), 0);
1263
1264 assert!(parse_index_with_negative("abc", 10).is_err());
1266 assert!(parse_index_with_negative("-abc", 10).is_err());
1267 }
1268
1269 #[test]
1270 fn test_detect_data_structure() {
1271 let regular = vec![json!({"id": 1}), json!({"id": 2})];
1273 assert_eq!(detect_data_structure(®ular), DataStructure::RegularArray);
1274
1275 let grouped = vec![
1277 json!([{"cat": "A", "val": 1}, {"cat": "A", "val": 2}]),
1278 json!([{"cat": "B", "val": 3}, {"cat": "B", "val": 4}]),
1279 ];
1280 assert_eq!(detect_data_structure(&grouped), DataStructure::GroupedData);
1281
1282 let primitives = vec![json!(1), json!(2), json!(3)];
1284 assert_eq!(
1285 detect_data_structure(&primitives),
1286 DataStructure::RegularArray
1287 );
1288
1289 let empty: Vec<Value> = vec![];
1291 assert_eq!(detect_data_structure(&empty), DataStructure::RegularArray);
1292 }
1293
1294 #[test]
1295 fn test_apply_sort_with_field_operation() {
1296 let data = vec![
1297 json!({"name": "Alice", "score": 85}),
1298 json!({"name": "Bob", "score": 92}),
1299 json!({"name": "Carol", "score": 78}),
1300 ];
1301
1302 let result = apply_sort_with_field_operation(data, "sort(.score)").unwrap();
1303
1304 assert_eq!(result[0].get("score").unwrap(), &json!(78)); assert_eq!(result[1].get("score").unwrap(), &json!(85)); assert_eq!(result[2].get("score").unwrap(), &json!(92)); }
1309
1310 #[test]
1311 fn test_apply_negative_index_slice() {
1312 let data = vec![json!("a"), json!("b"), json!("c"), json!("d"), json!("e")];
1313
1314 let result = apply_negative_index_slice(data.clone(), "-1").unwrap();
1316 assert_eq!(result.len(), 1);
1317 assert_eq!(result[0], json!("e"));
1318
1319 let result = apply_negative_index_slice(data.clone(), "-3").unwrap();
1321 assert_eq!(result.len(), 1);
1322 assert_eq!(result[0], json!("c"));
1323
1324 let result = apply_negative_index_slice(data.clone(), "-10").unwrap();
1326 assert_eq!(result.len(), 0);
1327 }
1328}