triblespace_core/query/
rangeconstraint.rs1use super::*;
2
3pub struct InlineRange {
22 variable: VariableId,
23 min: RawInline,
24 max: RawInline,
25}
26
27impl InlineRange {
28 pub fn new<T: InlineEncoding>(variable: Variable<T>, min: Inline<T>, max: Inline<T>) -> Self {
30 InlineRange {
31 variable: variable.index,
32 min: min.raw,
33 max: max.raw,
34 }
35 }
36}
37
38pub fn value_range<T: InlineEncoding>(
40 variable: Variable<T>,
41 min: Inline<T>,
42 max: Inline<T>,
43) -> InlineRange {
44 InlineRange::new(variable, min, max)
45}
46
47impl<'a> Constraint<'a> for InlineRange {
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<RawInline>) {
64 }
66
67 fn confirm(&self, variable: VariableId, _binding: &Binding, proposals: &mut Vec<RawInline>) {
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::inlineencodings::R256;
86 use crate::prelude::*;
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: Inline<R256> = 10i128.to_inline();
99 let v50: Inline<R256> = 50i128.to_inline();
100 let v90: Inline<R256> = 90i128.to_inline();
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<Inline<R256>> = find!(
109 v: Inline<R256>,
110 pattern!(&data, [{ test_score: ?v }])
111 )
112 .collect();
113 assert_eq!(all.len(), 3);
114
115 let min: Inline<R256> = 20i128.to_inline();
117 let max: Inline<R256> = 80i128.to_inline();
118 let filtered: Vec<Inline<R256>> = find!(
119 v: Inline<R256>,
120 and!(
121 pattern!(&data, [{ test_score: ?v }]),
122 value_range(v, min, max),
123 )
124 )
125 .collect();
126 assert_eq!(filtered.len(), 1);
127 assert_eq!(filtered[0], v50);
128 }
129}