Skip to main content

triblespace_core/query/
patchconstraint.rs

1use 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}