1use super::types::Segment;
2use crate::error::PickError;
3use serde_json::Value;
4
5pub fn apply_set(
11 value: &Value,
12 segments: &[Segment],
13 new_value: &Value,
14) -> Result<Value, PickError> {
15 if segments.is_empty() {
16 return Ok(new_value.clone());
17 }
18
19 let segment = &segments[0];
20 let rest = &segments[1..];
21
22 if let Some(ref key) = segment.key {
23 match value {
25 Value::Object(map) => {
26 let mut new_map = map.clone();
27 let child = map.get(key).unwrap_or(&Value::Null);
28 let child = apply_set_with_indices(child, &segment.indices, rest, new_value)?;
29 new_map.insert(key.clone(), child);
30 Ok(Value::Object(new_map))
31 }
32 _ => {
34 let mut new_map = serde_json::Map::new();
35 let child =
36 apply_set_with_indices(&Value::Null, &segment.indices, rest, new_value)?;
37 new_map.insert(key.clone(), child);
38 Ok(Value::Object(new_map))
39 }
40 }
41 } else {
42 apply_set_with_indices(value, &segment.indices, rest, new_value)
44 }
45}
46
47fn apply_set_with_indices(
48 value: &Value,
49 indices: &[super::types::Index],
50 remaining_segments: &[Segment],
51 new_value: &Value,
52) -> Result<Value, PickError> {
53 if indices.is_empty() {
54 return apply_set(value, remaining_segments, new_value);
55 }
56
57 let index = &indices[0];
58 let rest_indices = &indices[1..];
59
60 match index {
61 super::types::Index::Number(n) => match value {
62 Value::Array(arr) => {
63 let len = arr.len();
64 let i = resolve_index(*n, len)?;
65 let mut new_arr = arr.clone();
66 if i < len {
67 let child = &arr[i];
68 new_arr[i] =
69 apply_set_with_indices(child, rest_indices, remaining_segments, new_value)?;
70 }
71 Ok(Value::Array(new_arr))
72 }
73 _ => Err(PickError::NotAnArray(
74 super::extract::value_type_name(value).into(),
75 )),
76 },
77 _ => Err(PickError::InvalidSelector(
79 "set() does not support wildcard or slice indices".into(),
80 )),
81 }
82}
83
84pub fn apply_del(value: &Value, segments: &[Segment]) -> Result<Value, PickError> {
89 if segments.is_empty() {
90 return Ok(Value::Null);
92 }
93
94 let segment = &segments[0];
95 let rest = &segments[1..];
96
97 if let Some(ref key) = segment.key {
98 match value {
99 Value::Object(map) => {
100 if rest.is_empty() && segment.indices.is_empty() {
101 let mut new_map = map.clone();
103 new_map.remove(key);
104 Ok(Value::Object(new_map))
105 } else if let Some(child) = map.get(key) {
106 let mut new_map = map.clone();
108 let new_child = apply_del_with_indices(child, &segment.indices, rest)?;
109 new_map.insert(key.clone(), new_child);
110 Ok(Value::Object(new_map))
111 } else {
112 Ok(value.clone())
114 }
115 }
116 _ => Ok(value.clone()), }
118 } else {
119 apply_del_with_indices(value, &segment.indices, rest)
121 }
122}
123
124fn apply_del_with_indices(
125 value: &Value,
126 indices: &[super::types::Index],
127 remaining_segments: &[Segment],
128) -> Result<Value, PickError> {
129 if indices.is_empty() {
130 return apply_del(value, remaining_segments);
131 }
132
133 let index = &indices[0];
134 let rest_indices = &indices[1..];
135
136 match index {
137 super::types::Index::Number(n) => {
138 match value {
139 Value::Array(arr) => {
140 let len = arr.len();
141 let i = resolve_index(*n, len)?;
142 if i >= len {
143 return Ok(value.clone()); }
145
146 if rest_indices.is_empty() && remaining_segments.is_empty() {
147 let mut new_arr = arr.clone();
149 new_arr.remove(i);
150 Ok(Value::Array(new_arr))
151 } else {
152 let mut new_arr = arr.clone();
154 new_arr[i] =
155 apply_del_with_indices(&arr[i], rest_indices, remaining_segments)?;
156 Ok(Value::Array(new_arr))
157 }
158 }
159 _ => Ok(value.clone()), }
161 }
162 _ => Err(PickError::InvalidSelector(
163 "del() does not support wildcard or slice indices".into(),
164 )),
165 }
166}
167
168fn resolve_index(n: i64, len: usize) -> Result<usize, PickError> {
169 if n < 0 {
170 let len_i64 = len as i64;
171 if n.unsigned_abs() > len as u64 {
172 return Err(PickError::IndexOutOfBounds(n));
173 }
174 Ok((len_i64 + n) as usize)
175 } else {
176 Ok(n as usize)
177 }
178}
179
180#[cfg(test)]
181mod tests {
182 use super::*;
183 use crate::selector::types::Selector;
184 use serde_json::json;
185
186 #[test]
189 fn set_top_level_key() {
190 let val = json!({"a": 1, "b": 2});
191 let sel = Selector::parse("a").unwrap();
192 let result = apply_set(&val, &sel.segments, &json!(99)).unwrap();
193 assert_eq!(result, json!({"a": 99, "b": 2}));
194 }
195
196 #[test]
197 fn set_nested_key() {
198 let val = json!({"x": {"y": 1}});
199 let sel = Selector::parse("x.y").unwrap();
200 let result = apply_set(&val, &sel.segments, &json!(2)).unwrap();
201 assert_eq!(result, json!({"x": {"y": 2}}));
202 }
203
204 #[test]
205 fn set_new_key() {
206 let val = json!({"a": 1});
207 let sel = Selector::parse("b").unwrap();
208 let result = apply_set(&val, &sel.segments, &json!(2)).unwrap();
209 assert_eq!(result["a"], json!(1));
210 assert_eq!(result["b"], json!(2));
211 }
212
213 #[test]
214 fn set_deep_new_path() {
215 let val = json!({});
216 let sel = Selector::parse("a.b").unwrap();
217 let result = apply_set(&val, &sel.segments, &json!(1)).unwrap();
218 assert_eq!(result, json!({"a": {"b": 1}}));
219 }
220
221 #[test]
222 fn set_array_element() {
223 let val = json!({"items": [1, 2, 3]});
224 let sel = Selector::parse("items[1]").unwrap();
225 let result = apply_set(&val, &sel.segments, &json!(99)).unwrap();
226 assert_eq!(result, json!({"items": [1, 99, 3]}));
227 }
228
229 #[test]
230 fn set_array_negative_index() {
231 let val = json!({"items": [1, 2, 3]});
232 let sel = Selector::parse("items[-1]").unwrap();
233 let result = apply_set(&val, &sel.segments, &json!(99)).unwrap();
234 assert_eq!(result, json!({"items": [1, 2, 99]}));
235 }
236
237 #[test]
238 fn set_nested_in_array() {
239 let val = json!({"users": [{"name": "Alice"}, {"name": "Bob"}]});
240 let sel = Selector::parse("users[0].name").unwrap();
241 let result = apply_set(&val, &sel.segments, &json!("Charlie")).unwrap();
242 assert_eq!(result["users"][0]["name"], json!("Charlie"));
243 assert_eq!(result["users"][1]["name"], json!("Bob"));
244 }
245
246 #[test]
247 fn set_string_value() {
248 let val = json!({"name": "old"});
249 let sel = Selector::parse("name").unwrap();
250 let result = apply_set(&val, &sel.segments, &json!("new")).unwrap();
251 assert_eq!(result, json!({"name": "new"}));
252 }
253
254 #[test]
255 fn set_null_value() {
256 let val = json!({"x": 1});
257 let sel = Selector::parse("x").unwrap();
258 let result = apply_set(&val, &sel.segments, &json!(null)).unwrap();
259 assert_eq!(result, json!({"x": null}));
260 }
261
262 #[test]
263 fn set_bool_value() {
264 let val = json!({"active": false});
265 let sel = Selector::parse("active").unwrap();
266 let result = apply_set(&val, &sel.segments, &json!(true)).unwrap();
267 assert_eq!(result, json!({"active": true}));
268 }
269
270 #[test]
271 fn set_empty_path_replaces_root() {
272 let val = json!({"a": 1});
273 let result = apply_set(&val, &[], &json!(42)).unwrap();
274 assert_eq!(result, json!(42));
275 }
276
277 #[test]
280 fn del_top_level_key() {
281 let val = json!({"a": 1, "b": 2});
282 let sel = Selector::parse("a").unwrap();
283 let result = apply_del(&val, &sel.segments).unwrap();
284 assert_eq!(result, json!({"b": 2}));
285 }
286
287 #[test]
288 fn del_nested_key() {
289 let val = json!({"x": {"y": 1, "z": 2}});
290 let sel = Selector::parse("x.y").unwrap();
291 let result = apply_del(&val, &sel.segments).unwrap();
292 assert_eq!(result, json!({"x": {"z": 2}}));
293 }
294
295 #[test]
296 fn del_missing_key() {
297 let val = json!({"a": 1});
298 let sel = Selector::parse("missing").unwrap();
299 let result = apply_del(&val, &sel.segments).unwrap();
300 assert_eq!(result, json!({"a": 1}));
301 }
302
303 #[test]
304 fn del_array_element() {
305 let val = json!({"items": [1, 2, 3]});
306 let sel = Selector::parse("items[1]").unwrap();
307 let result = apply_del(&val, &sel.segments).unwrap();
308 assert_eq!(result, json!({"items": [1, 3]}));
309 }
310
311 #[test]
312 fn del_array_first() {
313 let val = json!({"items": [1, 2, 3]});
314 let sel = Selector::parse("items[0]").unwrap();
315 let result = apply_del(&val, &sel.segments).unwrap();
316 assert_eq!(result, json!({"items": [2, 3]}));
317 }
318
319 #[test]
320 fn del_array_last_negative() {
321 let val = json!({"items": [1, 2, 3]});
322 let sel = Selector::parse("items[-1]").unwrap();
323 let result = apply_del(&val, &sel.segments).unwrap();
324 assert_eq!(result, json!({"items": [1, 2]}));
325 }
326
327 #[test]
328 fn del_nested_in_array() {
329 let val = json!({"users": [{"name": "Alice", "temp": "x"}, {"name": "Bob"}]});
330 let sel = Selector::parse("users[0].temp").unwrap();
331 let result = apply_del(&val, &sel.segments).unwrap();
332 assert_eq!(result["users"][0], json!({"name": "Alice"}));
333 assert_eq!(result["users"][1], json!({"name": "Bob"}));
334 }
335
336 #[test]
337 fn del_from_non_object_noop() {
338 let val = json!("hello");
339 let sel = Selector::parse("foo").unwrap();
340 let result = apply_del(&val, &sel.segments).unwrap();
341 assert_eq!(result, json!("hello"));
342 }
343
344 #[test]
345 fn del_empty_path_returns_null() {
346 let val = json!({"a": 1});
347 let result = apply_del(&val, &[]).unwrap();
348 assert_eq!(result, json!(null));
349 }
350
351 #[test]
352 fn del_preserves_other_keys() {
353 let val = json!({"a": 1, "b": 2, "c": 3});
354 let sel = Selector::parse("b").unwrap();
355 let result = apply_del(&val, &sel.segments).unwrap();
356 assert_eq!(result["a"], json!(1));
357 assert_eq!(result["c"], json!(3));
358 assert!(result.get("b").is_none());
359 }
360
361 #[test]
368 fn set_triple_nested_creates_intermediates() {
369 let val = json!({});
370 let sel = Selector::parse("a.b.c").unwrap();
371 let result = apply_set(&val, &sel.segments, &json!(42)).unwrap();
372 assert_eq!(result, json!({"a": {"b": {"c": 42}}}));
373 }
374
375 #[test]
376 fn set_deep_new_path_four_levels() {
377 let val = json!({});
378 let sel = Selector::parse("a.b.c.d").unwrap();
379 let result = apply_set(&val, &sel.segments, &json!("deep")).unwrap();
380 assert_eq!(result["a"]["b"]["c"]["d"], json!("deep"));
381 }
382
383 #[test]
384 fn set_overwrites_non_object_with_object() {
385 let val = json!({"a": "string"});
387 let sel = Selector::parse("a.b").unwrap();
388 let result = apply_set(&val, &sel.segments, &json!(1)).unwrap();
389 assert_eq!(result, json!({"a": {"b": 1}}));
390 }
391
392 #[test]
393 fn set_on_root_number() {
394 let val = json!(42);
395 let sel = Selector::parse("a").unwrap();
396 let result = apply_set(&val, &sel.segments, &json!(1)).unwrap();
397 assert_eq!(result, json!({"a": 1}));
398 }
399
400 #[test]
401 fn set_preserves_sibling_keys() {
402 let val = json!({"x": {"a": 1, "b": 2, "c": 3}});
403 let sel = Selector::parse("x.b").unwrap();
404 let result = apply_set(&val, &sel.segments, &json!(99)).unwrap();
405 assert_eq!(result["x"]["a"], json!(1));
406 assert_eq!(result["x"]["b"], json!(99));
407 assert_eq!(result["x"]["c"], json!(3));
408 }
409
410 #[test]
411 fn set_array_first_element() {
412 let val = json!({"items": [10, 20, 30]});
413 let sel = Selector::parse("items[0]").unwrap();
414 let result = apply_set(&val, &sel.segments, &json!(99)).unwrap();
415 assert_eq!(result, json!({"items": [99, 20, 30]}));
416 }
417
418 #[test]
419 fn set_array_middle_element() {
420 let val = json!([1, 2, 3, 4, 5]);
421 let sel = Selector::parse("[2]").unwrap();
422 let result = apply_set(&val, &sel.segments, &json!(99)).unwrap();
423 assert_eq!(result, json!([1, 2, 99, 4, 5]));
424 }
425
426 #[test]
427 fn set_nested_array_in_object() {
428 let val = json!({"data": {"items": [1, 2, 3]}});
429 let sel = Selector::parse("data.items[1]").unwrap();
430 let result = apply_set(&val, &sel.segments, &json!(99)).unwrap();
431 assert_eq!(result["data"]["items"], json!([1, 99, 3]));
432 }
433
434 #[test]
435 fn set_with_negative_index_middle() {
436 let val = json!([10, 20, 30, 40]);
437 let sel = Selector::parse("[-2]").unwrap();
438 let result = apply_set(&val, &sel.segments, &json!(99)).unwrap();
439 assert_eq!(result, json!([10, 20, 99, 40]));
440 }
441
442 #[test]
443 fn set_wildcard_error() {
444 let val = json!({"items": [1, 2, 3]});
445 let sel = Selector::parse("items[*]").unwrap();
446 assert!(apply_set(&val, &sel.segments, &json!(0)).is_err());
447 }
448
449 #[test]
450 fn set_slice_error() {
451 let val = json!({"items": [1, 2, 3]});
452 let sel = Selector::parse("items[0:2]").unwrap();
453 assert!(apply_set(&val, &sel.segments, &json!(0)).is_err());
454 }
455
456 #[test]
457 fn set_object_value() {
458 let val = json!({"config": {}});
459 let sel = Selector::parse("config.server").unwrap();
460 let result = apply_set(
461 &val,
462 &sel.segments,
463 &json!({"host": "localhost", "port": 8080}),
464 )
465 .unwrap();
466 assert_eq!(result["config"]["server"]["host"], json!("localhost"));
467 }
468
469 #[test]
470 fn set_array_value() {
471 let val = json!({"data": {}});
472 let sel = Selector::parse("data.items").unwrap();
473 let result = apply_set(&val, &sel.segments, &json!([1, 2, 3])).unwrap();
474 assert_eq!(result["data"]["items"], json!([1, 2, 3]));
475 }
476
477 #[test]
480 fn del_deeply_nested_missing_intermediate() {
481 let val = json!({"a": 1});
483 let sel = Selector::parse("a.b.c").unwrap();
484 let result = apply_del(&val, &sel.segments).unwrap();
485 assert_eq!(result, json!({"a": 1}));
487 }
488
489 #[test]
490 fn del_deeply_nested_key() {
491 let val = json!({"a": {"b": {"c": 1, "d": 2}}});
492 let sel = Selector::parse("a.b.c").unwrap();
493 let result = apply_del(&val, &sel.segments).unwrap();
494 assert_eq!(result, json!({"a": {"b": {"d": 2}}}));
495 }
496
497 #[test]
498 fn del_array_last_element() {
499 let val = json!([1, 2, 3]);
500 let sel = Selector::parse("[2]").unwrap();
501 let result = apply_del(&val, &sel.segments).unwrap();
502 assert_eq!(result, json!([1, 2]));
503 }
504
505 #[test]
506 fn del_array_out_of_bounds_noop() {
507 let val = json!({"items": [1, 2, 3]});
509 let sel = Selector::parse("items[10]").unwrap();
510 let result = apply_del(&val, &sel.segments).unwrap();
511 assert_eq!(result, json!({"items": [1, 2, 3]}));
512 }
513
514 #[test]
515 fn del_negative_index_first() {
516 let val = json!([10, 20, 30]);
517 let sel = Selector::parse("[-3]").unwrap();
518 let result = apply_del(&val, &sel.segments).unwrap();
519 assert_eq!(result, json!([20, 30]));
520 }
521
522 #[test]
523 fn del_all_keys_one_by_one() {
524 let val = json!({"a": 1});
525 let sel = Selector::parse("a").unwrap();
526 let result = apply_del(&val, &sel.segments).unwrap();
527 assert_eq!(result, json!({}));
528 }
529
530 #[test]
531 fn del_from_array_non_array_noop() {
532 let val = json!({"items": "not an array"});
533 let sel = Selector::parse("items[0]").unwrap();
534 let result = apply_del(&val, &sel.segments).unwrap();
536 assert_eq!(result["items"], json!("not an array"));
538 }
539
540 #[test]
541 fn del_wildcard_error() {
542 let val = json!({"items": [1, 2, 3]});
543 let sel = Selector::parse("items[*]").unwrap();
544 assert!(apply_del(&val, &sel.segments).is_err());
545 }
546
547 #[test]
548 fn del_slice_error() {
549 let val = json!({"items": [1, 2, 3]});
550 let sel = Selector::parse("items[0:2]").unwrap();
551 assert!(apply_del(&val, &sel.segments).is_err());
552 }
553
554 #[test]
555 fn del_nested_in_array_preserves_siblings() {
556 let val = json!([
557 {"name": "Alice", "age": 30, "temp": "x"},
558 {"name": "Bob", "age": 25}
559 ]);
560 let sel = Selector::parse("[0].temp").unwrap();
561 let result = apply_del(&val, &sel.segments).unwrap();
562 assert_eq!(result[0], json!({"name": "Alice", "age": 30}));
563 assert_eq!(result[1], json!({"name": "Bob", "age": 25}));
564 }
565
566 #[test]
567 fn del_single_element_array() {
568 let val = json!([42]);
569 let sel = Selector::parse("[0]").unwrap();
570 let result = apply_del(&val, &sel.segments).unwrap();
571 assert_eq!(result, json!([]));
572 }
573
574 #[test]
577 fn resolve_positive_index() {
578 assert_eq!(resolve_index(0, 5).unwrap(), 0);
579 assert_eq!(resolve_index(4, 5).unwrap(), 4);
580 }
581
582 #[test]
583 fn resolve_negative_index() {
584 assert_eq!(resolve_index(-1, 5).unwrap(), 4);
585 assert_eq!(resolve_index(-5, 5).unwrap(), 0);
586 }
587
588 #[test]
589 fn resolve_negative_out_of_bounds() {
590 assert!(resolve_index(-6, 5).is_err());
591 }
592}