1use std::sync::Arc;
16
17use uqa_core::{Edge, Value, Vertex};
18
19#[derive(Clone)]
21pub enum VertexPredicate {
22 LabelEq(String),
24 PropertyEq { key: String, value: Value },
26 PropertyExists(String),
28 All(Vec<VertexPredicate>),
30 Custom(Arc<dyn Fn(&Vertex) -> bool + Send + Sync>),
33}
34
35impl VertexPredicate {
36 pub fn matches(&self, vertex: &Vertex) -> bool {
37 match self {
38 VertexPredicate::LabelEq(l) => vertex.label == *l,
39 VertexPredicate::PropertyEq { key, value } => vertex.properties.get(key) == Some(value),
40 VertexPredicate::PropertyExists(key) => vertex.properties.contains_key(key),
41 VertexPredicate::All(preds) => preds.iter().all(|p| p.matches(vertex)),
42 VertexPredicate::Custom(f) => f(vertex),
43 }
44 }
45}
46
47impl std::fmt::Debug for VertexPredicate {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 match self {
50 VertexPredicate::LabelEq(l) => write!(f, "LabelEq({l:?})"),
51 VertexPredicate::PropertyEq { key, value } => {
52 write!(f, "PropertyEq({key:?} = {value:?})")
53 }
54 VertexPredicate::PropertyExists(k) => write!(f, "PropertyExists({k:?})"),
55 VertexPredicate::All(ps) => f.debug_tuple("All").field(ps).finish(),
56 VertexPredicate::Custom(_) => write!(f, "Custom(<fn>)"),
57 }
58 }
59}
60
61#[derive(Clone)]
63pub enum EdgePredicate {
64 PropertyEq {
66 key: String,
67 value: Value,
68 },
69 PropertyExists(String),
70 All(Vec<EdgePredicate>),
71 Custom(Arc<dyn Fn(&Edge) -> bool + Send + Sync>),
72}
73
74impl EdgePredicate {
75 pub fn matches(&self, edge: &Edge) -> bool {
76 match self {
77 EdgePredicate::PropertyEq { key, value } => edge.properties.get(key) == Some(value),
78 EdgePredicate::PropertyExists(key) => edge.properties.contains_key(key),
79 EdgePredicate::All(preds) => preds.iter().all(|p| p.matches(edge)),
80 EdgePredicate::Custom(f) => f(edge),
81 }
82 }
83}
84
85impl std::fmt::Debug for EdgePredicate {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 match self {
88 EdgePredicate::PropertyEq { key, value } => {
89 write!(f, "PropertyEq({key:?} = {value:?})")
90 }
91 EdgePredicate::PropertyExists(k) => write!(f, "PropertyExists({k:?})"),
92 EdgePredicate::All(ps) => f.debug_tuple("All").field(ps).finish(),
93 EdgePredicate::Custom(_) => write!(f, "Custom(<fn>)"),
94 }
95 }
96}
97
98#[derive(Debug, Clone)]
100pub struct VertexPattern {
101 pub variable: String,
102 pub constraints: Vec<VertexPredicate>,
103}
104
105impl VertexPattern {
106 pub fn new(variable: impl Into<String>) -> Self {
107 Self {
108 variable: variable.into(),
109 constraints: Vec::new(),
110 }
111 }
112
113 pub fn with(mut self, predicate: VertexPredicate) -> Self {
114 self.constraints.push(predicate);
115 self
116 }
117
118 pub fn satisfies(&self, vertex: &Vertex) -> bool {
119 self.constraints.iter().all(|c| c.matches(vertex))
120 }
121}
122
123#[derive(Debug, Clone)]
127pub struct EdgePattern {
128 pub source_var: String,
129 pub target_var: String,
130 pub label: Option<String>,
131 pub constraints: Vec<EdgePredicate>,
132 pub negated: bool,
133}
134
135impl EdgePattern {
136 pub fn new(source: impl Into<String>, target: impl Into<String>) -> Self {
137 Self {
138 source_var: source.into(),
139 target_var: target.into(),
140 label: None,
141 constraints: Vec::new(),
142 negated: false,
143 }
144 }
145
146 pub fn with_label(mut self, label: impl Into<String>) -> Self {
147 self.label = Some(label.into());
148 self
149 }
150
151 pub fn with(mut self, predicate: EdgePredicate) -> Self {
152 self.constraints.push(predicate);
153 self
154 }
155
156 pub fn negated(mut self) -> Self {
157 self.negated = true;
158 self
159 }
160
161 pub fn satisfies(&self, edge: &Edge) -> bool {
162 if let Some(label) = &self.label {
163 if edge.label != *label {
164 return false;
165 }
166 }
167 self.constraints.iter().all(|c| c.matches(edge))
168 }
169}
170
171#[derive(Debug, Clone, Default)]
173pub struct GraphPattern {
174 pub vertex_patterns: Vec<VertexPattern>,
175 pub edge_patterns: Vec<EdgePattern>,
176}
177
178impl GraphPattern {
179 pub fn new() -> Self {
180 Self::default()
181 }
182
183 pub fn add_vertex(mut self, vp: VertexPattern) -> Self {
184 self.vertex_patterns.push(vp);
185 self
186 }
187
188 pub fn add_edge(mut self, ep: EdgePattern) -> Self {
189 self.edge_patterns.push(ep);
190 self
191 }
192}