triblespace_core/query/
patchconstraint.rs1use crate::id::id_from_value;
2use crate::id::id_into_value;
3use crate::id::ID_LEN;
4use crate::patch::IdentitySchema;
5use crate::patch::PATCH;
6use crate::value::RawValue;
7use crate::value::ValueSchema;
8use crate::value::VALUE_LEN;
9
10use super::Binding;
11use super::Constraint;
12use super::ContainsConstraint;
13use super::Variable;
14use super::VariableId;
15use super::VariableSet;
16
17pub struct PatchValueConstraint<'a, T: ValueSchema> {
18 variable: Variable<T>,
19 patch: &'a PATCH<VALUE_LEN, IdentitySchema, ()>,
20}
21
22impl<'a, T: ValueSchema> PatchValueConstraint<'a, T> {
23 pub fn new(variable: Variable<T>, patch: &'a PATCH<VALUE_LEN, IdentitySchema, ()>) -> Self {
24 PatchValueConstraint { variable, patch }
25 }
26}
27
28impl<'a, S: ValueSchema> Constraint<'a> for PatchValueConstraint<'a, S> {
29 fn variables(&self) -> VariableSet {
30 VariableSet::new_singleton(self.variable.index)
31 }
32
33 fn estimate(&self, variable: VariableId, _binding: &Binding) -> Option<usize> {
34 if self.variable.index == variable {
35 Some(self.patch.len() as usize)
36 } else {
37 None
38 }
39 }
40
41 fn propose(&self, variable: VariableId, _binding: &Binding, proposals: &mut Vec<RawValue>) {
42 if self.variable.index == variable {
43 self.patch
44 .infixes(&[0; 0], &mut |&k: &[u8; 32]| proposals.push(k));
45 }
46 }
47
48 fn confirm(&self, variable: VariableId, _binding: &Binding, proposals: &mut Vec<RawValue>) {
49 if self.variable.index == variable {
50 proposals.retain(|v| self.patch.has_prefix(v));
51 }
52 }
53}
54
55impl<'a, S: ValueSchema> ContainsConstraint<'a, S> for &'a PATCH<VALUE_LEN, IdentitySchema, ()> {
56 type Constraint = PatchValueConstraint<'a, S>;
57
58 fn has(self, v: Variable<S>) -> Self::Constraint {
59 PatchValueConstraint::new(v, self)
60 }
61}
62
63pub struct PatchIdConstraint<S>
64where
65 S: ValueSchema,
66{
67 variable: Variable<S>,
68 patch: PATCH<ID_LEN, IdentitySchema, ()>,
69}
70
71impl<S> PatchIdConstraint<S>
72where
73 S: ValueSchema,
74{
75 pub fn new(variable: Variable<S>, patch: PATCH<ID_LEN, IdentitySchema, ()>) -> Self {
76 PatchIdConstraint { variable, patch }
77 }
78}
79
80impl<'a, S> Constraint<'a> for PatchIdConstraint<S>
81where
82 S: ValueSchema,
83{
84 fn variables(&self) -> VariableSet {
85 VariableSet::new_singleton(self.variable.index)
86 }
87
88 fn estimate(&self, variable: VariableId, _binding: &Binding) -> Option<usize> {
89 if self.variable.index == variable {
90 Some(self.patch.len() as usize)
91 } else {
92 None
93 }
94 }
95
96 fn propose(&self, variable: VariableId, _binding: &Binding, proposals: &mut Vec<RawValue>) {
97 if self.variable.index == variable {
98 self.patch.infixes(&[0; 0], &mut |id: &[u8; 16]| {
99 proposals.push(id_into_value(id))
100 });
101 }
102 }
103
104 fn confirm(&self, _variable: VariableId, _binding: &Binding, proposals: &mut Vec<RawValue>) {
105 proposals.retain(|v| {
106 if let Some(id) = id_from_value(v) {
107 self.patch.has_prefix(&id)
108 } else {
109 false
110 }
111 });
112 }
113}
114
115impl<'a, S: ValueSchema> ContainsConstraint<'a, S> for PATCH<ID_LEN, IdentitySchema, ()> {
116 type Constraint = PatchIdConstraint<S>;
117
118 fn has(self, v: Variable<S>) -> Self::Constraint {
119 PatchIdConstraint::new(v, self)
120 }
121}