1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use std::sync::Arc;
4
5use crate::types::VertexId;
6use crate::value::Value;
7
8#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
10pub struct Tag {
11 pub name: String,
12 pub properties: HashMap<Arc<str>, Value>,
13}
14
15impl std::hash::Hash for Tag {
17 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
18 self.name.hash(state);
19 let mut pairs: Vec<_> = self.properties.iter().collect();
21 pairs.sort_by_key(|&(k, _)| k);
22 for (k, v) in pairs {
23 k.hash(state);
24 v.hash(state);
25 }
26 }
27}
28
29impl Tag {
30 pub fn new(name: String, properties: HashMap<std::sync::Arc<str>, Value>) -> Self {
31 Self { name, properties }
32 }
33
34 pub fn estimated_size(&self) -> usize {
36 let mut size = std::mem::size_of::<Self>();
37
38 size += std::mem::size_of::<String>() + self.name.capacity();
40
41 size += self.properties.capacity()
43 * (8 + std::mem::size_of::<String>() + std::mem::size_of::<Value>());
44
45 for (k, v) in &self.properties {
46 size += k.len();
47 size += v.estimated_size();
48 }
49
50 size
51 }
52}
53
54#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
60pub struct Vertex {
61 pub vid: VertexId,
62 pub tag: Tag,
63}
64
65impl std::hash::Hash for Vertex {
67 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
68 self.vid.hash(state);
69 self.tag.hash(state);
70 }
71}
72
73impl Vertex {
74 pub fn new(vid: VertexId, tag: Tag) -> Self {
75 Self { vid, tag }
76 }
77
78 pub fn vid(&self) -> &VertexId {
79 &self.vid
80 }
81
82 pub fn tag(&self) -> &Tag {
83 &self.tag
84 }
85
86 pub fn tag_name(&self) -> &str {
87 &self.tag.name
88 }
89
90 pub fn properties(&self) -> &HashMap<Arc<str>, Value> {
91 &self.tag.properties
92 }
93
94 pub fn get_property(&self, prop_name: &str) -> Option<&Value> {
95 self.tag.properties.get(prop_name)
96 }
97
98 pub fn property_value(&self, property: &str) -> Option<Value> {
99 self.tag.properties.get(property).cloned()
100 }
101
102 pub fn has_properties(&self) -> bool {
103 !self.tag.properties.is_empty()
104 }
105
106 fn cmp_properties(
107 a: &HashMap<Arc<str>, Value>,
108 b: &HashMap<Arc<str>, Value>,
109 ) -> std::cmp::Ordering {
110 match a.len().cmp(&b.len()) {
111 std::cmp::Ordering::Equal => {
112 let mut a_sorted: Vec<_> = a.iter().collect();
113 let mut b_sorted: Vec<_> = b.iter().collect();
114 a_sorted.sort_by_key(|(k1, _)| *k1);
115 b_sorted.sort_by_key(|(k1, _)| *k1);
116
117 for ((k1, v1), (k2, v2)) in a_sorted.iter().zip(b_sorted.iter()) {
118 match k1.cmp(k2) {
119 std::cmp::Ordering::Equal => match v1.cmp(v2) {
120 std::cmp::Ordering::Equal => continue,
121 ord => return ord,
122 },
123 ord => return ord,
124 }
125 }
126 std::cmp::Ordering::Equal
127 }
128 ord => ord,
129 }
130 }
131}
132
133impl Ord for Vertex {
134 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
135 self.vid.cmp(&other.vid).then_with(|| {
137 self.tag
138 .name
139 .cmp(&other.tag.name)
140 .then_with(|| Vertex::cmp_properties(&self.tag.properties, &other.tag.properties))
141 })
142 }
143}
144
145impl PartialOrd for Vertex {
146 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
147 Some(self.cmp(other))
148 }
149}
150
151impl Vertex {
152 pub fn estimated_size(&self) -> usize {
153 let mut size = std::mem::size_of::<Self>();
154
155 size += self.vid.len();
156
157 size += self.tag.estimated_size();
158
159 size
160 }
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
168pub struct Edge {
169 pub src: VertexId,
170 pub dst: VertexId,
171 pub edge_type: String,
172 pub ranking: i64,
173 pub props: HashMap<Arc<str>, Value>,
174}
175
176impl Edge {
177 pub fn properties(&self) -> &HashMap<Arc<str>, Value> {
178 &self.props
179 }
180
181 pub fn src(&self) -> &VertexId {
182 &self.src
183 }
184
185 pub fn dst(&self) -> &VertexId {
186 &self.dst
187 }
188
189 pub fn edge_type(&self) -> &str {
190 &self.edge_type
191 }
192
193 pub fn ranking(&self) -> i64 {
194 self.ranking
195 }
196
197 pub fn get_all_properties(&self) -> &HashMap<Arc<str>, Value> {
198 &self.props
199 }
200
201 pub fn get_property(&self, name: &str) -> Option<&Value> {
203 self.props.get(name)
204 }
205
206 pub fn set_property(&mut self, name: Arc<str>, value: Value) {
208 self.props.insert(name, value);
209 }
210
211 pub fn remove_property(&mut self, name: &str) -> Option<Value> {
213 self.props.remove(name)
214 }
215
216 pub fn has_property(&self, name: &str) -> bool {
218 self.props.contains_key(name)
219 }
220
221 pub fn property_count(&self) -> usize {
223 self.props.len()
224 }
225
226 pub fn has_properties(&self) -> bool {
228 !self.props.is_empty()
229 }
230
231 pub fn new_empty(src: VertexId, dst: VertexId, edge_type: String, ranking: i64) -> Self {
232 Self {
233 src,
234 dst,
235 edge_type,
236 ranking,
237 props: HashMap::new(),
238 }
239 }
240
241 pub fn debug_string(&self) -> String {
242 format!(
243 "Edge({:?} -> {:?}, type: {}, ranking: {})",
244 self.src, self.dst, self.edge_type, self.ranking
245 )
246 }
247
248 pub fn estimated_size(&self) -> usize {
249 let mut size = std::mem::size_of::<Self>();
250
251 size += self.src.len();
252 size += self.dst.len();
253
254 size += std::mem::size_of::<String>() + self.edge_type.capacity();
255
256 size += self.props.capacity()
257 * (8 + std::mem::size_of::<Arc<str>>() + std::mem::size_of::<Value>());
258
259 for (k, v) in &self.props {
260 size += k.len();
261 size += v.estimated_size();
262 }
263
264 size
265 }
266}
267
268impl std::hash::Hash for Edge {
270 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
271 self.src.hash(state);
272 self.dst.hash(state);
273 self.edge_type.hash(state);
274 self.ranking.hash(state);
275 let mut pairs: Vec<_> = self.props.iter().collect();
277 pairs.sort_by_key(|&(k, _)| k);
278 for (k, v) in pairs {
279 k.hash(state);
280 v.hash(state);
281 }
282 }
283}
284
285impl Edge {
286 pub fn new(
287 src: VertexId,
288 dst: VertexId,
289 edge_type: String,
290 ranking: i64,
291 props: HashMap<Arc<str>, Value>,
292 ) -> Self {
293 Self {
294 src,
295 dst,
296 edge_type,
297 ranking,
298 props,
299 }
300 }
301}
302
303impl Edge {
304 fn cmp_properties(
305 a: &HashMap<Arc<str>, Value>,
306 b: &HashMap<Arc<str>, Value>,
307 ) -> std::cmp::Ordering {
308 match a.len().cmp(&b.len()) {
309 std::cmp::Ordering::Equal => {
310 let mut a_sorted: Vec<_> = a.iter().collect();
311 let mut b_sorted: Vec<_> = b.iter().collect();
312 a_sorted.sort_by_key(|(k1, _)| *k1);
313 b_sorted.sort_by_key(|(k1, _)| *k1);
314
315 for ((k1, v1), (k2, v2)) in a_sorted.iter().zip(b_sorted.iter()) {
316 match k1.cmp(k2) {
317 std::cmp::Ordering::Equal => match v1.cmp(v2) {
318 std::cmp::Ordering::Equal => continue,
319 ord => return ord,
320 },
321 ord => return ord,
322 }
323 }
324 std::cmp::Ordering::Equal
325 }
326 ord => ord,
327 }
328 }
329}
330
331impl Ord for Edge {
332 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
333 self.src
335 .cmp(&other.src)
336 .then_with(|| self.dst.cmp(&other.dst))
337 .then_with(|| self.edge_type.cmp(&other.edge_type))
338 .then_with(|| self.ranking.cmp(&other.ranking))
339 .then_with(|| Edge::cmp_properties(&self.props, &other.props))
340 }
341}
342
343impl PartialOrd for Edge {
344 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
345 Some(self.cmp(other))
346 }
347}
348
349#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
354pub struct EdgeDeleteKey {
355 pub src: VertexId,
356 pub dst: VertexId,
357 pub edge_type: String,
358 pub ranking: i64,
359}
360
361impl EdgeDeleteKey {
362 pub fn new(src: VertexId, dst: VertexId, edge_type: String, ranking: i64) -> Self {
363 Self {
364 src,
365 dst,
366 edge_type,
367 ranking,
368 }
369 }
370}
371
372#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
380pub struct EdgeHeader {
381 pub src: VertexId,
382 pub dst: VertexId,
383 pub edge_type: String,
384 pub ranking: i64,
385}
386
387impl EdgeHeader {
388 pub fn new(src: VertexId, dst: VertexId, edge_type: String, ranking: i64) -> Self {
389 Self {
390 src,
391 dst,
392 edge_type,
393 ranking,
394 }
395 }
396
397 pub fn from_edge(edge: &Edge) -> Self {
398 Self {
399 src: edge.src,
400 dst: edge.dst,
401 edge_type: edge.edge_type.clone(),
402 ranking: edge.ranking,
403 }
404 }
405
406 pub fn src(&self) -> &VertexId {
407 &self.src
408 }
409
410 pub fn dst(&self) -> &VertexId {
411 &self.dst
412 }
413
414 pub fn edge_type(&self) -> &str {
415 &self.edge_type
416 }
417
418 pub fn ranking(&self) -> i64 {
419 self.ranking
420 }
421
422 pub fn estimated_size(&self) -> usize {
423 std::mem::size_of::<Self>()
424 + self.src.len()
425 + self.dst.len()
426 + std::mem::size_of::<String>()
427 + self.edge_type.capacity()
428 }
429}
430
431impl std::hash::Hash for EdgeHeader {
432 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
433 self.src.hash(state);
434 self.dst.hash(state);
435 self.edge_type.hash(state);
436 self.ranking.hash(state);
437 }
438}
439
440impl Ord for EdgeHeader {
441 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
442 self.src
443 .cmp(&other.src)
444 .then_with(|| self.dst.cmp(&other.dst))
445 .then_with(|| self.edge_type.cmp(&other.edge_type))
446 .then_with(|| self.ranking.cmp(&other.ranking))
447 }
448}
449
450impl PartialOrd for EdgeHeader {
451 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
452 Some(self.cmp(other))
453 }
454}
455
456#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
458pub struct Step {
459 pub dst: Box<Vertex>,
460 pub edge: Box<Edge>,
461}
462
463impl std::hash::Hash for Step {
464 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
465 self.dst.hash(state);
466 self.edge.hash(state);
467 }
468}
469
470impl Ord for Step {
471 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
472 match self.dst.cmp(&other.dst) {
474 std::cmp::Ordering::Equal => self.edge.cmp(&other.edge),
475 ord => ord,
476 }
477 }
478}
479
480impl PartialOrd for Step {
481 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
482 Some(self.cmp(other))
483 }
484}
485
486impl Step {
487 pub fn new(dst: Vertex, edge_type: String, _edge_name: String, ranking: i64) -> Self {
488 let edge = Edge::new_empty(VertexId::new(), VertexId::new(), edge_type, ranking);
489 Self {
490 dst: Box::new(dst),
491 edge: Box::new(edge),
492 }
493 }
494
495 pub fn new_with_edge(dst: Vertex, edge: Edge) -> Self {
496 Self {
497 dst: Box::new(dst),
498 edge: Box::new(edge),
499 }
500 }
501
502 pub fn src_vid(&self) -> &VertexId {
503 &self.edge.src
504 }
505
506 pub fn dst_vid(&self) -> &VertexId {
507 &self.dst.vid
508 }
509
510 pub fn ranking(&self) -> i64 {
512 self.edge.ranking
513 }
514
515 pub fn estimated_size(&self) -> usize {
517 let mut size = std::mem::size_of::<Self>();
518
519 size += std::mem::size_of::<Box<Vertex>>() + self.dst.estimated_size();
521 size += std::mem::size_of::<Box<Edge>>() + self.edge.estimated_size();
522
523 size
524 }
525}
526
527#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
529pub struct Path {
530 pub src: Box<Vertex>,
531 pub steps: Vec<Step>,
532}
533
534impl Ord for Path {
535 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
536 self.src
538 .cmp(&other.src)
539 .then_with(|| self.steps.len().cmp(&other.steps.len()))
540 .then_with(|| self.cmp_steps(other))
541 }
542}
543
544impl Path {
545 fn cmp_steps(&self, other: &Self) -> std::cmp::Ordering {
547 for (step1, step2) in self.steps.iter().zip(other.steps.iter()) {
549 let step_cmp = step1.cmp(step2);
550 if step_cmp != std::cmp::Ordering::Equal {
551 return step_cmp;
552 }
553 }
554 std::cmp::Ordering::Equal
555 }
556}
557
558impl PartialOrd for Path {
559 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
560 Some(self.cmp(other))
561 }
562}
563
564impl std::hash::Hash for Path {
566 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
567 self.src.hash(state);
568 for step in &self.steps {
569 step.hash(state);
570 }
571 }
572}
573
574impl Path {
575 pub fn new(src: Vertex) -> Self {
577 Self {
578 src: Box::new(src),
579 steps: Vec::new(),
580 }
581 }
582
583 pub fn estimated_size(&self) -> usize {
585 let mut size = std::mem::size_of::<Self>();
586
587 size += std::mem::size_of::<Box<Vertex>>() + self.src.as_ref().estimated_size();
589
590 size += self.steps.capacity() * std::mem::size_of::<Step>();
592
593 for step in &self.steps {
594 size += step.estimated_size();
595 }
596
597 size
598 }
599
600 pub fn add_step(&mut self, step: Step) {
602 self.steps.push(step);
603 }
604
605 pub fn edges(&self) -> Vec<&Edge> {
607 self.steps.iter().map(|step| step.edge.as_ref()).collect()
608 }
609
610 pub fn len(&self) -> usize {
612 self.steps.len()
613 }
614
615 pub fn length(&self) -> usize {
617 self.steps.len()
618 }
619
620 pub fn steps(&self) -> &[Step] {
622 &self.steps
623 }
624
625 pub fn is_empty(&self) -> bool {
627 self.steps.is_empty()
628 }
629
630 pub fn has_duplicate_edges(&self) -> bool {
632 let mut seen_edges: std::collections::HashSet<(VertexId, VertexId, String)> =
633 std::collections::HashSet::new();
634
635 for step in &self.steps {
636 let edge_key = (step.edge.src, step.edge.dst, step.edge.edge_type.clone());
637
638 if !seen_edges.insert(edge_key) {
639 return true;
640 }
641 }
642
643 false
644 }
645
646 pub fn reverse(&mut self) {
647 if self.steps.is_empty() {
648 return;
649 }
650
651 let mut vertices = Vec::with_capacity(self.steps.len() + 1);
653 vertices.push((*self.src).clone());
654 for step in &self.steps {
655 vertices.push((*step.dst).clone());
656 }
657
658 let mut reversed_steps = Vec::with_capacity(self.steps.len());
662 for i in (0..self.steps.len()).rev() {
663 let mut edge = (*self.steps[i].edge).clone();
664 std::mem::swap(&mut edge.src, &mut edge.dst);
665 reversed_steps.push(Step {
666 dst: Box::new(vertices[i].clone()),
667 edge: Box::new(edge),
668 });
669 }
670 self.src = Box::new(vertices[vertices.len() - 1].clone());
671 self.steps = reversed_steps;
672 }
673
674 pub fn append_reverse(&mut self, other: Path) {
677 if other.steps.is_empty() {
678 return;
679 }
680
681 let mut other_steps: Vec<Step> = other.steps.into_iter().rev().collect();
683
684 for step in &mut other_steps {
686 std::mem::swap(&mut step.edge.src, &mut step.edge.dst);
687 }
688
689 self.steps.extend(other_steps);
691 }
692}
693
694impl Default for Path {
695 fn default() -> Self {
696 Self {
697 src: Box::new(Vertex::default()),
698 steps: Vec::new(),
699 }
700 }
701}