use crate::val::field_path::{FieldPath, FieldPathPart};
use crate::val::{Object, Value};
impl Value {
pub fn set_at_field_path_owned(&mut self, path: &FieldPath, val: Value) {
self.set_at_field_path_owned_depth(path, val, 0);
}
fn set_at_field_path_owned_depth(&mut self, path: &FieldPath, val: Value, depth: usize) {
if depth >= path.len() {
*self = val;
return;
}
let part = &path.0[depth];
let is_last = depth == path.len() - 1;
match (self, part) {
(Value::Object(obj), FieldPathPart::Field(key) | FieldPathPart::Lookup(key)) => {
if is_last {
obj.insert(key.clone(), val);
} else {
let nested =
obj.entry(key.clone()).or_insert_with(|| Value::Object(Object::default()));
nested.set_at_field_path_owned_depth(path, val, depth + 1);
}
}
(Value::Array(arr), FieldPathPart::Index(i)) if *i < arr.len() => {
if is_last {
arr[*i] = val;
} else {
arr[*i].set_at_field_path_owned_depth(path, val, depth + 1);
}
}
(Value::Array(arr), FieldPathPart::First) if !arr.is_empty() => {
if is_last {
arr[0] = val;
} else {
arr[0].set_at_field_path_owned_depth(path, val, depth + 1);
}
}
(Value::Array(arr), FieldPathPart::Last) if !arr.is_empty() => {
let last_idx = arr.len() - 1;
if is_last {
arr[last_idx] = val;
} else {
arr[last_idx].set_at_field_path_owned_depth(path, val, depth + 1);
}
}
(Value::Set(set), FieldPathPart::Index(i)) if set.nth(*i).is_some() => {
if let Some(elem) = set.nth_mut(*i) {
if is_last {
*elem = val;
} else {
elem.set_at_field_path_owned_depth(path, val, depth + 1);
}
}
}
(Value::Set(set), FieldPathPart::First) if !set.is_empty() => {
if let Some(elem) = set.first_mut() {
if is_last {
*elem = val;
} else {
elem.set_at_field_path_owned_depth(path, val, depth + 1);
}
}
}
(Value::Set(set), FieldPathPart::Last) if !set.is_empty() => {
if let Some(elem) = set.last_mut() {
if is_last {
*elem = val;
} else {
elem.set_at_field_path_owned_depth(path, val, depth + 1);
}
}
}
(Value::Array(arr), FieldPathPart::Field(_) | FieldPathPart::Lookup(_)) => {
if let Some((last, rest)) = arr.split_last_mut() {
for elem in rest {
elem.set_at_field_path_owned_depth(path, val.clone(), depth);
}
last.set_at_field_path_owned_depth(path, val, depth);
}
}
(target, FieldPathPart::Field(key) | FieldPathPart::Lookup(key)) => {
let mut obj = Object::default();
if is_last {
obj.insert(key.clone(), val);
} else {
let mut nested = Value::Object(Object::default());
nested.set_at_field_path_owned_depth(path, val, depth + 1);
obj.insert(key.clone(), nested);
}
*target = Value::Object(obj);
}
_ => {} }
}
}