triblespace_core/query/
hashmapconstraint.rs1use std::collections::HashMap;
2use std::ops::Deref;
3use std::rc::Rc;
4use std::sync::Arc;
5
6use crate::query::Binding;
7use crate::query::Constraint;
8use crate::query::ContainsConstraint;
9use crate::query::Variable;
10use crate::query::VariableId;
11use crate::query::VariableSet;
12use crate::value::TryFromValue;
13use crate::value::RawValue;
14use crate::value::ToValue;
15use crate::value::Value;
16use crate::value::ValueSchema;
17
18pub struct KeysConstraint<S: ValueSchema, R, K, V>
25where
26 R: Deref<Target = HashMap<K, V>>,
27{
28 variable: Variable<S>,
29 map: R,
30}
31
32impl<S: ValueSchema, R, K, V> KeysConstraint<S, R, K, V>
33where
34 R: Deref<Target = HashMap<K, V>>,
35{
36 pub fn new(variable: Variable<S>, map: R) -> Self {
38 KeysConstraint { variable, map }
39 }
40}
41
42impl<'a, S: ValueSchema, R, K, V> Constraint<'a> for KeysConstraint<S, R, K, V>
43where
44 K: 'a + std::cmp::Eq + std::hash::Hash + for<'b> TryFromValue<'b, S>,
45 for<'b> &'b K: ToValue<S>,
46 V: 'a,
47 R: Deref<Target = HashMap<K, V>>,
48{
49 fn variables(&self) -> VariableSet {
50 VariableSet::new_singleton(self.variable.index)
51 }
52
53 fn estimate(&self, variable: VariableId, _binding: &Binding) -> Option<usize> {
54 if self.variable.index == variable {
55 Some(self.map.len())
57 } else {
58 None
59 }
60 }
61
62 fn propose(&self, variable: VariableId, _binding: &Binding, proposals: &mut Vec<RawValue>) {
63 if self.variable.index == variable {
64 proposals.extend(self.map.keys().map(|k| ToValue::to_value(k).raw));
65 }
66 }
67
68 fn confirm(&self, variable: VariableId, _binding: &Binding, proposals: &mut Vec<RawValue>) {
69 if self.variable.index == variable {
70 proposals.retain(|v| {
71 self.map
72 .contains_key(&match TryFromValue::try_from_value(Value::<S>::as_transmute_raw(v)) {
73 Ok(v) => v,
74 Err(_) => return false,
75 })
76 });
77 }
78 }
79}
80
81impl<'a, S: ValueSchema, K, V> ContainsConstraint<'a, S> for &'a HashMap<K, V>
82where
83 K: 'a + std::cmp::Eq + std::hash::Hash + for<'b> TryFromValue<'b, S>,
84 for<'b> &'b K: ToValue<S>,
85 V: 'a,
86{
87 type Constraint = KeysConstraint<S, Self, K, V>;
88
89 fn has(self, v: Variable<S>) -> Self::Constraint {
90 KeysConstraint::new(v, self)
91 }
92}
93
94impl<'a, S: ValueSchema, K, V> ContainsConstraint<'a, S> for Rc<HashMap<K, V>>
95where
96 K: 'a + std::cmp::Eq + std::hash::Hash + for<'b> TryFromValue<'b, S>,
97 for<'b> &'b K: ToValue<S>,
98 V: 'a,
99{
100 type Constraint = KeysConstraint<S, Self, K, V>;
101
102 fn has(self, v: Variable<S>) -> Self::Constraint {
103 KeysConstraint::new(v, self)
104 }
105}
106
107impl<'a, S: ValueSchema, K, V> ContainsConstraint<'a, S> for Arc<HashMap<K, V>>
108where
109 K: 'a + std::cmp::Eq + std::hash::Hash + for<'b> TryFromValue<'b, S>,
110 for<'b> &'b K: ToValue<S>,
111 V: 'a,
112{
113 type Constraint = KeysConstraint<S, Self, K, V>;
114
115 fn has(self, v: Variable<S>) -> Self::Constraint {
116 KeysConstraint::new(v, self)
117 }
118}