graphddb_runtime 0.7.5

Rust runtime for GraphDDB — interprets the language-neutral IR (manifest.json + operations.json) and executes the validated access patterns against DynamoDB.
Documentation
//! Bridging composed `TransactWriteItem`s to the W3 `PersistItemCtx` seam.
//!
//! The transaction persist path (W3) exposes each composed item's mutable
//! expression fields to a `write.persist.before` hook, then applies the (possibly
//! mutated) fields back onto the item — the byte-for-byte analogue of the PHP
//! php-filter mutation that strips a compiled `ConditionExpression` (and its `#f*` /
//! `:vf*` aliases) off each item on the wire. [`to_item_ctx`] extracts the seam
//! view; [`apply_item_ctx`] rebuilds the item from it.

use aws_sdk_dynamodb::types::{ConditionCheck, Delete, Put, TransactWriteItem, Update};

use crate::middleware::PersistItemCtx;

/// Extract the W3 seam view (`op_kind` + expression fields) from a composed
/// `TransactWriteItem`.
pub fn to_item_ctx(item: &TransactWriteItem) -> PersistItemCtx {
    if let Some(put) = item.put() {
        return PersistItemCtx::new(
            "Put",
            put.condition_expression().map(str::to_string),
            put.expression_attribute_names()
                .cloned()
                .unwrap_or_default(),
            put.expression_attribute_values()
                .cloned()
                .unwrap_or_default(),
        );
    }
    if let Some(upd) = item.update() {
        return PersistItemCtx::new(
            "Update",
            upd.condition_expression().map(str::to_string),
            upd.expression_attribute_names()
                .cloned()
                .unwrap_or_default(),
            upd.expression_attribute_values()
                .cloned()
                .unwrap_or_default(),
        );
    }
    if let Some(del) = item.delete() {
        return PersistItemCtx::new(
            "Delete",
            del.condition_expression().map(str::to_string),
            del.expression_attribute_names()
                .cloned()
                .unwrap_or_default(),
            del.expression_attribute_values()
                .cloned()
                .unwrap_or_default(),
        );
    }
    if let Some(cc) = item.condition_check() {
        return PersistItemCtx::new(
            "ConditionCheck",
            Some(cc.condition_expression().to_string()),
            cc.expression_attribute_names().cloned().unwrap_or_default(),
            cc.expression_attribute_values()
                .cloned()
                .unwrap_or_default(),
        );
    }
    PersistItemCtx::new("Unknown", None, Default::default(), Default::default())
}

/// Rebuild a composed `TransactWriteItem` from its (possibly W3-mutated) seam view,
/// carrying the immutable structural parts (table, item/key, update expression)
/// through unchanged and applying the seam's condition / names / values.
pub fn apply_item_ctx(item: TransactWriteItem, ctx: &PersistItemCtx) -> TransactWriteItem {
    let names = ctx.names.clone();
    let values = ctx.values.clone();
    if let Some(put) = item.put() {
        let mut b = Put::builder()
            .table_name(put.table_name())
            .set_item(Some(put.item().clone()));
        if let Some(ce) = &ctx.condition_expression {
            b = b.condition_expression(ce);
        }
        if !names.is_empty() {
            b = b.set_expression_attribute_names(Some(names));
        }
        if !values.is_empty() {
            b = b.set_expression_attribute_values(Some(values));
        }
        return TransactWriteItem::builder()
            .put(b.build().expect("Put rebuild"))
            .build();
    }
    if let Some(upd) = item.update() {
        let mut b = Update::builder()
            .table_name(upd.table_name())
            .set_key(Some(upd.key().clone()))
            .update_expression(upd.update_expression());
        if let Some(ce) = &ctx.condition_expression {
            b = b.condition_expression(ce);
        }
        if !names.is_empty() {
            b = b.set_expression_attribute_names(Some(names));
        }
        if !values.is_empty() {
            b = b.set_expression_attribute_values(Some(values));
        }
        return TransactWriteItem::builder()
            .update(b.build().expect("Update rebuild"))
            .build();
    }
    if let Some(del) = item.delete() {
        let mut b = Delete::builder()
            .table_name(del.table_name())
            .set_key(Some(del.key().clone()));
        if let Some(ce) = &ctx.condition_expression {
            b = b.condition_expression(ce);
        }
        if !names.is_empty() {
            b = b.set_expression_attribute_names(Some(names));
        }
        if !values.is_empty() {
            b = b.set_expression_attribute_values(Some(values));
        }
        return TransactWriteItem::builder()
            .delete(b.build().expect("Delete rebuild"))
            .build();
    }
    if let Some(cc) = item.condition_check() {
        let mut b = ConditionCheck::builder()
            .table_name(cc.table_name())
            .set_key(Some(cc.key().clone()))
            .condition_expression(ctx.condition_expression.clone().unwrap_or_default());
        if !names.is_empty() {
            b = b.set_expression_attribute_names(Some(names));
        }
        if !values.is_empty() {
            b = b.set_expression_attribute_values(Some(values));
        }
        return TransactWriteItem::builder()
            .condition_check(b.build().expect("ConditionCheck rebuild"))
            .build();
    }
    item
}