leptos_sync_core/crdt/advanced/
common.rs

1//! Common types and error handling for advanced CRDTs
2
3use super::super::ReplicaId;
4use serde::{Deserialize, Serialize};
5use std::fmt;
6use uuid::Uuid;
7
8/// Error types for advanced CRDT operations
9#[derive(Debug, Clone, PartialEq)]
10pub enum AdvancedCrdtError {
11    /// Invalid position in sequence
12    InvalidPosition(String),
13    /// Element not found
14    ElementNotFound(String),
15    /// Invalid parent-child relationship
16    InvalidRelationship(String),
17    /// Cycle detected in DAG
18    CycleDetected(String),
19    /// Invalid operation for CRDT type
20    InvalidOperation(String),
21    /// Merge operation failed
22    MergeError(String),
23}
24
25impl fmt::Display for AdvancedCrdtError {
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        match self {
28            AdvancedCrdtError::InvalidPosition(msg) => write!(f, "Invalid position: {}", msg),
29            AdvancedCrdtError::ElementNotFound(msg) => write!(f, "Element not found: {}", msg),
30            AdvancedCrdtError::InvalidRelationship(msg) => write!(f, "Invalid relationship: {}", msg),
31            AdvancedCrdtError::CycleDetected(msg) => write!(f, "Cycle detected: {}", msg),
32            AdvancedCrdtError::InvalidOperation(msg) => write!(f, "Invalid operation: {}", msg),
33            AdvancedCrdtError::MergeError(msg) => write!(f, "Merge error: {}", msg),
34        }
35    }
36}
37
38impl std::error::Error for AdvancedCrdtError {}
39
40/// Position identifier for RGA and LSEQ
41#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
42pub struct PositionId {
43    /// Replica ID that created this position
44    pub replica_id: ReplicaId,
45    /// Logical timestamp
46    pub timestamp: u64,
47    /// Additional disambiguation value
48    pub disambiguation: u64,
49}
50
51impl PositionId {
52    /// Create a new position ID
53    pub fn new(replica_id: ReplicaId, timestamp: u64, disambiguation: u64) -> Self {
54        Self {
55            replica_id,
56            timestamp,
57            disambiguation,
58        }
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65    use super::super::super::ReplicaId;
66    use uuid::Uuid;
67
68    fn create_replica(id: u64) -> ReplicaId {
69        ReplicaId::from(Uuid::from_u64_pair(0, id))
70    }
71
72    #[test]
73    fn test_position_id_creation() {
74        let replica = create_replica(1);
75        let position = PositionId::new(replica, 12345, 67890);
76        
77        assert_eq!(position.replica_id, replica);
78        assert_eq!(position.timestamp, 12345);
79        assert_eq!(position.disambiguation, 67890);
80    }
81
82    #[test]
83    fn test_position_id_ordering() {
84        let replica1 = create_replica(1);
85        let replica2 = create_replica(2);
86        
87        let pos1 = PositionId::new(replica1, 100, 10);
88        let pos2 = PositionId::new(replica1, 200, 10);
89        let pos3 = PositionId::new(replica2, 100, 10);
90        
91        assert!(pos1 < pos2);
92        assert!(pos1 < pos3);
93        assert!(pos2 > pos3);
94    }
95
96    #[test]
97    fn test_advanced_crdt_error_display() {
98        let error = AdvancedCrdtError::InvalidPosition("test".to_string());
99        assert_eq!(format!("{}", error), "Invalid position: test");
100        
101        let error = AdvancedCrdtError::ElementNotFound("missing".to_string());
102        assert_eq!(format!("{}", error), "Element not found: missing");
103    }
104}