ruvector_graph/
edge.rs

1//! Edge (relationship) implementation
2
3use crate::types::{EdgeId, NodeId, Properties, PropertyValue};
4use bincode::{Decode, Encode};
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7use uuid::Uuid;
8
9#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)]
10pub struct Edge {
11    pub id: EdgeId,
12    pub from: NodeId,
13    pub to: NodeId,
14    pub edge_type: String,
15    pub properties: Properties,
16}
17
18impl Edge {
19    /// Create a new edge with all fields
20    pub fn new(
21        id: EdgeId,
22        from: NodeId,
23        to: NodeId,
24        edge_type: String,
25        properties: Properties,
26    ) -> Self {
27        Self {
28            id,
29            from,
30            to,
31            edge_type,
32            properties,
33        }
34    }
35
36    /// Create a new edge with auto-generated ID and empty properties
37    pub fn create(from: NodeId, to: NodeId, edge_type: impl Into<String>) -> Self {
38        Self {
39            id: Uuid::new_v4().to_string(),
40            from,
41            to,
42            edge_type: edge_type.into(),
43            properties: HashMap::new(),
44        }
45    }
46
47    /// Get a property value by key
48    pub fn get_property(&self, key: &str) -> Option<&PropertyValue> {
49        self.properties.get(key)
50    }
51
52    /// Set a property value
53    pub fn set_property(&mut self, key: impl Into<String>, value: PropertyValue) {
54        self.properties.insert(key.into(), value);
55    }
56}
57
58/// Builder for constructing Edge instances
59#[derive(Debug, Clone)]
60pub struct EdgeBuilder {
61    id: Option<EdgeId>,
62    from: NodeId,
63    to: NodeId,
64    edge_type: String,
65    properties: Properties,
66}
67
68impl EdgeBuilder {
69    /// Create a new edge builder with required fields
70    pub fn new(from: NodeId, to: NodeId, edge_type: impl Into<String>) -> Self {
71        Self {
72            id: None,
73            from,
74            to,
75            edge_type: edge_type.into(),
76            properties: HashMap::new(),
77        }
78    }
79
80    /// Set a custom edge ID
81    pub fn id(mut self, id: impl Into<String>) -> Self {
82        self.id = Some(id.into());
83        self
84    }
85
86    /// Add a property to the edge
87    pub fn property<V: Into<PropertyValue>>(mut self, key: impl Into<String>, value: V) -> Self {
88        self.properties.insert(key.into(), value.into());
89        self
90    }
91
92    /// Add multiple properties to the edge
93    pub fn properties(mut self, props: Properties) -> Self {
94        self.properties.extend(props);
95        self
96    }
97
98    /// Build the edge
99    pub fn build(self) -> Edge {
100        Edge {
101            id: self.id.unwrap_or_else(|| Uuid::new_v4().to_string()),
102            from: self.from,
103            to: self.to,
104            edge_type: self.edge_type,
105            properties: self.properties,
106        }
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn test_edge_builder() {
116        let edge = EdgeBuilder::new("node1".to_string(), "node2".to_string(), "KNOWS")
117            .property("since", 2020i64)
118            .build();
119
120        assert_eq!(edge.from, "node1");
121        assert_eq!(edge.to, "node2");
122        assert_eq!(edge.edge_type, "KNOWS");
123        assert_eq!(
124            edge.get_property("since"),
125            Some(&PropertyValue::Integer(2020))
126        );
127    }
128
129    #[test]
130    fn test_edge_create() {
131        let edge = Edge::create("a".to_string(), "b".to_string(), "FOLLOWS");
132        assert_eq!(edge.from, "a");
133        assert_eq!(edge.to, "b");
134        assert_eq!(edge.edge_type, "FOLLOWS");
135        assert!(edge.properties.is_empty());
136    }
137
138    #[test]
139    fn test_edge_new() {
140        let edge = Edge::new(
141            "e1".to_string(),
142            "n1".to_string(),
143            "n2".to_string(),
144            "LIKES".to_string(),
145            HashMap::new(),
146        );
147        assert_eq!(edge.id, "e1");
148        assert_eq!(edge.edge_type, "LIKES");
149    }
150}