triblespace_core/query/
rangeconstraint.rs1use super::*;
2
3pub struct ValueRange {
22 variable: VariableId,
23 min: RawValue,
24 max: RawValue,
25}
26
27impl ValueRange {
28 pub fn new<T: ValueSchema>(variable: Variable<T>, min: Value<T>, max: Value<T>) -> Self {
30 ValueRange {
31 variable: variable.index,
32 min: min.raw,
33 max: max.raw,
34 }
35 }
36}
37
38pub fn value_range<T: ValueSchema>(
40 variable: Variable<T>,
41 min: Value<T>,
42 max: Value<T>,
43) -> ValueRange {
44 ValueRange::new(variable, min, max)
45}
46
47impl<'a> Constraint<'a> for ValueRange {
48 fn variables(&self) -> VariableSet {
49 VariableSet::new_singleton(self.variable)
50 }
51
52 fn estimate(&self, variable: VariableId, _binding: &Binding) -> Option<usize> {
55 if self.variable == variable {
56 Some(usize::MAX)
57 } else {
58 None
59 }
60 }
61
62 fn propose(&self, _variable: VariableId, _binding: &Binding, _proposals: &mut Vec<RawValue>) {
64 }
66
67 fn confirm(&self, variable: VariableId, _binding: &Binding, proposals: &mut Vec<RawValue>) {
69 if self.variable == variable {
70 proposals.retain(|v| *v >= self.min && *v <= self.max);
71 }
72 }
73
74 fn satisfied(&self, binding: &Binding) -> bool {
76 match binding.get(self.variable) {
77 Some(v) => *v >= self.min && *v <= self.max,
78 None => true,
79 }
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use crate::prelude::*;
86 use crate::prelude::valueschemas::R256;
87
88 attributes! {
89 "AA00000000000000AA00000000000000" as test_score: R256;
90 }
91
92 #[test]
93 fn value_range_filters_correctly() {
94 let e1 = ufoid();
95 let e2 = ufoid();
96 let e3 = ufoid();
97
98 let v10: Value<R256> = 10i128.to_value();
99 let v50: Value<R256> = 50i128.to_value();
100 let v90: Value<R256> = 90i128.to_value();
101
102 let mut data = TribleSet::new();
103 data += entity! { &e1 @ test_score: v10 };
104 data += entity! { &e2 @ test_score: v50 };
105 data += entity! { &e3 @ test_score: v90 };
106
107 let all: Vec<Value<R256>> = find!(
109 v: Value<R256>,
110 pattern!(&data, [{ test_score: ?v }])
111 ).collect();
112 assert_eq!(all.len(), 3);
113
114 let min: Value<R256> = 20i128.to_value();
116 let max: Value<R256> = 80i128.to_value();
117 let filtered: Vec<Value<R256>> = find!(
118 v: Value<R256>,
119 and!(
120 pattern!(&data, [{ test_score: ?v }]),
121 value_range(v, min, max),
122 )
123 ).collect();
124 assert_eq!(filtered.len(), 1);
125 assert_eq!(filtered[0], v50);
126 }
127}