1use std::collections::HashMap;
13use std::fmt;
14use std::hash::{Hash, Hasher};
15use std::sync::Arc;
16
17use crate::json;
18use crate::serde_json::{Map as JsonMap, Value as JsonValue};
19
20#[derive(Debug, Clone, PartialEq, Eq, Hash)]
22pub struct Var {
23 name: String,
24}
25
26impl Var {
27 pub fn new(name: &str) -> Self {
29 Self {
30 name: name.to_string(),
31 }
32 }
33
34 pub fn name(&self) -> &str {
36 &self.name
37 }
38
39 pub fn is_anonymous(&self) -> bool {
41 self.name.starts_with('_')
42 }
43}
44
45impl fmt::Display for Var {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 write!(f, "?{}", self.name)
48 }
49}
50
51impl From<&str> for Var {
52 fn from(s: &str) -> Self {
53 let name = s.strip_prefix('?').unwrap_or(s);
55 Self::new(name)
56 }
57}
58
59#[derive(Debug, Clone)]
61pub enum Value {
62 Node(String),
64 Edge(String),
66 String(String),
68 Integer(i64),
70 Float(f64),
72 Boolean(bool),
74 Uri(String),
76 Null,
78}
79
80impl Value {
81 pub fn as_string(&self) -> Option<&str> {
83 match self {
84 Value::String(s) | Value::Node(s) | Value::Edge(s) | Value::Uri(s) => Some(s),
85 _ => None,
86 }
87 }
88
89 pub fn as_integer(&self) -> Option<i64> {
91 match self {
92 Value::Integer(i) => Some(*i),
93 _ => None,
94 }
95 }
96
97 pub fn as_float(&self) -> Option<f64> {
99 match self {
100 Value::Float(f) => Some(*f),
101 Value::Integer(i) => Some(*i as f64),
102 _ => None,
103 }
104 }
105
106 pub fn is_null(&self) -> bool {
108 matches!(self, Value::Null)
109 }
110
111 pub fn to_json(&self) -> JsonValue {
113 match self {
114 Value::Node(id) => json!({ "type": "node", "id": id }),
115 Value::Edge(id) => json!({ "type": "edge", "id": id }),
116 Value::String(s) => JsonValue::String(s.clone()),
117 Value::Integer(i) => json!(i),
118 Value::Float(f) => json!(f),
119 Value::Boolean(b) => JsonValue::Bool(*b),
120 Value::Uri(uri) => json!({ "type": "uri", "value": uri }),
121 Value::Null => JsonValue::Null,
122 }
123 }
124}
125
126impl PartialEq for Value {
127 fn eq(&self, other: &Self) -> bool {
128 match (self, other) {
129 (Value::Node(a), Value::Node(b)) => a == b,
130 (Value::Edge(a), Value::Edge(b)) => a == b,
131 (Value::String(a), Value::String(b)) => a == b,
132 (Value::Integer(a), Value::Integer(b)) => a == b,
133 (Value::Float(a), Value::Float(b)) => {
134 (a - b).abs() < f64::EPSILON || (a.is_nan() && b.is_nan())
135 }
136 (Value::Boolean(a), Value::Boolean(b)) => a == b,
137 (Value::Uri(a), Value::Uri(b)) => a == b,
138 (Value::Null, Value::Null) => true,
139 _ => false,
140 }
141 }
142}
143
144impl Eq for Value {}
145
146impl Hash for Value {
147 fn hash<H: Hasher>(&self, state: &mut H) {
148 match self {
149 Value::Node(s) => {
150 0u8.hash(state);
151 s.hash(state);
152 }
153 Value::Edge(s) => {
154 1u8.hash(state);
155 s.hash(state);
156 }
157 Value::String(s) => {
158 2u8.hash(state);
159 s.hash(state);
160 }
161 Value::Integer(i) => {
162 3u8.hash(state);
163 i.hash(state);
164 }
165 Value::Boolean(b) => {
166 4u8.hash(state);
167 b.hash(state);
168 }
169 Value::Uri(s) => {
170 5u8.hash(state);
171 s.hash(state);
172 }
173 Value::Float(f) => {
174 6u8.hash(state);
175 f.to_bits().hash(state);
176 }
177 Value::Null => {
178 7u8.hash(state);
179 }
180 }
181 }
182}
183
184impl fmt::Display for Value {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 match self {
187 Value::Node(id) => write!(f, "<node:{}>", id),
188 Value::Edge(id) => write!(f, "<edge:{}>", id),
189 Value::String(s) => write!(f, "\"{}\"", s),
190 Value::Integer(i) => write!(f, "{}", i),
191 Value::Float(fl) => write!(f, "{}", fl),
192 Value::Boolean(b) => write!(f, "{}", b),
193 Value::Uri(uri) => write!(f, "<{}>", uri),
194 Value::Null => write!(f, "NULL"),
195 }
196 }
197}
198
199#[derive(Debug, Clone)]
201pub struct Binding {
202 bindings: HashMap<Var, Value>,
204 parent: Option<Arc<Binding>>,
206}
207
208impl Binding {
209 pub fn empty() -> Self {
211 Self {
212 bindings: HashMap::new(),
213 parent: None,
214 }
215 }
216
217 pub fn one(var: Var, value: Value) -> Self {
219 let mut bindings = HashMap::new();
220 bindings.insert(var, value);
221 Self {
222 bindings,
223 parent: None,
224 }
225 }
226
227 pub fn two(var1: Var, val1: Value, var2: Var, val2: Value) -> Self {
229 let mut bindings = HashMap::new();
230 bindings.insert(var1, val1);
231 bindings.insert(var2, val2);
232 Self {
233 bindings,
234 parent: None,
235 }
236 }
237
238 pub fn with_parent(self, parent: Arc<Binding>) -> Self {
240 Self {
241 bindings: self.bindings,
242 parent: Some(parent),
243 }
244 }
245
246 pub fn get(&self, var: &Var) -> Option<&Value> {
248 self.bindings
249 .get(var)
250 .or_else(|| self.parent.as_ref().and_then(|p| p.get(var)))
251 }
252
253 pub fn contains(&self, var: &Var) -> bool {
255 self.bindings.contains_key(var)
256 || self
257 .parent
258 .as_ref()
259 .map(|p| p.contains(var))
260 .unwrap_or(false)
261 }
262
263 pub fn vars(&self) -> impl Iterator<Item = &Var> {
265 self.bindings.keys()
266 }
267
268 pub fn all_vars(&self) -> Vec<&Var> {
270 let mut vars: Vec<&Var> = self.bindings.keys().collect();
271 if let Some(ref parent) = self.parent {
272 for v in parent.all_vars() {
273 if !vars.contains(&v) {
274 vars.push(v);
275 }
276 }
277 }
278 vars
279 }
280
281 pub fn size(&self) -> usize {
283 self.bindings.len()
284 }
285
286 pub fn is_empty(&self) -> bool {
288 self.bindings.is_empty() && self.parent.as_ref().map(|p| p.is_empty()).unwrap_or(true)
289 }
290
291 pub fn merge(&self, other: &Binding) -> Option<Binding> {
293 let mut merged = self.bindings.clone();
294
295 for (var, value) in &other.bindings {
296 if let Some(existing) = self.get(var) {
297 if existing != value {
298 return None; }
300 } else {
301 merged.insert(var.clone(), value.clone());
302 }
303 }
304
305 Some(Binding {
306 bindings: merged,
307 parent: self.parent.clone(),
308 })
309 }
310
311 pub fn project(&self, vars: &[Var]) -> Binding {
313 let mut projected = HashMap::new();
314 for var in vars {
315 if let Some(value) = self.get(var) {
316 projected.insert(var.clone(), value.clone());
317 }
318 }
319 Binding {
320 bindings: projected,
321 parent: None,
322 }
323 }
324
325 pub fn extend(&self, var: Var, value: Value) -> Binding {
327 let mut bindings = self.bindings.clone();
328 bindings.insert(var, value);
329 Binding {
330 bindings,
331 parent: self.parent.clone(),
332 }
333 }
334
335 pub fn to_map(&self) -> HashMap<String, Value> {
337 let mut map = HashMap::new();
338 if let Some(ref parent) = self.parent {
339 for (k, v) in parent.to_map() {
340 map.insert(k, v);
341 }
342 }
343 for (var, value) in &self.bindings {
344 map.insert(var.name().to_string(), value.clone());
345 }
346 map
347 }
348
349 pub fn to_json(&self) -> JsonValue {
351 let map: JsonMap<String, JsonValue> = self
352 .to_map()
353 .into_iter()
354 .map(|(k, v)| (k, v.to_json()))
355 .collect();
356 JsonValue::Object(map)
357 }
358}
359
360impl Default for Binding {
361 fn default() -> Self {
362 Self::empty()
363 }
364}
365
366impl PartialEq for Binding {
367 fn eq(&self, other: &Self) -> bool {
368 let self_map = self.to_map();
370 let other_map = other.to_map();
371 self_map == other_map
372 }
373}
374
375impl Eq for Binding {}
376
377impl Hash for Binding {
378 fn hash<H: Hasher>(&self, state: &mut H) {
379 let mut entries: Vec<_> = self.to_map().into_iter().collect();
381 entries.sort_by(|a, b| a.0.cmp(&b.0));
382 for (k, v) in entries {
383 k.hash(state);
384 v.hash(state);
385 }
386 }
387}
388
389pub struct BindingBuilder {
391 bindings: HashMap<Var, Value>,
392 parent: Option<Arc<Binding>>,
393}
394
395impl BindingBuilder {
396 pub fn new() -> Self {
398 Self {
399 bindings: HashMap::new(),
400 parent: None,
401 }
402 }
403
404 pub fn from(binding: &Binding) -> Self {
406 Self {
407 bindings: binding.bindings.clone(),
408 parent: binding.parent.clone(),
409 }
410 }
411
412 pub fn parent(mut self, parent: Arc<Binding>) -> Self {
414 self.parent = Some(parent);
415 self
416 }
417
418 pub fn add(mut self, var: Var, value: Value) -> Self {
420 self.bindings.insert(var, value);
421 self
422 }
423
424 pub fn add_named(self, name: &str, value: Value) -> Self {
426 self.add(Var::from(name), value)
427 }
428
429 pub fn remove(mut self, var: &Var) -> Self {
431 self.bindings.remove(var);
432 self
433 }
434
435 pub fn build(self) -> Binding {
437 Binding {
438 bindings: self.bindings,
439 parent: self.parent,
440 }
441 }
442}
443
444impl Default for BindingBuilder {
445 fn default() -> Self {
446 Self::new()
447 }
448}
449
450#[cfg(test)]
451mod tests {
452 use super::*;
453
454 #[test]
455 fn test_var() {
456 let v = Var::new("x");
457 assert_eq!(v.name(), "x");
458 assert!(!v.is_anonymous());
459
460 let anon = Var::new("_g1");
461 assert!(anon.is_anonymous());
462 }
463
464 #[test]
465 fn test_var_from_string() {
466 let v1 = Var::from("x");
467 let v2 = Var::from("?x");
468 assert_eq!(v1, v2);
469 }
470
471 #[test]
472 fn test_binding_empty() {
473 let b = Binding::empty();
474 assert!(b.is_empty());
475 assert_eq!(b.size(), 0);
476 }
477
478 #[test]
479 fn test_binding_one() {
480 let b = Binding::one(Var::new("x"), Value::Integer(42));
481 assert!(!b.is_empty());
482 assert_eq!(b.size(), 1);
483 assert!(b.contains(&Var::new("x")));
484 assert_eq!(b.get(&Var::new("x")), Some(&Value::Integer(42)));
485 }
486
487 #[test]
488 fn test_binding_parent() {
489 let parent = Arc::new(Binding::one(Var::new("x"), Value::Integer(1)));
490 let child = Binding::one(Var::new("y"), Value::Integer(2)).with_parent(parent);
491
492 assert!(child.contains(&Var::new("x")));
494 assert!(child.contains(&Var::new("y")));
495
496 assert_eq!(child.size(), 1);
498 }
499
500 #[test]
501 fn test_binding_merge() {
502 let b1 = Binding::one(Var::new("x"), Value::Integer(1));
503 let b2 = Binding::one(Var::new("y"), Value::Integer(2));
504
505 let merged = b1.merge(&b2).unwrap();
506 assert!(merged.contains(&Var::new("x")));
507 assert!(merged.contains(&Var::new("y")));
508 }
509
510 #[test]
511 fn test_binding_merge_conflict() {
512 let b1 = Binding::one(Var::new("x"), Value::Integer(1));
513 let b2 = Binding::one(Var::new("x"), Value::Integer(2));
514
515 let merged = b1.merge(&b2);
516 assert!(merged.is_none()); }
518
519 #[test]
520 fn test_binding_merge_same_value() {
521 let b1 = Binding::one(Var::new("x"), Value::Integer(1));
522 let b2 = Binding::one(Var::new("x"), Value::Integer(1));
523
524 let merged = b1.merge(&b2).unwrap();
525 assert_eq!(merged.get(&Var::new("x")), Some(&Value::Integer(1)));
526 }
527
528 #[test]
529 fn test_binding_project() {
530 let b = Binding::two(
531 Var::new("x"),
532 Value::Integer(1),
533 Var::new("y"),
534 Value::Integer(2),
535 );
536
537 let projected = b.project(&[Var::new("x")]);
538 assert!(projected.contains(&Var::new("x")));
539 assert!(!projected.contains(&Var::new("y")));
540 }
541
542 #[test]
543 fn test_binding_extend() {
544 let b = Binding::one(Var::new("x"), Value::Integer(1));
545 let extended = b.extend(Var::new("y"), Value::Integer(2));
546
547 assert!(extended.contains(&Var::new("x")));
548 assert!(extended.contains(&Var::new("y")));
549 }
550
551 #[test]
552 fn test_binding_builder() {
553 let b = BindingBuilder::new()
554 .add_named("x", Value::Integer(1))
555 .add_named("y", Value::String("hello".to_string()))
556 .build();
557
558 assert_eq!(b.size(), 2);
559 assert_eq!(b.get(&Var::new("x")), Some(&Value::Integer(1)));
560 }
561
562 #[test]
563 fn test_value_display() {
564 assert_eq!(format!("{}", Value::Integer(42)), "42");
565 assert_eq!(
566 format!("{}", Value::String("hello".to_string())),
567 "\"hello\""
568 );
569 assert_eq!(format!("{}", Value::Null), "NULL");
570 }
571}