hypen_engine/reconcile/
patch.rs1use crate::ir::NodeId;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4use std::collections::HashMap;
5use std::sync::atomic::{AtomicU64, Ordering};
6use std::sync::Mutex;
7
8static NEXT_ID: AtomicU64 = AtomicU64::new(1);
10
11static NODE_ID_MAP: Mutex<Option<HashMap<NodeId, String>>> = Mutex::new(None);
15
16#[inline]
22pub fn node_id_str(id: NodeId) -> String {
23 let mut guard = NODE_ID_MAP.lock().unwrap();
24 let map = guard.get_or_insert_with(HashMap::new);
25 map.entry(id)
26 .or_insert_with(|| NEXT_ID.fetch_add(1, Ordering::Relaxed).to_string())
27 .clone()
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
32#[serde(tag = "type", rename_all = "camelCase")]
33pub enum Patch {
34 #[serde(rename_all = "camelCase")]
36 Create {
37 id: String,
38 element_type: String,
39 props: indexmap::IndexMap<String, Value>,
40 },
41
42 #[serde(rename_all = "camelCase")]
44 SetProp {
45 id: String,
46 name: String,
47 value: Value,
48 },
49
50 #[serde(rename_all = "camelCase")]
52 RemoveProp {
53 id: String,
54 name: String,
55 },
56
57 #[serde(rename_all = "camelCase")]
59 SetText {
60 id: String,
61 text: String,
62 },
63
64 #[serde(rename_all = "camelCase")]
66 Insert {
67 parent_id: String,
68 id: String,
69 before_id: Option<String>,
70 },
71
72 #[serde(rename_all = "camelCase")]
74 Move {
75 parent_id: String,
76 id: String,
77 before_id: Option<String>,
78 },
79
80 #[serde(rename_all = "camelCase")]
82 Remove {
83 id: String,
84 },
85}
86
87impl Patch {
88 pub fn create(id: NodeId, element_type: String, props: indexmap::IndexMap<String, Value>) -> Self {
89 Self::Create {
90 id: node_id_str(id),
91 element_type,
92 props,
93 }
94 }
95
96 pub fn set_prop(id: NodeId, name: String, value: Value) -> Self {
97 Self::SetProp {
98 id: node_id_str(id),
99 name,
100 value,
101 }
102 }
103
104 pub fn remove_prop(id: NodeId, name: String) -> Self {
105 Self::RemoveProp {
106 id: node_id_str(id),
107 name,
108 }
109 }
110
111 pub fn set_text(id: NodeId, text: String) -> Self {
112 Self::SetText {
113 id: node_id_str(id),
114 text,
115 }
116 }
117
118 pub fn insert(parent_id: NodeId, id: NodeId, before_id: Option<NodeId>) -> Self {
119 Self::Insert {
120 parent_id: node_id_str(parent_id),
121 id: node_id_str(id),
122 before_id: before_id.map(node_id_str),
123 }
124 }
125
126 pub fn insert_root(id: NodeId) -> Self {
128 Self::Insert {
129 parent_id: "root".to_string(),
130 id: node_id_str(id),
131 before_id: None,
132 }
133 }
134
135 pub fn move_node(parent_id: NodeId, id: NodeId, before_id: Option<NodeId>) -> Self {
136 Self::Move {
137 parent_id: node_id_str(parent_id),
138 id: node_id_str(id),
139 before_id: before_id.map(node_id_str),
140 }
141 }
142
143 pub fn remove(id: NodeId) -> Self {
144 Self::Remove {
145 id: node_id_str(id),
146 }
147 }
148
149}