use super::*;
pub(in crate::transform) fn set_path(
root: &mut JsonValue,
path: &str,
value: JsonValue,
mapping_path: &str,
) -> Result<(), TransformError> {
let tokens = parse_path_tokens(
path,
TransformErrorKind::InvalidTarget,
format!("{}.target", mapping_path),
)?;
if tokens.is_empty() {
return Err(TransformError::new(
TransformErrorKind::InvalidTarget,
"target path is invalid",
)
.with_path(format!("{}.target", mapping_path)));
}
set_path_tokens(root, &tokens, value, mapping_path)
}
pub(in crate::transform) fn set_path_tokens(
root: &mut JsonValue,
tokens: &[PathToken],
value: JsonValue,
mapping_path: &str,
) -> Result<(), TransformError> {
let mut current = root;
for (index, token) in tokens.iter().enumerate() {
let is_last = index == tokens.len() - 1;
let key = match token {
PathToken::Key(key) => key,
PathToken::Index(_) => {
return Err(TransformError::new(
TransformErrorKind::InvalidTarget,
"target path must not include indexes",
)
.with_path(format!("{}.target", mapping_path)));
}
};
match current {
JsonValue::Object(map) => {
if is_last {
map.insert(key.to_string(), value);
return Ok(());
}
let entry = map
.entry(key.to_string())
.or_insert_with(|| JsonValue::Object(Map::new()));
if !entry.is_object() {
return Err(TransformError::new(
TransformErrorKind::InvalidTarget,
"target path conflicts with non-object value",
)
.with_path(format!("{}.target", mapping_path)));
}
current = entry;
}
_ => {
return Err(TransformError::new(
TransformErrorKind::InvalidTarget,
"target root must be an object",
)
.with_path(format!("{}.target", mapping_path)));
}
}
}
Ok(())
}