leptos_sync_core/crdt/graph/
vertex.rs

1//! Graph vertex operations and types
2
3use super::super::{CRDT, Mergeable, ReplicaId};
4use serde::{Deserialize, Serialize};
5use std::error::Error;
6use uuid::Uuid;
7
8/// Custom error type for graph operations
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct GraphError {
11    message: String,
12}
13
14impl GraphError {
15    pub fn new(message: String) -> Self {
16        Self { message }
17    }
18}
19
20impl std::fmt::Display for GraphError {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        write!(f, "GraphError: {}", self.message)
23    }
24}
25
26impl Error for GraphError {}
27
28/// Unique identifier for a graph vertex
29#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
30pub struct VertexId {
31    /// Unique identifier for the vertex
32    pub id: Uuid,
33    /// Replica that created the vertex
34    pub replica: ReplicaId,
35}
36
37impl VertexId {
38    /// Create a new vertex ID
39    pub fn new(replica: ReplicaId) -> Self {
40        Self {
41            id: Uuid::new_v4(),
42            replica,
43        }
44    }
45
46    /// Create a vertex ID from existing UUID and replica
47    pub fn from_parts(id: Uuid, replica: ReplicaId) -> Self {
48        Self { id, replica }
49    }
50}
51
52/// Metadata for a graph vertex
53#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
54pub struct VertexMetadata {
55    /// When the vertex was created
56    pub created_at: u64,
57    /// When the vertex was last modified
58    pub modified_at: u64,
59    /// Whether the vertex is marked as deleted
60    pub deleted: bool,
61    /// Replica that last modified the vertex
62    pub last_modified_by: ReplicaId,
63}
64
65impl VertexMetadata {
66    /// Create new metadata
67    pub fn new(replica: ReplicaId, timestamp: u64) -> Self {
68        Self {
69            created_at: timestamp,
70            modified_at: timestamp,
71            deleted: false,
72            last_modified_by: replica,
73        }
74    }
75
76    /// Mark as modified
77    pub fn mark_modified(&mut self, replica: ReplicaId, timestamp: u64) {
78        self.modified_at = timestamp;
79        self.last_modified_by = replica;
80    }
81
82    /// Mark as deleted
83    pub fn mark_deleted(&mut self, replica: ReplicaId, timestamp: u64) {
84        self.deleted = true;
85        self.mark_modified(replica, timestamp);
86    }
87}
88
89/// A graph vertex with its metadata
90#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
91pub struct Vertex<T> {
92    /// Unique identifier
93    pub id: VertexId,
94    /// The actual value
95    pub value: T,
96    /// Metadata
97    pub metadata: VertexMetadata,
98}
99
100impl<T> Vertex<T> {
101    /// Create a new vertex
102    pub fn new(value: T, replica: ReplicaId, timestamp: u64) -> Self {
103        Self {
104            id: VertexId::new(replica),
105            value,
106            metadata: VertexMetadata::new(replica, timestamp),
107        }
108    }
109
110    /// Mark as modified
111    pub fn mark_modified(&mut self, replica: ReplicaId, timestamp: u64) {
112        self.metadata.mark_modified(replica, timestamp);
113    }
114
115    /// Mark as deleted
116    pub fn mark_deleted(&mut self, replica: ReplicaId, timestamp: u64) {
117        self.metadata.mark_deleted(replica, timestamp);
118    }
119}
120
121#[cfg(test)]
122mod tests {
123    use super::super::super::ReplicaId;
124    use super::*;
125    use uuid::Uuid;
126
127    fn create_replica(id: u64) -> ReplicaId {
128        ReplicaId::from(Uuid::from_u64_pair(0, id))
129    }
130
131    #[test]
132    fn test_vertex_id_creation() {
133        let replica = create_replica(1);
134        let vertex_id = VertexId::new(replica);
135
136        assert_eq!(vertex_id.replica, replica);
137        assert_ne!(vertex_id.id, Uuid::nil());
138    }
139
140    #[test]
141    fn test_vertex_creation() {
142        let replica = create_replica(1);
143        let timestamp = 1234567890;
144        let vertex = Vertex::new("test_value", replica, timestamp);
145
146        assert_eq!(vertex.value, "test_value");
147        assert_eq!(vertex.metadata.created_at, timestamp);
148        assert_eq!(vertex.metadata.modified_at, timestamp);
149        assert_eq!(vertex.metadata.deleted, false);
150        assert_eq!(vertex.metadata.last_modified_by, replica);
151    }
152
153    #[test]
154    fn test_vertex_metadata_operations() {
155        let replica = create_replica(1);
156        let timestamp = 1234567890;
157        let mut metadata = VertexMetadata::new(replica, timestamp);
158
159        // Test modification
160        let new_timestamp = 1234567891;
161        metadata.mark_modified(replica, new_timestamp);
162        assert_eq!(metadata.modified_at, new_timestamp);
163
164        // Test deletion
165        let delete_timestamp = 1234567892;
166        metadata.mark_deleted(replica, delete_timestamp);
167        assert_eq!(metadata.deleted, true);
168        assert_eq!(metadata.modified_at, delete_timestamp);
169    }
170}