1use crate::{
8 DsonOperation, FilterPredicate, MergeStrategy, OperationValue, ReduceFunction, StreamGenerator,
9 TransformFunction,
10};
11use fionn_core::Result;
12use smallvec::SmallVec;
13
14pub trait DocumentProcessor {
20 fn process(&mut self, input: &str) -> Result<String>;
25
26 fn apply_operation(&mut self, op: &DsonOperation) -> Result<()>;
31
32 fn apply_operations(&mut self, ops: &[DsonOperation]) -> Result<()> {
37 for op in ops {
38 self.apply_operation(op)?;
39 }
40 Ok(())
41 }
42
43 fn output(&self) -> Result<String>;
48}
49
50pub trait SchemaAware {
52 fn matches_input_schema(&self, path: &str) -> bool;
54
55 fn matches_output_schema(&self, path: &str) -> bool;
57
58 fn input_schema(&self) -> Vec<String>;
60
61 fn output_schema(&self) -> Vec<String>;
63}
64
65pub trait FieldOperations {
67 fn field_add(&mut self, path: &str, value: OperationValue) -> Result<()>;
72
73 fn field_modify(&mut self, path: &str, value: OperationValue) -> Result<()>;
78
79 fn field_delete(&mut self, path: &str) -> Result<()>;
84
85 fn field_read(&self, path: &str) -> Result<Option<OperationValue>>;
90
91 fn field_exists(&self, path: &str) -> bool;
93}
94
95pub trait ArrayOperations {
97 fn array_insert(&mut self, path: &str, index: usize, value: OperationValue) -> Result<()>;
102
103 fn array_remove(&mut self, path: &str, index: usize) -> Result<()>;
108
109 fn array_replace(&mut self, path: &str, index: usize, value: OperationValue) -> Result<()>;
114
115 fn array_len(&self, path: &str) -> Result<usize>;
120
121 fn array_build(&mut self, path: &str, elements: Vec<OperationValue>) -> Result<()>;
126
127 fn array_filter(&mut self, path: &str, predicate: &FilterPredicate) -> Result<()>;
132
133 fn array_map(&mut self, path: &str, transform: &TransformFunction) -> Result<()>;
138
139 fn array_reduce(
144 &mut self,
145 path: &str,
146 initial: OperationValue,
147 reducer: &ReduceFunction,
148 ) -> Result<OperationValue>;
149}
150
151#[derive(Debug, Clone, PartialEq, Eq, Default)]
158pub struct VectorClock {
159 inline: SmallVec<[(u64, u64); 8]>, replica_ids: SmallVec<[String; 8]>,
164}
165
166impl VectorClock {
167 #[inline]
169 #[must_use]
170 pub fn new() -> Self {
171 Self {
172 inline: SmallVec::new(),
173 replica_ids: SmallVec::new(),
174 }
175 }
176
177 #[inline]
178 fn hash_replica_id(replica_id: &str) -> u64 {
179 use std::hash::{Hash, Hasher};
180 let mut hasher = ahash::AHasher::default();
181 replica_id.hash(&mut hasher);
182 hasher.finish()
183 }
184
185 #[inline]
187 pub fn increment(&mut self, replica_id: &str) {
188 let hash = Self::hash_replica_id(replica_id);
189 for (h, ts) in &mut self.inline {
191 if *h == hash {
192 *ts += 1;
193 return;
194 }
195 }
196 self.inline.push((hash, 1));
198 self.replica_ids.push(replica_id.to_string());
199 }
200
201 #[inline]
203 #[must_use]
204 pub fn get(&self, replica_id: &str) -> u64 {
205 let hash = Self::hash_replica_id(replica_id);
206 for &(h, ts) in &self.inline {
207 if h == hash {
208 return ts;
209 }
210 }
211 0
212 }
213
214 #[inline]
216 pub fn merge(&mut self, other: &Self) {
217 for (i, &(hash, time)) in other.inline.iter().enumerate() {
218 let mut found = false;
219 for (h, ts) in &mut self.inline {
220 if *h == hash {
221 *ts = (*ts).max(time);
222 found = true;
223 break;
224 }
225 }
226 if !found {
227 self.inline.push((hash, time));
228 if i < other.replica_ids.len() {
229 self.replica_ids.push(other.replica_ids[i].clone());
230 }
231 }
232 }
233 }
234
235 #[inline]
237 #[must_use]
238 pub fn happened_before(&self, other: &Self) -> bool {
239 let mut dominated = false;
240 for &(hash, time) in &self.inline {
241 let other_time = other.get_by_hash(hash);
242 if time > other_time {
243 return false;
244 }
245 if time < other_time {
246 dominated = true;
247 }
248 }
249 for &(hash, time) in &other.inline {
250 if self.get_by_hash(hash) == 0 && time > 0 {
251 dominated = true;
252 }
253 }
254 dominated
255 }
256
257 #[inline]
258 fn get_by_hash(&self, hash: u64) -> u64 {
259 for &(h, ts) in &self.inline {
260 if h == hash {
261 return ts;
262 }
263 }
264 0
265 }
266
267 #[inline]
269 #[must_use]
270 pub fn concurrent_with(&self, other: &Self) -> bool {
271 !self.happened_before(other) && !other.happened_before(self)
272 }
273
274 #[must_use]
276 pub fn clocks(&self) -> std::collections::BTreeMap<String, u64> {
277 let mut map = std::collections::BTreeMap::new();
278 for (i, &(_, ts)) in self.inline.iter().enumerate() {
279 if i < self.replica_ids.len() {
280 map.insert(self.replica_ids[i].clone(), ts);
281 }
282 }
283 map
284 }
285}
286
287#[derive(Debug, Clone)]
289pub struct CrdtOperation {
290 pub operation: DsonOperation,
292 pub timestamp: u64,
294 pub replica_id: String,
296 pub vector_clock: VectorClock,
298}
299
300#[derive(Debug, Clone)]
302pub struct MergeConflict {
303 pub path: String,
305 pub local_value: OperationValue,
307 pub remote_value: OperationValue,
309 pub local_timestamp: u64,
311 pub remote_timestamp: u64,
313 pub resolved_value: Option<OperationValue>,
315}
316
317pub trait CrdtMerge {
319 fn merge_operation(&mut self, op: CrdtOperation) -> Result<Option<MergeConflict>>;
324
325 fn merge_field(
330 &mut self,
331 path: &str,
332 value: OperationValue,
333 timestamp: u64,
334 strategy: &MergeStrategy,
335 ) -> Result<Option<MergeConflict>>;
336
337 fn vector_clock(&self) -> &VectorClock;
339
340 fn replica_id(&self) -> &str;
342
343 fn resolve_conflict(
348 &mut self,
349 conflict: &MergeConflict,
350 strategy: &MergeStrategy,
351 ) -> Result<OperationValue>;
352}
353
354pub trait DeltaCrdt: CrdtMerge {
356 type Delta;
358
359 fn generate_delta(&self, since: &VectorClock) -> Self::Delta;
361
362 fn apply_delta(&mut self, delta: Self::Delta) -> Result<Vec<MergeConflict>>;
367
368 fn compact(&mut self);
370}
371
372pub trait OpBasedCrdt: CrdtMerge {
374 fn prepare(&self, op: &DsonOperation) -> Result<CrdtOperation>;
379
380 fn effect(&mut self, op: CrdtOperation) -> Result<Option<MergeConflict>>;
385
386 fn is_causally_ready(&self, op: &CrdtOperation) -> bool;
388
389 fn buffer_operation(&mut self, op: CrdtOperation);
391
392 fn process_buffered(&mut self) -> Result<Vec<MergeConflict>>;
397}
398
399pub trait StreamProcessor {
405 fn process_stream<I>(&mut self, lines: I) -> Result<Vec<String>>
410 where
411 I: Iterator<Item = String>;
412
413 fn stream_build(&mut self, path: &str, generator: &StreamGenerator) -> Result<()>;
418
419 fn stream_filter(&mut self, path: &str, predicate: &FilterPredicate) -> Result<()>;
424
425 fn stream_map(&mut self, path: &str, transform: &TransformFunction) -> Result<()>;
430
431 fn stream_emit(&mut self, path: &str, batch_size: usize) -> Result<Vec<OperationValue>>;
436}
437
438pub trait TapeProcessor {
440 type Node;
442
443 fn parse(json: &str) -> Result<Self>
448 where
449 Self: Sized;
450
451 fn nodes(&self) -> &[Self::Node];
453
454 fn serialize(&self) -> Result<String>;
459
460 fn resolve_path(&self, path: &str) -> Result<Option<usize>>;
465
466 fn skip_value(&self, index: usize) -> Result<usize>;
471}
472
473pub trait CanonicalProcessor {
479 fn add_operation(&mut self, op: DsonOperation);
481
482 fn compute_canonical(&mut self) -> Result<Vec<DsonOperation>>;
487
488 fn can_coalesce(&self, a: &DsonOperation, b: &DsonOperation) -> bool;
490
491 fn reorder(&mut self);
493}
494
495pub trait DsonImplementation:
501 DocumentProcessor + FieldOperations + ArrayOperations + SchemaAware
502{
503 fn name(&self) -> &str;
505
506 fn version(&self) -> &str;
508
509 fn features(&self) -> Vec<&str>;
511
512 fn characteristics(&self) -> ImplementationCharacteristics;
514}
515
516#[derive(Debug, Clone, Default)]
518#[allow(clippy::struct_excessive_bools)] pub struct ImplementationCharacteristics {
520 pub zero_copy: bool,
522 pub simd_accelerated: bool,
524 pub streaming: bool,
526 pub crdt_support: bool,
528 pub schema_filtering: bool,
530 pub parallel: bool,
532 pub memory_overhead: usize,
534 pub max_document_size: usize,
536}
537
538impl MergeStrategy {
543 #[inline]
545 #[must_use]
546 pub fn resolve(
547 &self,
548 local: &OperationValue,
549 remote: &OperationValue,
550 local_ts: u64,
551 remote_ts: u64,
552 ) -> OperationValue {
553 match self {
554 Self::LastWriteWins => {
555 if remote_ts > local_ts {
556 remote.clone()
557 } else {
558 local.clone()
559 }
560 }
561 Self::Max => {
562 match (local, remote) {
564 (OperationValue::NumberRef(a), OperationValue::NumberRef(b)) => {
565 let a_val: f64 = a.parse().unwrap_or(0.0);
566 let b_val: f64 = b.parse().unwrap_or(0.0);
567 if b_val > a_val {
568 remote.clone()
569 } else {
570 local.clone()
571 }
572 }
573 _ => {
574 if remote_ts > local_ts {
576 remote.clone()
577 } else {
578 local.clone()
579 }
580 }
581 }
582 }
583 Self::Min => match (local, remote) {
584 (OperationValue::NumberRef(a), OperationValue::NumberRef(b)) => {
585 let a_val: f64 = a.parse().unwrap_or(0.0);
586 let b_val: f64 = b.parse().unwrap_or(0.0);
587 if b_val < a_val {
588 remote.clone()
589 } else {
590 local.clone()
591 }
592 }
593 _ => {
594 if remote_ts > local_ts {
595 remote.clone()
596 } else {
597 local.clone()
598 }
599 }
600 },
601 Self::Additive => {
602 match (local, remote) {
604 (OperationValue::NumberRef(a), OperationValue::NumberRef(b)) => {
605 let a_val: f64 = a.parse().unwrap_or(0.0);
606 let b_val: f64 = b.parse().unwrap_or(0.0);
607 OperationValue::NumberRef((a_val + b_val).to_string())
608 }
609 (OperationValue::StringRef(a), OperationValue::StringRef(b)) => {
611 OperationValue::StringRef(format!("{a}{b}"))
612 }
613 _ => {
614 if remote_ts > local_ts {
615 remote.clone()
616 } else {
617 local.clone()
618 }
619 }
620 }
621 }
622 Self::Union => {
623 if remote_ts > local_ts {
625 remote.clone()
626 } else {
627 local.clone()
628 }
629 }
630 Self::Custom(_name) => {
631 if remote_ts > local_ts {
633 remote.clone()
634 } else {
635 local.clone()
636 }
637 }
638 }
639 }
640}
641
642#[cfg(test)]
647mod tests {
648 use super::*;
649
650 #[test]
651 fn test_vector_clock_basics() {
652 let mut vc1 = VectorClock::new();
653 vc1.increment("replica_a");
654 vc1.increment("replica_a");
655
656 let mut vc2 = VectorClock::new();
657 vc2.increment("replica_b");
658
659 assert_eq!(vc1.get("replica_a"), 2);
660 assert_eq!(vc1.get("replica_b"), 0);
661 assert_eq!(vc2.get("replica_b"), 1);
662
663 assert!(vc1.concurrent_with(&vc2));
665 }
666
667 #[test]
668 fn test_vector_clock_causality() {
669 let mut vc1 = VectorClock::new();
670 vc1.increment("replica_a");
671
672 let mut vc2 = vc1.clone();
673 vc2.increment("replica_a");
674
675 assert!(vc1.happened_before(&vc2));
677 assert!(!vc2.happened_before(&vc1));
678 }
679
680 #[test]
681 fn test_merge_strategy_lww() {
682 let local = OperationValue::StringRef("local".to_string());
683 let remote = OperationValue::StringRef("remote".to_string());
684
685 let result = MergeStrategy::LastWriteWins.resolve(&local, &remote, 1, 2);
686 assert_eq!(result, remote);
687
688 let result = MergeStrategy::LastWriteWins.resolve(&local, &remote, 2, 1);
689 assert_eq!(result, local);
690 }
691
692 #[test]
693 fn test_merge_strategy_max() {
694 let local = OperationValue::NumberRef("10".to_string());
695 let remote = OperationValue::NumberRef("20".to_string());
696
697 let result = MergeStrategy::Max.resolve(&local, &remote, 1, 1);
698 assert_eq!(result, remote);
699 }
700
701 #[test]
702 fn test_merge_strategy_additive() {
703 let local = OperationValue::NumberRef("10".to_string());
704 let remote = OperationValue::NumberRef("20".to_string());
705
706 let result = MergeStrategy::Additive.resolve(&local, &remote, 1, 1);
707 match result {
708 OperationValue::NumberRef(s) => assert_eq!(s, "30"),
709 _ => panic!("Expected NumberRef"),
710 }
711 }
712
713 #[test]
716 fn test_vector_clock_new() {
717 let vc = VectorClock::new();
718 assert_eq!(vc.get("any_replica"), 0);
719 }
720
721 #[test]
722 fn test_vector_clock_default() {
723 let vc = VectorClock::default();
724 assert_eq!(vc.get("any"), 0);
725 }
726
727 #[test]
728 fn test_vector_clock_increment_multiple_replicas() {
729 let mut vc = VectorClock::new();
730 vc.increment("a");
731 vc.increment("b");
732 vc.increment("c");
733 vc.increment("a");
734
735 assert_eq!(vc.get("a"), 2);
736 assert_eq!(vc.get("b"), 1);
737 assert_eq!(vc.get("c"), 1);
738 assert_eq!(vc.get("d"), 0);
739 }
740
741 #[test]
742 fn test_vector_clock_merge() {
743 let mut vc1 = VectorClock::new();
744 vc1.increment("a");
745 vc1.increment("a");
746
747 let mut vc2 = VectorClock::new();
748 vc2.increment("b");
749 vc2.increment("b");
750 vc2.increment("b");
751
752 vc1.merge(&vc2);
753
754 assert_eq!(vc1.get("a"), 2);
755 assert_eq!(vc1.get("b"), 3);
756 }
757
758 #[test]
759 fn test_vector_clock_merge_overlapping() {
760 let mut vc1 = VectorClock::new();
761 vc1.increment("a");
762
763 let mut vc2 = VectorClock::new();
764 vc2.increment("a");
765 vc2.increment("a");
766 vc2.increment("a");
767
768 vc1.merge(&vc2);
769 assert_eq!(vc1.get("a"), 3);
771 }
772
773 #[test]
774 fn test_vector_clock_clocks() {
775 let mut vc = VectorClock::new();
776 vc.increment("replica_a");
777 vc.increment("replica_b");
778
779 let clocks = vc.clocks();
780 assert!(clocks.contains_key("replica_a"));
781 assert!(clocks.contains_key("replica_b"));
782 }
783
784 #[test]
785 fn test_vector_clock_happened_before_empty() {
786 let vc1 = VectorClock::new();
787 let mut vc2 = VectorClock::new();
788 vc2.increment("a");
789
790 assert!(vc1.happened_before(&vc2));
792 }
793
794 #[test]
795 fn test_vector_clock_happened_before_equal() {
796 let mut vc1 = VectorClock::new();
797 vc1.increment("a");
798
799 let vc2 = vc1.clone();
800
801 assert!(!vc1.happened_before(&vc2));
803 assert!(!vc2.happened_before(&vc1));
804 }
805
806 #[test]
807 fn test_vector_clock_concurrent_with_both_have_unique() {
808 let mut vc1 = VectorClock::new();
809 vc1.increment("a");
810
811 let mut vc2 = VectorClock::new();
812 vc2.increment("b");
813
814 assert!(vc1.concurrent_with(&vc2));
816 assert!(vc2.concurrent_with(&vc1));
817 }
818
819 #[test]
820 fn test_vector_clock_clone() {
821 let mut vc = VectorClock::new();
822 vc.increment("a");
823 vc.increment("b");
824
825 let cloned = vc.clone();
826 assert_eq!(cloned.get("a"), 1);
827 assert_eq!(cloned.get("b"), 1);
828 }
829
830 #[test]
831 fn test_vector_clock_eq() {
832 let mut vc1 = VectorClock::new();
833 vc1.increment("a");
834
835 let mut vc2 = VectorClock::new();
836 vc2.increment("a");
837
838 let _ = vc1 == vc2;
840 }
841
842 #[test]
843 fn test_vector_clock_debug() {
844 let vc = VectorClock::new();
845 let debug = format!("{vc:?}");
846 assert!(debug.contains("VectorClock"));
847 }
848
849 #[test]
850 fn test_crdt_operation_fields() {
851 let op = CrdtOperation {
852 operation: DsonOperation::FieldAdd {
853 path: "test".to_string(),
854 value: OperationValue::StringRef("value".to_string()),
855 },
856 timestamp: 100,
857 replica_id: "replica_1".to_string(),
858 vector_clock: VectorClock::new(),
859 };
860
861 assert_eq!(op.timestamp, 100);
862 assert_eq!(op.replica_id, "replica_1");
863 }
864
865 #[test]
866 fn test_crdt_operation_clone() {
867 let op = CrdtOperation {
868 operation: DsonOperation::FieldAdd {
869 path: "test".to_string(),
870 value: OperationValue::Null,
871 },
872 timestamp: 50,
873 replica_id: "r1".to_string(),
874 vector_clock: VectorClock::new(),
875 };
876
877 let cloned = op;
878 assert_eq!(cloned.timestamp, 50);
879 }
880
881 #[test]
882 fn test_crdt_operation_debug() {
883 let op = CrdtOperation {
884 operation: DsonOperation::FieldDelete {
885 path: "test".to_string(),
886 },
887 timestamp: 0,
888 replica_id: "r".to_string(),
889 vector_clock: VectorClock::new(),
890 };
891
892 let debug = format!("{op:?}");
893 assert!(debug.contains("CrdtOperation"));
894 }
895
896 #[test]
897 fn test_merge_conflict_fields() {
898 let conflict = MergeConflict {
899 path: "user.name".to_string(),
900 local_value: OperationValue::StringRef("local".to_string()),
901 remote_value: OperationValue::StringRef("remote".to_string()),
902 local_timestamp: 100,
903 remote_timestamp: 200,
904 resolved_value: None,
905 };
906
907 assert_eq!(conflict.path, "user.name");
908 assert_eq!(conflict.local_timestamp, 100);
909 assert_eq!(conflict.remote_timestamp, 200);
910 assert!(conflict.resolved_value.is_none());
911 }
912
913 #[test]
914 fn test_merge_conflict_with_resolved() {
915 let conflict = MergeConflict {
916 path: "counter".to_string(),
917 local_value: OperationValue::NumberRef("10".to_string()),
918 remote_value: OperationValue::NumberRef("20".to_string()),
919 local_timestamp: 1,
920 remote_timestamp: 2,
921 resolved_value: Some(OperationValue::NumberRef("20".to_string())),
922 };
923
924 assert!(conflict.resolved_value.is_some());
925 }
926
927 #[test]
928 fn test_merge_conflict_clone() {
929 let conflict = MergeConflict {
930 path: "test".to_string(),
931 local_value: OperationValue::Null,
932 remote_value: OperationValue::Null,
933 local_timestamp: 0,
934 remote_timestamp: 0,
935 resolved_value: None,
936 };
937
938 let cloned = conflict;
939 assert_eq!(cloned.path, "test");
940 }
941
942 #[test]
943 fn test_merge_conflict_debug() {
944 let conflict = MergeConflict {
945 path: "p".to_string(),
946 local_value: OperationValue::Null,
947 remote_value: OperationValue::Null,
948 local_timestamp: 0,
949 remote_timestamp: 0,
950 resolved_value: None,
951 };
952
953 let debug = format!("{conflict:?}");
954 assert!(debug.contains("MergeConflict"));
955 }
956
957 #[test]
958 fn test_merge_strategy_min() {
959 let local = OperationValue::NumberRef("10".to_string());
960 let remote = OperationValue::NumberRef("5".to_string());
961
962 let result = MergeStrategy::Min.resolve(&local, &remote, 1, 1);
963 assert_eq!(result, remote); }
965
966 #[test]
967 fn test_merge_strategy_min_local_smaller() {
968 let local = OperationValue::NumberRef("3".to_string());
969 let remote = OperationValue::NumberRef("10".to_string());
970
971 let result = MergeStrategy::Min.resolve(&local, &remote, 1, 1);
972 assert_eq!(result, local); }
974
975 #[test]
976 fn test_merge_strategy_min_non_numeric() {
977 let local = OperationValue::StringRef("local".to_string());
978 let remote = OperationValue::StringRef("remote".to_string());
979
980 let result = MergeStrategy::Min.resolve(&local, &remote, 1, 2);
982 assert_eq!(result, remote);
983 }
984
985 #[test]
986 fn test_merge_strategy_max_local_larger() {
987 let local = OperationValue::NumberRef("100".to_string());
988 let remote = OperationValue::NumberRef("50".to_string());
989
990 let result = MergeStrategy::Max.resolve(&local, &remote, 1, 1);
991 assert_eq!(result, local); }
993
994 #[test]
995 fn test_merge_strategy_max_non_numeric() {
996 let local = OperationValue::StringRef("a".to_string());
997 let remote = OperationValue::StringRef("b".to_string());
998
999 let result = MergeStrategy::Max.resolve(&local, &remote, 1, 2);
1001 assert_eq!(result, remote);
1002 }
1003
1004 #[test]
1005 fn test_merge_strategy_additive_strings() {
1006 let local = OperationValue::StringRef("hello ".to_string());
1007 let remote = OperationValue::StringRef("world".to_string());
1008
1009 let result = MergeStrategy::Additive.resolve(&local, &remote, 1, 1);
1010 match result {
1011 OperationValue::StringRef(s) => assert_eq!(s, "hello world"),
1012 _ => panic!("Expected StringRef"),
1013 }
1014 }
1015
1016 #[test]
1017 fn test_merge_strategy_additive_non_matching() {
1018 let local = OperationValue::BoolRef(true);
1019 let remote = OperationValue::NumberRef("10".to_string());
1020
1021 let result = MergeStrategy::Additive.resolve(&local, &remote, 1, 2);
1023 assert_eq!(result, remote);
1024 }
1025
1026 #[test]
1027 fn test_merge_strategy_union() {
1028 let local = OperationValue::StringRef("a".to_string());
1029 let remote = OperationValue::StringRef("b".to_string());
1030
1031 let result = MergeStrategy::Union.resolve(&local, &remote, 1, 2);
1033 assert_eq!(result, remote);
1034 }
1035
1036 #[test]
1037 fn test_merge_strategy_custom() {
1038 let local = OperationValue::StringRef("local".to_string());
1039 let remote = OperationValue::StringRef("remote".to_string());
1040
1041 let result = MergeStrategy::Custom("my_custom".to_string()).resolve(&local, &remote, 1, 2);
1043 assert_eq!(result, remote);
1044 }
1045
1046 #[test]
1047 fn test_implementation_characteristics_default() {
1048 let chars = ImplementationCharacteristics::default();
1049 assert!(!chars.zero_copy);
1050 assert!(!chars.simd_accelerated);
1051 assert!(!chars.streaming);
1052 assert!(!chars.crdt_support);
1053 assert!(!chars.schema_filtering);
1054 assert!(!chars.parallel);
1055 assert_eq!(chars.memory_overhead, 0);
1056 assert_eq!(chars.max_document_size, 0);
1057 }
1058
1059 #[test]
1060 fn test_implementation_characteristics_custom() {
1061 let chars = ImplementationCharacteristics {
1062 zero_copy: true,
1063 simd_accelerated: true,
1064 streaming: true,
1065 crdt_support: true,
1066 schema_filtering: true,
1067 parallel: true,
1068 memory_overhead: 1024,
1069 max_document_size: 1_000_000,
1070 };
1071
1072 assert!(chars.zero_copy);
1073 assert!(chars.simd_accelerated);
1074 assert_eq!(chars.memory_overhead, 1024);
1075 }
1076
1077 #[test]
1078 fn test_implementation_characteristics_clone() {
1079 let chars = ImplementationCharacteristics {
1080 zero_copy: true,
1081 ..Default::default()
1082 };
1083
1084 let cloned = chars;
1085 assert!(cloned.zero_copy);
1086 }
1087
1088 #[test]
1089 fn test_implementation_characteristics_debug() {
1090 let chars = ImplementationCharacteristics::default();
1091 let debug = format!("{chars:?}");
1092 assert!(debug.contains("ImplementationCharacteristics"));
1093 }
1094
1095 #[test]
1096 fn test_vector_clock_hash_replica_id_consistency() {
1097 let hash1 = VectorClock::hash_replica_id("replica_a");
1099 let hash2 = VectorClock::hash_replica_id("replica_a");
1100 assert_eq!(hash1, hash2);
1101
1102 let hash3 = VectorClock::hash_replica_id("replica_b");
1104 assert_ne!(hash1, hash3);
1105 }
1106
1107 #[test]
1108 fn test_vector_clock_get_by_hash() {
1109 let mut vc = VectorClock::new();
1110 vc.increment("test_replica");
1111
1112 let hash = VectorClock::hash_replica_id("test_replica");
1113 assert_eq!(vc.get_by_hash(hash), 1);
1114
1115 let fake_hash = 12_345_678;
1117 assert_eq!(vc.get_by_hash(fake_hash), 0);
1118 }
1119
1120 #[test]
1121 fn test_merge_strategy_max_invalid_parse() {
1122 let local = OperationValue::NumberRef("invalid".to_string());
1124 let remote = OperationValue::NumberRef("5".to_string());
1125
1126 let result = MergeStrategy::Max.resolve(&local, &remote, 1, 1);
1127 assert_eq!(result, remote);
1129 }
1130
1131 #[test]
1132 fn test_merge_strategy_min_invalid_parse() {
1133 let local = OperationValue::NumberRef("invalid".to_string());
1134 let remote = OperationValue::NumberRef("5".to_string());
1135
1136 let result = MergeStrategy::Min.resolve(&local, &remote, 1, 1);
1137 assert_eq!(result, local);
1139 }
1140
1141 #[test]
1142 fn test_merge_strategy_additive_invalid_parse() {
1143 let local = OperationValue::NumberRef("invalid".to_string());
1144 let remote = OperationValue::NumberRef("10".to_string());
1145
1146 let result = MergeStrategy::Additive.resolve(&local, &remote, 1, 1);
1147 match result {
1149 OperationValue::NumberRef(s) => assert_eq!(s, "10"),
1150 _ => panic!("Expected NumberRef"),
1151 }
1152 }
1153
1154 #[test]
1155 fn test_vector_clock_merge_with_more_replicas() {
1156 let mut vc1 = VectorClock::new();
1157 vc1.increment("a");
1158
1159 let mut vc2 = VectorClock::new();
1160 vc2.increment("b");
1161 vc2.increment("c");
1162 vc2.increment("d");
1163
1164 vc1.merge(&vc2);
1165
1166 assert_eq!(vc1.get("a"), 1);
1167 assert_eq!(vc1.get("b"), 1);
1168 assert_eq!(vc1.get("c"), 1);
1169 assert_eq!(vc1.get("d"), 1);
1170 }
1171}