selene_graph/graph_types/
endpoint.rs1use std::fmt;
4
5use serde::{Deserialize, Serialize};
6
7#[derive(
16 Clone,
17 Debug,
18 Deserialize,
19 Eq,
20 Hash,
21 PartialEq,
22 rkyv::Archive,
23 rkyv::Deserialize,
24 rkyv::Serialize,
25 Serialize,
26)]
27pub enum EdgeEndpointDef {
28 Any,
30 NodeType(u32),
32 OneOf(Vec<u32>),
35}
36
37impl EdgeEndpointDef {
38 #[must_use]
50 pub fn one_of(indices: impl IntoIterator<Item = u32>) -> Self {
51 let mut buf: Vec<u32> = indices.into_iter().collect();
52 buf.sort_unstable();
53 buf.dedup();
54 assert!(
55 !buf.is_empty(),
56 "EdgeEndpointDef::one_of called with empty index set"
57 );
58 match buf.len() {
59 1 => Self::NodeType(buf[0]),
60 _ => Self::OneOf(buf),
61 }
62 }
63
64 #[must_use]
66 pub fn matches_node_type(&self, node_type: u32) -> bool {
67 match self {
68 Self::Any => true,
69 Self::NodeType(expected) => *expected == node_type,
70 Self::OneOf(indices) => indices.binary_search(&node_type).is_ok(),
71 }
72 }
73
74 #[must_use]
76 pub fn overlaps(&self, other: &Self) -> bool {
77 match (self, other) {
78 (Self::Any, _) | (_, Self::Any) => true,
79 (Self::NodeType(left), Self::NodeType(right)) => left == right,
80 (Self::NodeType(index), Self::OneOf(indices))
81 | (Self::OneOf(indices), Self::NodeType(index)) => indices.binary_search(index).is_ok(),
82 (Self::OneOf(left), Self::OneOf(right)) => sorted_slices_intersect(left, right),
83 }
84 }
85
86 #[must_use]
93 pub const fn node_type_index(&self) -> Option<u32> {
94 match self {
95 Self::Any | Self::OneOf(_) => None,
96 Self::NodeType(index) => Some(*index),
97 }
98 }
99}
100
101impl fmt::Display for EdgeEndpointDef {
102 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
103 match self {
104 Self::Any => formatter.write_str("Any"),
105 Self::NodeType(index) => write!(formatter, "{index}"),
106 Self::OneOf(indices) => {
107 formatter.write_str("OneOf(")?;
108 for (position, index) in indices.iter().enumerate() {
109 if position > 0 {
110 formatter.write_str(", ")?;
111 }
112 write!(formatter, "{index}")?;
113 }
114 formatter.write_str(")")
115 }
116 }
117 }
118}
119
120fn sorted_slices_intersect(left: &[u32], right: &[u32]) -> bool {
121 let (mut i, mut j) = (0, 0);
122 while i < left.len() && j < right.len() {
123 match left[i].cmp(&right[j]) {
124 std::cmp::Ordering::Less => i += 1,
125 std::cmp::Ordering::Greater => j += 1,
126 std::cmp::Ordering::Equal => return true,
127 }
128 }
129 false
130}