gioser

tawasuyu/brahman

Rust 582TOML 222Markdown 73JSON 198635 Definiciones

⎇ 4d50bfc5879839a835e26ffda3bbc7ae3b927cc7 crates/modules/nakui/core/src/delta.rs Rust · 72 líneas · 2.1 KB Historia Quién tocó qué crudo

chore: absorbe nakui (ERP matemático) en modules/nakui 4d50bfc58 · Sergio ·

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use uuid::Uuid;
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
6pub struct FieldPath {
7    pub entity: String,
8    pub id: Uuid,
9    pub field: String,
10}
11
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13#[serde(tag = "op", rename_all = "snake_case")]
14pub enum FieldOp {
15    Set {
16        path: FieldPath,
17        value: Value,
18    },
19    Create {
20        entity: String,
21        id: Uuid,
22        data: Value,
23    },
24    Delete {
25        entity: String,
26        id: Uuid,
27    },
28}
29
30impl FieldOp {
31    /// Token a manifest's `writes` list matches against.
32    /// "Caja.saldo" for field updates, "Movimiento" for whole-record ops.
33    pub fn capability_token(&self) -> String {
34        match self {
35            FieldOp::Set { path, .. } => format!("{}.{}", path.entity, path.field),
36            FieldOp::Create { entity, .. } => entity.clone(),
37            FieldOp::Delete { entity, .. } => entity.clone(),
38        }
39    }
40}
41
42/// Apply only the ops that target `(entity, id)` to `state` and return the
43/// new value. Returns `None` if a Delete op removes the target — callers
44/// should skip post-checks against a deleted entity rather than running
45/// them against the stale prior state.
46pub fn simulate_on(state: &Value, entity: &str, id: Uuid, ops: &[FieldOp]) -> Option<Value> {
47    let mut s: Option<Value> = Some(state.clone());
48    for op in ops {
49        match op {
50            FieldOp::Set { path, value } if path.entity == entity && path.id == id => {
51                if let Some(Value::Object(map)) = s.as_mut() {
52                    map.insert(path.field.clone(), value.clone());
53                }
54            }
55            FieldOp::Create {
56                entity: e,
57                id: i,
58                data,
59            } if e == entity && *i == id => {
60                s = Some(data.clone());
61            }
62            FieldOp::Delete {
63                entity: e,
64                id: i,
65            } if e == entity && *i == id => {
66                s = None;
67            }
68            _ => {}
69        }
70    }
71    s
72}