graphos_core/graph/lpg/
edge.rs1use graphos_common::types::{EdgeId, EpochId, NodeId, PropertyKey, Value};
4use std::collections::BTreeMap;
5use std::sync::Arc;
6
7#[derive(Debug, Clone)]
11pub struct Edge {
12 pub id: EdgeId,
14 pub src: NodeId,
16 pub dst: NodeId,
18 pub edge_type: Arc<str>,
20 pub properties: BTreeMap<PropertyKey, Value>,
22}
23
24impl Edge {
25 #[must_use]
27 pub fn new(id: EdgeId, src: NodeId, dst: NodeId, edge_type: impl Into<Arc<str>>) -> Self {
28 Self {
29 id,
30 src,
31 dst,
32 edge_type: edge_type.into(),
33 properties: BTreeMap::new(),
34 }
35 }
36
37 pub fn set_property(&mut self, key: impl Into<PropertyKey>, value: impl Into<Value>) {
39 self.properties.insert(key.into(), value.into());
40 }
41
42 #[must_use]
44 pub fn get_property(&self, key: &str) -> Option<&Value> {
45 self.properties.get(&PropertyKey::new(key))
46 }
47
48 pub fn remove_property(&mut self, key: &str) -> Option<Value> {
50 self.properties.remove(&PropertyKey::new(key))
51 }
52
53 #[must_use]
57 pub fn other_endpoint(&self, node: NodeId) -> Option<NodeId> {
58 if node == self.src {
59 Some(self.dst)
60 } else if node == self.dst {
61 Some(self.src)
62 } else {
63 None
64 }
65 }
66}
67
68#[repr(C)]
72#[derive(Debug, Clone, Copy)]
73pub struct EdgeRecord {
74 pub id: EdgeId,
76 pub src: NodeId,
78 pub dst: NodeId,
80 pub type_id: u32,
82 pub props_offset: u32,
84 pub props_count: u16,
86 pub flags: EdgeFlags,
88 pub epoch: EpochId,
90}
91
92impl EdgeRecord {
93 pub const FLAG_DELETED: u16 = 1 << 0;
95 pub const FLAG_HAS_VERSION: u16 = 1 << 1;
97
98 #[must_use]
100 pub const fn new(id: EdgeId, src: NodeId, dst: NodeId, type_id: u32, epoch: EpochId) -> Self {
101 Self {
102 id,
103 src,
104 dst,
105 type_id,
106 props_offset: 0,
107 props_count: 0,
108 flags: EdgeFlags(0),
109 epoch,
110 }
111 }
112
113 #[must_use]
115 pub const fn is_deleted(&self) -> bool {
116 self.flags.contains(Self::FLAG_DELETED)
117 }
118
119 pub fn set_deleted(&mut self, deleted: bool) {
121 if deleted {
122 self.flags.set(Self::FLAG_DELETED);
123 } else {
124 self.flags.clear(Self::FLAG_DELETED);
125 }
126 }
127}
128
129#[repr(transparent)]
131#[derive(Debug, Clone, Copy, Default)]
132pub struct EdgeFlags(pub u16);
133
134impl EdgeFlags {
135 #[must_use]
137 pub const fn contains(&self, flag: u16) -> bool {
138 (self.0 & flag) != 0
139 }
140
141 pub fn set(&mut self, flag: u16) {
143 self.0 |= flag;
144 }
145
146 pub fn clear(&mut self, flag: u16) {
148 self.0 &= !flag;
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155
156 #[test]
157 fn test_edge_creation() {
158 let edge = Edge::new(
159 EdgeId::new(1),
160 NodeId::new(10),
161 NodeId::new(20),
162 "KNOWS",
163 );
164
165 assert_eq!(edge.id, EdgeId::new(1));
166 assert_eq!(edge.src, NodeId::new(10));
167 assert_eq!(edge.dst, NodeId::new(20));
168 assert_eq!(edge.edge_type.as_ref(), "KNOWS");
169 }
170
171 #[test]
172 fn test_edge_properties() {
173 let mut edge = Edge::new(
174 EdgeId::new(1),
175 NodeId::new(10),
176 NodeId::new(20),
177 "KNOWS",
178 );
179
180 edge.set_property("since", 2020i64);
181 edge.set_property("weight", 1.5f64);
182
183 assert_eq!(edge.get_property("since").and_then(|v| v.as_int64()), Some(2020));
184 assert_eq!(edge.get_property("weight").and_then(|v| v.as_float64()), Some(1.5));
185 }
186
187 #[test]
188 fn test_edge_other_endpoint() {
189 let edge = Edge::new(
190 EdgeId::new(1),
191 NodeId::new(10),
192 NodeId::new(20),
193 "KNOWS",
194 );
195
196 assert_eq!(edge.other_endpoint(NodeId::new(10)), Some(NodeId::new(20)));
197 assert_eq!(edge.other_endpoint(NodeId::new(20)), Some(NodeId::new(10)));
198 assert_eq!(edge.other_endpoint(NodeId::new(30)), None);
199 }
200
201 #[test]
202 fn test_edge_record_flags() {
203 let mut record = EdgeRecord::new(
204 EdgeId::new(1),
205 NodeId::new(10),
206 NodeId::new(20),
207 0,
208 EpochId::INITIAL,
209 );
210
211 assert!(!record.is_deleted());
212 record.set_deleted(true);
213 assert!(record.is_deleted());
214 }
215
216 #[test]
217 fn test_edge_record_size() {
218 let size = std::mem::size_of::<EdgeRecord>();
220 assert!(size <= 64, "EdgeRecord is {} bytes", size);
222 }
223}