Skip to main content

braid_core/antimatter/
json_crdt.rs

1use super::crdt_trait::PrunableCrdt;
2use super::messages::Patch;
3use super::sequence_crdt::{self, SequenceElems, SequenceNode};
4use serde::{Deserialize, Serialize};
5use serde_json::{json, Value};
6use std::collections::{HashMap, HashSet};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct JsonCrdt {
10    pub id: String,
11    pub root: SequenceNode,
12    pub next_seq: u64,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct JsonPatch {
17    pub path: Vec<String>,
18    pub range: String,
19    pub content: Value,
20}
21
22impl PrunableCrdt for JsonCrdt {
23    fn apply_patch(&mut self, patch: Patch) {
24        // Simplified JSON CRDT application for strings/text
25        // In real antimatter, this handles complex nested structures
26        if let Some(content_str) = patch.content.as_str() {
27            // Treat as text insert/replace
28            if patch.range.is_empty() {
29                // Initial content
30                self.root = SequenceNode::text(&format!("{}@{}", self.next_seq, self.id), content_str);
31            } else {
32                // This is a simplified mock behavior matching braid-http requirements
33                // Real antimatter would use the range to find the path in the JSON tree
34            }
35        }
36        self.next_seq += 1;
37    }
38
39    fn prune(&mut self, version: &str) {
40        sequence_crdt::prune(&mut self.root, version);
41    }
42
43    fn get_next_seq(&self) -> u64 {
44        self.next_seq
45    }
46
47    fn generate_braid(
48        &self,
49        known_versions: &HashMap<String, bool>,
50    ) -> Vec<(String, HashMap<String, bool>, Vec<Patch>)> {
51        // Return visibility-based patches
52        let visible = |v: &str| {
53            if v.is_empty() {
54                return true;
55            }
56            !known_versions.contains_key(v)
57        };
58
59        vec![(
60            self.generate_version(),
61            known_versions.clone(),
62            vec![Patch {
63                range: "0".to_string(),
64                content: json!(sequence_crdt::content(&self.root, visible)),
65            }],
66        )]
67    }
68}
69
70impl JsonCrdt {
71    pub fn new(id: &str) -> Self {
72        Self {
73            id: id.to_string(),
74            root: SequenceNode {
75                version: None,
76                elems: SequenceElems::String(String::new()),
77                next: Vec::new(),
78                deleted_by: HashSet::new(),
79            },
80            next_seq: 0,
81        }
82    }
83
84    pub fn with_content(id: &str, content: &str) -> Self {
85        let mut crdt = Self::new(id);
86        crdt.root = SequenceNode::text(&format!("0@{}", id), content);
87        crdt.next_seq = 1;
88        crdt
89    }
90
91    pub fn get_content(&self) -> String {
92        sequence_crdt::content(&self.root, |_| true)
93    }
94
95    pub fn get_length(&self) -> usize {
96        sequence_crdt::length(&self.root, |_| true)
97    }
98
99    pub fn generate_version(&self) -> String {
100        format!("{}@{}", self.next_seq, self.id)
101    }
102
103    pub fn get_frontier(&self) -> Vec<String> {
104        // Search versions in the tree
105        let mut versions = HashSet::new();
106        let mut stack = vec![&self.root];
107        while let Some(node) = stack.pop() {
108            if let Some(v) = &node.version {
109                versions.insert(v.clone());
110            }
111            for child in &node.next {
112                stack.push(child);
113            }
114        }
115        versions.into_iter().collect()
116    }
117}