1use crate::error::DbError;
12use crate::rga_list::{RGAList, RGAListDelta};
13use mdcs_core::lattice::Lattice;
14use serde::{Deserialize, Serialize};
15use std::collections::{HashMap, HashSet};
16use ulid::Ulid;
17
18#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
20pub struct JsonPath(Vec<PathSegment>);
21
22impl JsonPath {
23 pub fn root() -> Self {
25 Self(Vec::new())
26 }
27
28 pub fn new(segments: Vec<PathSegment>) -> Self {
30 Self(segments)
31 }
32
33 pub fn parse(path: &str) -> Self {
35 if path.is_empty() {
36 return Self::root();
37 }
38 let segments = path
39 .split('.')
40 .map(|s| {
41 if let Ok(idx) = s.parse::<usize>() {
42 PathSegment::Index(idx)
43 } else {
44 PathSegment::Key(s.to_string())
45 }
46 })
47 .collect();
48 Self(segments)
49 }
50
51 pub fn segments(&self) -> &[PathSegment] {
53 &self.0
54 }
55
56 pub fn is_root(&self) -> bool {
58 self.0.is_empty()
59 }
60
61 pub fn parent(&self) -> Option<Self> {
63 if self.0.is_empty() {
64 None
65 } else {
66 Some(Self(self.0[..self.0.len() - 1].to_vec()))
67 }
68 }
69
70 pub fn last(&self) -> Option<&PathSegment> {
72 self.0.last()
73 }
74
75 pub fn push(&mut self, segment: PathSegment) {
77 self.0.push(segment);
78 }
79
80 pub fn child_key(&self, key: impl Into<String>) -> Self {
82 let mut new = self.clone();
83 new.push(PathSegment::Key(key.into()));
84 new
85 }
86
87 pub fn child_index(&self, index: usize) -> Self {
89 let mut new = self.clone();
90 new.push(PathSegment::Index(index));
91 new
92 }
93}
94
95impl std::fmt::Display for JsonPath {
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 let s: Vec<String> = self.0.iter().map(|s| s.to_string()).collect();
98 write!(f, "{}", s.join("."))
99 }
100}
101
102#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
104pub enum PathSegment {
105 Key(String),
107 Index(usize),
109}
110
111impl std::fmt::Display for PathSegment {
112 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113 match self {
114 PathSegment::Key(k) => write!(f, "{}", k),
115 PathSegment::Index(i) => write!(f, "{}", i),
116 }
117 }
118}
119
120#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
122pub enum JsonValue {
123 #[default]
125 Null,
126 Bool(bool),
128 Int(i64),
130 Float(f64),
132 String(String),
134 Array(ArrayId),
136 Object(ObjectId),
138}
139
140impl JsonValue {
141 pub fn is_null(&self) -> bool {
142 matches!(self, JsonValue::Null)
143 }
144
145 pub fn as_bool(&self) -> Option<bool> {
146 match self {
147 JsonValue::Bool(b) => Some(*b),
148 _ => None,
149 }
150 }
151
152 pub fn as_int(&self) -> Option<i64> {
153 match self {
154 JsonValue::Int(i) => Some(*i),
155 _ => None,
156 }
157 }
158
159 pub fn as_float(&self) -> Option<f64> {
160 match self {
161 JsonValue::Float(f) => Some(*f),
162 _ => None,
163 }
164 }
165
166 pub fn as_str(&self) -> Option<&str> {
167 match self {
168 JsonValue::String(s) => Some(s),
169 _ => None,
170 }
171 }
172}
173
174#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
176pub struct ArrayId(String);
177
178impl ArrayId {
179 pub fn new() -> Self {
180 Self(Ulid::new().to_string())
181 }
182}
183
184impl Default for ArrayId {
185 fn default() -> Self {
186 Self::new()
187 }
188}
189
190#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
192pub struct ObjectId(String);
193
194impl ObjectId {
195 pub fn new() -> Self {
196 Self(Ulid::new().to_string())
197 }
198
199 pub fn root() -> Self {
200 Self("root".to_string())
201 }
202}
203
204impl Default for ObjectId {
205 fn default() -> Self {
206 Self::new()
207 }
208}
209
210#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
212pub struct ValueId {
213 replica: String,
214 seq: u64,
215}
216
217impl ValueId {
218 pub fn new(replica: impl Into<String>, seq: u64) -> Self {
219 Self {
220 replica: replica.into(),
221 seq,
222 }
223 }
224}
225
226#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
228struct ObjectField {
229 values: HashMap<ValueId, JsonValue>,
231 deleted: HashSet<ValueId>,
233}
234
235impl ObjectField {
236 fn new() -> Self {
237 Self {
238 values: HashMap::new(),
239 deleted: HashSet::new(),
240 }
241 }
242
243 fn set(&mut self, id: ValueId, value: JsonValue) {
244 let to_delete: Vec<_> = self
246 .values
247 .keys()
248 .filter(|k| k.replica == id.replica)
249 .cloned()
250 .collect();
251 for k in to_delete {
252 self.values.remove(&k);
253 }
254 self.values.insert(id, value);
255 }
256
257 #[allow(dead_code)]
258 fn get(&self) -> Vec<&JsonValue> {
259 self.values.values().collect()
260 }
261
262 fn get_winner(&self) -> Option<&JsonValue> {
263 self.values
265 .iter()
266 .max_by(|(a, _), (b, _)| a.seq.cmp(&b.seq).then_with(|| a.replica.cmp(&b.replica)))
267 .map(|(_, v)| v)
268 }
269
270 fn is_deleted(&self) -> bool {
271 self.values.is_empty() || self.values.values().all(|v| v.is_null())
272 }
273
274 fn merge(&mut self, other: &ObjectField) {
275 for (id, value) in &other.values {
276 if !self.deleted.contains(id) {
277 self.values
278 .entry(id.clone())
279 .or_insert_with(|| value.clone());
280 }
281 }
282 self.deleted.extend(other.deleted.iter().cloned());
283 for id in &self.deleted {
285 self.values.remove(id);
286 }
287 }
288}
289
290#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
292struct JsonObject {
293 id: ObjectId,
294 fields: HashMap<String, ObjectField>,
295}
296
297impl JsonObject {
298 fn new(id: ObjectId) -> Self {
299 Self {
300 id,
301 fields: HashMap::new(),
302 }
303 }
304
305 fn set(&mut self, key: String, value_id: ValueId, value: JsonValue) {
306 self.fields
307 .entry(key)
308 .or_insert_with(ObjectField::new)
309 .set(value_id, value);
310 }
311
312 fn get(&self, key: &str) -> Option<&JsonValue> {
313 self.fields.get(key)?.get_winner()
314 }
315
316 #[allow(dead_code)]
317 fn get_all(&self, key: &str) -> Vec<&JsonValue> {
318 self.fields.get(key).map(|f| f.get()).unwrap_or_default()
319 }
320
321 fn keys(&self) -> impl Iterator<Item = &String> + '_ {
322 self.fields
323 .iter()
324 .filter(|(_, f)| !f.is_deleted())
325 .map(|(k, _)| k)
326 }
327
328 fn remove(&mut self, key: &str, value_id: ValueId) {
329 if let Some(field) = self.fields.get_mut(key) {
330 let to_delete: Vec<_> = field.values.keys().cloned().collect();
332 for id in to_delete {
333 field.deleted.insert(id);
334 }
335 field.values.clear();
336 field.values.insert(value_id, JsonValue::Null);
338 }
339 }
340
341 fn merge(&mut self, other: &JsonObject) {
342 for (key, field) in &other.fields {
343 self.fields
344 .entry(key.clone())
345 .or_insert_with(ObjectField::new)
346 .merge(field);
347 }
348 }
349}
350
351#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
353struct JsonArray {
354 id: ArrayId,
355 list: RGAList<JsonValue>,
356}
357
358impl JsonArray {
359 fn new(id: ArrayId, replica_id: &str) -> Self {
360 Self {
361 id,
362 list: RGAList::new(replica_id),
363 }
364 }
365
366 #[allow(dead_code)]
367 fn get(&self, index: usize) -> Option<&JsonValue> {
368 self.list.get(index)
369 }
370
371 fn len(&self) -> usize {
372 self.list.len()
373 }
374
375 fn insert(&mut self, index: usize, value: JsonValue) {
376 self.list.insert(index, value);
377 }
378
379 fn remove(&mut self, index: usize) -> Option<JsonValue> {
380 self.list.delete(index)
381 }
382
383 fn push(&mut self, value: JsonValue) {
384 self.list.push_back(value);
385 }
386
387 fn iter(&self) -> impl Iterator<Item = &JsonValue> + '_ {
388 self.list.iter()
389 }
390
391 fn merge(&mut self, other: &JsonArray) {
392 self.list = self.list.join(&other.list);
393 }
394}
395
396#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
398pub struct JsonCrdtDelta {
399 pub object_changes: Vec<ObjectChange>,
401 pub array_changes: Vec<ArrayChange>,
403 pub new_objects: Vec<ObjectId>,
405 pub new_arrays: Vec<ArrayId>,
407}
408
409#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
410pub struct ObjectChange {
411 pub object_id: ObjectId,
412 pub key: String,
413 pub value_id: ValueId,
414 pub value: JsonValue,
415}
416
417#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
418pub struct ArrayChange {
419 pub array_id: ArrayId,
420 pub delta: RGAListDelta<JsonValue>,
421}
422
423impl JsonCrdtDelta {
424 pub fn new() -> Self {
425 Self {
426 object_changes: Vec::new(),
427 array_changes: Vec::new(),
428 new_objects: Vec::new(),
429 new_arrays: Vec::new(),
430 }
431 }
432
433 pub fn is_empty(&self) -> bool {
434 self.object_changes.is_empty()
435 && self.array_changes.is_empty()
436 && self.new_objects.is_empty()
437 && self.new_arrays.is_empty()
438 }
439}
440
441impl Default for JsonCrdtDelta {
442 fn default() -> Self {
443 Self::new()
444 }
445}
446
447#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
452pub struct JsonCrdt {
453 replica_id: String,
455 seq: u64,
457 root_id: ObjectId,
459 objects: HashMap<ObjectId, JsonObject>,
461 arrays: HashMap<ArrayId, JsonArray>,
463 #[serde(skip)]
465 pending_delta: Option<JsonCrdtDelta>,
466}
467
468impl JsonCrdt {
469 pub fn new(replica_id: impl Into<String>) -> Self {
471 let replica_id = replica_id.into();
472 let root_id = ObjectId::root();
473 let root = JsonObject::new(root_id.clone());
474
475 let mut objects = HashMap::new();
476 objects.insert(root_id.clone(), root);
477
478 Self {
479 replica_id,
480 seq: 0,
481 root_id,
482 objects,
483 arrays: HashMap::new(),
484 pending_delta: None,
485 }
486 }
487
488 pub fn replica_id(&self) -> &str {
490 &self.replica_id
491 }
492
493 fn next_value_id(&mut self) -> ValueId {
495 self.seq += 1;
496 ValueId::new(&self.replica_id, self.seq)
497 }
498
499 pub fn get(&self, path: &JsonPath) -> Option<&JsonValue> {
501 let mut current_obj_id = &self.root_id;
502 let segments = path.segments();
503
504 for (i, segment) in segments.iter().enumerate() {
505 let is_last = i == segments.len() - 1;
506
507 match segment {
508 PathSegment::Key(key) => {
509 let obj = self.objects.get(current_obj_id)?;
510 let value = obj.get(key)?;
511
512 if is_last {
513 return Some(value);
514 }
515
516 match value {
517 JsonValue::Object(id) => current_obj_id = id,
518 JsonValue::Array(_) if !is_last => {
519 continue;
521 }
522 _ => return None,
523 }
524 }
525 PathSegment::Index(_idx) => {
526 let _obj = self.objects.get(current_obj_id)?;
528 return None; }
532 }
533 }
534
535 None
537 }
538
539 pub fn set(&mut self, path: &JsonPath, value: JsonValue) -> Result<(), DbError> {
541 if path.is_root() {
542 return Err(DbError::InvalidPath("Cannot set root".to_string()));
543 }
544
545 let parent_path = path.parent().unwrap_or(JsonPath::root());
546 let last_segment = path
547 .last()
548 .ok_or_else(|| DbError::InvalidPath("Empty path".to_string()))?;
549
550 let parent_obj_id = self.ensure_object_at(&parent_path)?;
552
553 let value_id = self.next_value_id();
554
555 match last_segment {
556 PathSegment::Key(key) => {
557 let actual_value = match &value {
559 JsonValue::Object(_) | JsonValue::Array(_) => value,
560 _ => value,
561 };
562
563 if let Some(obj) = self.objects.get_mut(&parent_obj_id) {
564 obj.set(key.clone(), value_id.clone(), actual_value.clone());
565 }
566
567 let delta = self.pending_delta.get_or_insert_with(JsonCrdtDelta::new);
569 delta.object_changes.push(ObjectChange {
570 object_id: parent_obj_id,
571 key: key.clone(),
572 value_id,
573 value: actual_value,
574 });
575 }
576 PathSegment::Index(_) => {
577 return Err(DbError::UnsupportedOperation(
578 "Set by index not supported; use array_insert".to_string(),
579 ));
580 }
581 }
582
583 Ok(())
584 }
585
586 pub fn delete(&mut self, path: &JsonPath) -> Result<(), DbError> {
588 if path.is_root() {
589 return Err(DbError::InvalidPath("Cannot delete root".to_string()));
590 }
591
592 let parent_path = path.parent().unwrap_or(JsonPath::root());
593 let last_segment = path
594 .last()
595 .ok_or_else(|| DbError::InvalidPath("Empty path".to_string()))?;
596
597 let parent_obj_id = self
598 .get_object_id_at(&parent_path)
599 .ok_or_else(|| DbError::PathNotFound(parent_path.to_string()))?;
600
601 let value_id = self.next_value_id();
602
603 match last_segment {
604 PathSegment::Key(key) => {
605 if let Some(obj) = self.objects.get_mut(&parent_obj_id) {
606 obj.remove(key, value_id.clone());
607 }
608
609 let delta = self.pending_delta.get_or_insert_with(JsonCrdtDelta::new);
611 delta.object_changes.push(ObjectChange {
612 object_id: parent_obj_id,
613 key: key.clone(),
614 value_id,
615 value: JsonValue::Null,
616 });
617 }
618 PathSegment::Index(_) => {
619 return Err(DbError::UnsupportedOperation(
620 "Delete by index not supported; use array_remove".to_string(),
621 ));
622 }
623 }
624
625 Ok(())
626 }
627
628 pub fn create_object(&mut self) -> ObjectId {
630 let id = ObjectId::new();
631 let obj = JsonObject::new(id.clone());
632 self.objects.insert(id.clone(), obj);
633
634 let delta = self.pending_delta.get_or_insert_with(JsonCrdtDelta::new);
635 delta.new_objects.push(id.clone());
636
637 id
638 }
639
640 pub fn create_array(&mut self) -> ArrayId {
642 let id = ArrayId::new();
643 let arr = JsonArray::new(id.clone(), &self.replica_id);
644 self.arrays.insert(id.clone(), arr);
645
646 let delta = self.pending_delta.get_or_insert_with(JsonCrdtDelta::new);
647 delta.new_arrays.push(id.clone());
648
649 id
650 }
651
652 pub fn set_object(&mut self, path: &JsonPath) -> Result<ObjectId, DbError> {
654 let obj_id = self.create_object();
655 self.set(path, JsonValue::Object(obj_id.clone()))?;
656 Ok(obj_id)
657 }
658
659 pub fn set_array(&mut self, path: &JsonPath) -> Result<ArrayId, DbError> {
661 let arr_id = self.create_array();
662 self.set(path, JsonValue::Array(arr_id.clone()))?;
663 Ok(arr_id)
664 }
665
666 #[allow(dead_code)]
668 fn get_array(&self, id: &ArrayId) -> Option<&JsonArray> {
669 self.arrays.get(id)
670 }
671
672 #[allow(dead_code)]
674 fn get_array_mut(&mut self, id: &ArrayId) -> Option<&mut JsonArray> {
675 self.arrays.get_mut(id)
676 }
677
678 pub fn array_insert(
680 &mut self,
681 array_id: &ArrayId,
682 index: usize,
683 value: JsonValue,
684 ) -> Result<(), DbError> {
685 let arr = self
686 .arrays
687 .get_mut(array_id)
688 .ok_or_else(|| DbError::PathNotFound(format!("Array {:?}", array_id)))?;
689
690 arr.insert(index, value);
691
692 if let Some(delta) = arr.list.take_delta() {
693 let doc_delta = self.pending_delta.get_or_insert_with(JsonCrdtDelta::new);
694 doc_delta.array_changes.push(ArrayChange {
695 array_id: array_id.clone(),
696 delta,
697 });
698 }
699
700 Ok(())
701 }
702
703 pub fn array_push(&mut self, array_id: &ArrayId, value: JsonValue) -> Result<(), DbError> {
705 let arr = self
706 .arrays
707 .get_mut(array_id)
708 .ok_or_else(|| DbError::PathNotFound(format!("Array {:?}", array_id)))?;
709
710 arr.push(value);
711
712 if let Some(delta) = arr.list.take_delta() {
713 let doc_delta = self.pending_delta.get_or_insert_with(JsonCrdtDelta::new);
714 doc_delta.array_changes.push(ArrayChange {
715 array_id: array_id.clone(),
716 delta,
717 });
718 }
719
720 Ok(())
721 }
722
723 pub fn array_remove(&mut self, array_id: &ArrayId, index: usize) -> Result<JsonValue, DbError> {
725 let arr = self
726 .arrays
727 .get_mut(array_id)
728 .ok_or_else(|| DbError::PathNotFound(format!("Array {:?}", array_id)))?;
729
730 let arr_len = arr.len();
731 let value = arr.remove(index).ok_or(DbError::IndexOutOfBounds {
732 index,
733 length: arr_len,
734 })?;
735
736 if let Some(delta) = arr.list.take_delta() {
737 let doc_delta = self.pending_delta.get_or_insert_with(JsonCrdtDelta::new);
738 doc_delta.array_changes.push(ArrayChange {
739 array_id: array_id.clone(),
740 delta,
741 });
742 }
743
744 Ok(value)
745 }
746
747 pub fn array_len(&self, array_id: &ArrayId) -> Option<usize> {
749 self.arrays.get(array_id).map(|a| a.len())
750 }
751
752 pub fn keys(&self) -> Vec<String> {
754 self.objects
755 .get(&self.root_id)
756 .map(|obj| obj.keys().cloned().collect())
757 .unwrap_or_default()
758 }
759
760 pub fn contains_key(&self, key: &str) -> bool {
762 self.objects
763 .get(&self.root_id)
764 .map(|obj| obj.get(key).is_some())
765 .unwrap_or(false)
766 }
767
768 fn get_object_id_at(&self, path: &JsonPath) -> Option<ObjectId> {
771 if path.is_root() {
772 return Some(self.root_id.clone());
773 }
774
775 let value = self.get(path)?;
776 match value {
777 JsonValue::Object(id) => Some(id.clone()),
778 _ => None,
779 }
780 }
781
782 fn ensure_object_at(&mut self, path: &JsonPath) -> Result<ObjectId, DbError> {
783 if path.is_root() {
784 return Ok(self.root_id.clone());
785 }
786
787 if let Some(id) = self.get_object_id_at(path) {
789 return Ok(id);
790 }
791
792 self.set_object(path)
794 }
795
796 pub fn take_delta(&mut self) -> Option<JsonCrdtDelta> {
800 self.pending_delta.take()
801 }
802
803 pub fn apply_delta(&mut self, delta: &JsonCrdtDelta) {
805 for obj_id in &delta.new_objects {
807 self.objects
808 .entry(obj_id.clone())
809 .or_insert_with(|| JsonObject::new(obj_id.clone()));
810 }
811
812 for arr_id in &delta.new_arrays {
814 self.arrays
815 .entry(arr_id.clone())
816 .or_insert_with(|| JsonArray::new(arr_id.clone(), &self.replica_id));
817 }
818
819 for change in &delta.object_changes {
821 if let Some(obj) = self.objects.get_mut(&change.object_id) {
822 obj.set(
823 change.key.clone(),
824 change.value_id.clone(),
825 change.value.clone(),
826 );
827 }
828 }
829
830 for change in &delta.array_changes {
832 if let Some(arr) = self.arrays.get_mut(&change.array_id) {
833 arr.list.apply_delta(&change.delta);
834 }
835 }
836 }
837
838 pub fn to_json(&self) -> serde_json::Value {
842 self.object_to_json(&self.root_id)
843 }
844
845 fn object_to_json(&self, obj_id: &ObjectId) -> serde_json::Value {
846 let obj = match self.objects.get(obj_id) {
847 Some(o) => o,
848 None => return serde_json::Value::Null,
849 };
850
851 let mut map = serde_json::Map::new();
852 for key in obj.keys() {
853 if let Some(value) = obj.get(key) {
854 map.insert(key.clone(), self.value_to_json(value));
855 }
856 }
857 serde_json::Value::Object(map)
858 }
859
860 fn array_to_json(&self, arr_id: &ArrayId) -> serde_json::Value {
861 let arr = match self.arrays.get(arr_id) {
862 Some(a) => a,
863 None => return serde_json::Value::Array(vec![]),
864 };
865
866 let values: Vec<_> = arr.iter().map(|v| self.value_to_json(v)).collect();
867 serde_json::Value::Array(values)
868 }
869
870 fn value_to_json(&self, value: &JsonValue) -> serde_json::Value {
871 match value {
872 JsonValue::Null => serde_json::Value::Null,
873 JsonValue::Bool(b) => serde_json::Value::Bool(*b),
874 JsonValue::Int(i) => serde_json::Value::Number((*i).into()),
875 JsonValue::Float(f) => serde_json::Number::from_f64(*f)
876 .map(serde_json::Value::Number)
877 .unwrap_or(serde_json::Value::Null),
878 JsonValue::String(s) => serde_json::Value::String(s.clone()),
879 JsonValue::Object(id) => self.object_to_json(id),
880 JsonValue::Array(id) => self.array_to_json(id),
881 }
882 }
883}
884
885impl Lattice for JsonCrdt {
886 fn bottom() -> Self {
887 Self::new("")
888 }
889
890 fn join(&self, other: &Self) -> Self {
891 let mut result = self.clone();
892
893 for (id, other_obj) in &other.objects {
895 result
896 .objects
897 .entry(id.clone())
898 .and_modify(|obj| obj.merge(other_obj))
899 .or_insert_with(|| other_obj.clone());
900 }
901
902 for (id, other_arr) in &other.arrays {
904 result
905 .arrays
906 .entry(id.clone())
907 .and_modify(|arr| arr.merge(other_arr))
908 .or_insert_with(|| other_arr.clone());
909 }
910
911 result
912 }
913}
914
915impl Default for JsonCrdt {
916 fn default() -> Self {
917 Self::new("")
918 }
919}
920
921#[cfg(test)]
922mod tests {
923 use super::*;
924
925 #[test]
926 fn test_basic_set_get() {
927 let mut doc = JsonCrdt::new("r1");
928
929 doc.set(
930 &JsonPath::parse("name"),
931 JsonValue::String("Alice".to_string()),
932 )
933 .unwrap();
934 doc.set(&JsonPath::parse("age"), JsonValue::Int(30))
935 .unwrap();
936
937 let name = doc.get(&JsonPath::parse("name")).unwrap();
938 assert_eq!(name.as_str(), Some("Alice"));
939
940 let age = doc.get(&JsonPath::parse("age")).unwrap();
941 assert_eq!(age.as_int(), Some(30));
942 }
943
944 #[test]
945 fn test_nested_object() {
946 let mut doc = JsonCrdt::new("r1");
947
948 let _user_id = doc.set_object(&JsonPath::parse("user")).unwrap();
949 doc.set(
950 &JsonPath::parse("user.name"),
951 JsonValue::String("Bob".to_string()),
952 )
953 .unwrap();
954
955 assert!(doc.contains_key("user"));
956
957 let user_value = doc.get(&JsonPath::parse("user"));
959 assert!(user_value.is_some());
960 }
961
962 #[test]
963 fn test_array_operations() {
964 let mut doc = JsonCrdt::new("r1");
965
966 let arr_id = doc.create_array();
967 doc.set(&JsonPath::parse("items"), JsonValue::Array(arr_id.clone()))
968 .unwrap();
969
970 doc.array_push(&arr_id, JsonValue::String("one".to_string()))
971 .unwrap();
972 doc.array_push(&arr_id, JsonValue::String("two".to_string()))
973 .unwrap();
974 doc.array_push(&arr_id, JsonValue::String("three".to_string()))
975 .unwrap();
976
977 assert_eq!(doc.array_len(&arr_id), Some(3));
978
979 let removed = doc.array_remove(&arr_id, 1).unwrap();
980 assert_eq!(removed.as_str(), Some("two"));
981 assert_eq!(doc.array_len(&arr_id), Some(2));
982 }
983
984 #[test]
985 fn test_delete() {
986 let mut doc = JsonCrdt::new("r1");
987
988 doc.set(
989 &JsonPath::parse("temp"),
990 JsonValue::String("value".to_string()),
991 )
992 .unwrap();
993 assert!(doc.contains_key("temp"));
994
995 doc.delete(&JsonPath::parse("temp")).unwrap();
996 }
998
999 #[test]
1000 fn test_concurrent_sets() {
1001 let mut doc1 = JsonCrdt::new("r1");
1002 let mut doc2 = JsonCrdt::new("r2");
1003
1004 doc1.set(
1006 &JsonPath::parse("value"),
1007 JsonValue::String("from_r1".to_string()),
1008 )
1009 .unwrap();
1010 doc2.set(
1011 &JsonPath::parse("value"),
1012 JsonValue::String("from_r2".to_string()),
1013 )
1014 .unwrap();
1015
1016 let delta1 = doc1.take_delta().unwrap();
1018 let delta2 = doc2.take_delta().unwrap();
1019
1020 doc1.apply_delta(&delta2);
1021 doc2.apply_delta(&delta1);
1022
1023 let json1 = doc1.to_json();
1025 let json2 = doc2.to_json();
1026 assert_eq!(json1, json2);
1027 }
1028
1029 #[test]
1030 fn test_to_json() {
1031 let mut doc = JsonCrdt::new("r1");
1032
1033 doc.set(
1034 &JsonPath::parse("name"),
1035 JsonValue::String("Test".to_string()),
1036 )
1037 .unwrap();
1038 doc.set(&JsonPath::parse("count"), JsonValue::Int(42))
1039 .unwrap();
1040 doc.set(&JsonPath::parse("active"), JsonValue::Bool(true))
1041 .unwrap();
1042
1043 let json = doc.to_json();
1044 assert!(json.is_object());
1045 assert_eq!(json["name"], "Test");
1046 assert_eq!(json["count"], 42);
1047 assert_eq!(json["active"], true);
1048 }
1049
1050 #[test]
1051 fn test_path_parsing() {
1052 let path = JsonPath::parse("user.profile.name");
1053 assert_eq!(path.segments().len(), 3);
1054
1055 let path_with_index = JsonPath::parse("items.0.value");
1056 assert_eq!(path_with_index.segments().len(), 3);
1057 assert!(matches!(
1058 path_with_index.segments()[1],
1059 PathSegment::Index(0)
1060 ));
1061 }
1062
1063 #[test]
1064 fn test_lattice_join() {
1065 let mut doc1 = JsonCrdt::new("r1");
1066 let mut doc2 = JsonCrdt::new("r2");
1067
1068 doc1.set(
1069 &JsonPath::parse("a"),
1070 JsonValue::String("from_r1".to_string()),
1071 )
1072 .unwrap();
1073 doc2.set(
1074 &JsonPath::parse("b"),
1075 JsonValue::String("from_r2".to_string()),
1076 )
1077 .unwrap();
1078
1079 let merged = doc1.join(&doc2);
1080
1081 assert!(merged.contains_key("a"));
1083 assert!(merged.contains_key("b"));
1084 }
1085
1086 #[test]
1087 fn test_keys() {
1088 let mut doc = JsonCrdt::new("r1");
1089
1090 doc.set(&JsonPath::parse("x"), JsonValue::Int(1)).unwrap();
1091 doc.set(&JsonPath::parse("y"), JsonValue::Int(2)).unwrap();
1092 doc.set(&JsonPath::parse("z"), JsonValue::Int(3)).unwrap();
1093
1094 let keys = doc.keys();
1095 assert_eq!(keys.len(), 3);
1096 assert!(keys.contains(&"x".to_string()));
1097 assert!(keys.contains(&"y".to_string()));
1098 assert!(keys.contains(&"z".to_string()));
1099 }
1100}