grafeo_core/graph/lpg/
edge.rs1use grafeo_common::types::{EdgeId, EpochId, NodeId, PropertyKey, Value};
7use std::collections::BTreeMap;
8use std::sync::Arc;
9
10#[derive(Debug, Clone)]
31pub struct Edge {
32 pub id: EdgeId,
34 pub src: NodeId,
36 pub dst: NodeId,
38 pub edge_type: Arc<str>,
40 pub properties: BTreeMap<PropertyKey, Value>,
42}
43
44impl Edge {
45 #[must_use]
47 pub fn new(id: EdgeId, src: NodeId, dst: NodeId, edge_type: impl Into<Arc<str>>) -> Self {
48 Self {
49 id,
50 src,
51 dst,
52 edge_type: edge_type.into(),
53 properties: BTreeMap::new(),
54 }
55 }
56
57 pub fn set_property(&mut self, key: impl Into<PropertyKey>, value: impl Into<Value>) {
59 self.properties.insert(key.into(), value.into());
60 }
61
62 #[must_use]
64 pub fn get_property(&self, key: &str) -> Option<&Value> {
65 self.properties.get(&PropertyKey::new(key))
66 }
67
68 pub fn remove_property(&mut self, key: &str) -> Option<Value> {
70 self.properties.remove(&PropertyKey::new(key))
71 }
72
73 #[must_use]
78 pub fn other_endpoint(&self, node: NodeId) -> Option<NodeId> {
79 if node == self.src {
80 Some(self.dst)
81 } else if node == self.dst {
82 Some(self.src)
83 } else {
84 None
85 }
86 }
87}
88
89#[repr(C)]
94#[derive(Debug, Clone, Copy)]
95pub struct EdgeRecord {
96 pub id: EdgeId,
98 pub src: NodeId,
100 pub dst: NodeId,
102 pub type_id: u32,
104 pub props_offset: u32,
106 pub props_count: u16,
108 pub flags: EdgeFlags,
110 pub epoch: EpochId,
112}
113
114impl EdgeRecord {
115 pub const FLAG_DELETED: u16 = 1 << 0;
117 pub const FLAG_HAS_VERSION: u16 = 1 << 1;
119
120 #[must_use]
122 pub const fn new(id: EdgeId, src: NodeId, dst: NodeId, type_id: u32, epoch: EpochId) -> Self {
123 Self {
124 id,
125 src,
126 dst,
127 type_id,
128 props_offset: 0,
129 props_count: 0,
130 flags: EdgeFlags(0),
131 epoch,
132 }
133 }
134
135 #[must_use]
137 pub const fn is_deleted(&self) -> bool {
138 self.flags.contains(Self::FLAG_DELETED)
139 }
140
141 pub fn set_deleted(&mut self, deleted: bool) {
143 if deleted {
144 self.flags.set(Self::FLAG_DELETED);
145 } else {
146 self.flags.clear(Self::FLAG_DELETED);
147 }
148 }
149}
150
151#[repr(transparent)]
153#[derive(Debug, Clone, Copy, Default)]
154pub struct EdgeFlags(pub u16);
155
156impl EdgeFlags {
157 #[must_use]
159 pub const fn contains(&self, flag: u16) -> bool {
160 (self.0 & flag) != 0
161 }
162
163 pub fn set(&mut self, flag: u16) {
165 self.0 |= flag;
166 }
167
168 pub fn clear(&mut self, flag: u16) {
170 self.0 &= !flag;
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 #[test]
179 fn test_edge_creation() {
180 let edge = Edge::new(EdgeId::new(1), NodeId::new(10), NodeId::new(20), "KNOWS");
181
182 assert_eq!(edge.id, EdgeId::new(1));
183 assert_eq!(edge.src, NodeId::new(10));
184 assert_eq!(edge.dst, NodeId::new(20));
185 assert_eq!(edge.edge_type.as_ref(), "KNOWS");
186 }
187
188 #[test]
189 fn test_edge_properties() {
190 let mut edge = Edge::new(EdgeId::new(1), NodeId::new(10), NodeId::new(20), "KNOWS");
191
192 edge.set_property("since", 2020i64);
193 edge.set_property("weight", 1.5f64);
194
195 assert_eq!(
196 edge.get_property("since").and_then(|v| v.as_int64()),
197 Some(2020)
198 );
199 assert_eq!(
200 edge.get_property("weight").and_then(|v| v.as_float64()),
201 Some(1.5)
202 );
203 }
204
205 #[test]
206 fn test_edge_other_endpoint() {
207 let edge = Edge::new(EdgeId::new(1), NodeId::new(10), NodeId::new(20), "KNOWS");
208
209 assert_eq!(edge.other_endpoint(NodeId::new(10)), Some(NodeId::new(20)));
210 assert_eq!(edge.other_endpoint(NodeId::new(20)), Some(NodeId::new(10)));
211 assert_eq!(edge.other_endpoint(NodeId::new(30)), None);
212 }
213
214 #[test]
215 fn test_edge_record_flags() {
216 let mut record = EdgeRecord::new(
217 EdgeId::new(1),
218 NodeId::new(10),
219 NodeId::new(20),
220 0,
221 EpochId::INITIAL,
222 );
223
224 assert!(!record.is_deleted());
225 record.set_deleted(true);
226 assert!(record.is_deleted());
227 }
228
229 #[test]
230 fn test_edge_record_size() {
231 let size = std::mem::size_of::<EdgeRecord>();
233 assert!(size <= 64, "EdgeRecord is {} bytes", size);
235 }
236}