rulemorph 0.3.4

YAML-based declarative data transformation engine for CSV/JSON to JSON
Documentation
use serde_json::{Map as JsonMap, Value as JsonValue};

use crate::error::TransformError;
use crate::transform::GeneratedObjectBudget;
use crate::v2_model::{V2ObjectFieldValue, V2ObjectStep, object_field_rule_path};

use super::{EvalValue, V2EvalContext, eval_v2_expr};

#[allow(clippy::too_many_arguments)]
pub(crate) fn eval_v2_object_step<'a>(
    object: &V2ObjectStep,
    pipe_value: EvalValue,
    record: &'a JsonValue,
    context: Option<&'a JsonValue>,
    out: &'a JsonValue,
    path: &str,
    ctx: &V2EvalContext<'a>,
) -> Result<EvalValue, TransformError> {
    let limits = ctx.limits();
    limits.check_object_field_count(object.fields.len(), path)?;
    let mut budget = GeneratedObjectBudget::new(limits, path)?;
    let field_ctx = ctx.clone().with_pipe_value(pipe_value);
    let mut output = JsonMap::new();

    for field in &object.fields {
        let field_path = object_field_rule_path(path, &field.key);
        limits.check_object_key(&field.key, &field_path)?;
        let value = match &field.value {
            V2ObjectFieldValue::Expr(expr) => {
                eval_v2_expr(expr, record, context, out, &field_path, &field_ctx)?
            }
            V2ObjectFieldValue::Value(value) => EvalValue::Value(value.clone()),
        };
        if let EvalValue::Value(value) = value {
            budget.try_push_field(&field.key, &value, limits, &field_path)?;
            output.insert(field.key.clone(), value);
        }
    }

    Ok(EvalValue::Value(JsonValue::Object(output)))
}