graphrecords_query/operations/argument/
collection.rs1use crate::{
2 Explain, QueryResult, ValueDomain,
3 execution::EvaluationCache,
4 explain::ExplainFormatter,
5 operations::{Prepare, SetSource},
6 optimizer::{Estimate, Estimated, PlanIdentity, PlanInputs, Stats},
7};
8use graphrecords_core::GraphRecord;
9use graphrecords_utils::aliases::GrHashSet;
10use std::{
11 collections::HashSet,
12 fmt::{self, Display, Write},
13 hash::{BuildHasher, DefaultHasher, Hash, Hasher},
14};
15
16impl<T: Display> Explain for Vec<T> {
17 fn describe<'a>(&'a self, formatter: &mut ExplainFormatter<'a, '_>) -> fmt::Result {
18 formatter.write_char('[')?;
19
20 for (position, member) in self.iter().enumerate() {
21 if position > 0 {
22 formatter.write_str(", ")?;
23 }
24
25 write!(formatter, "{member}")?;
26 }
27
28 formatter.write_char(']')
29 }
30}
31
32impl<T: PartialEq + Hash> PlanIdentity for Vec<T> {
33 fn identity_eq(&self, other: &Self) -> bool {
34 self == other
35 }
36
37 fn identity_hash<H: Hasher>(&self, state: &mut H) {
38 self.hash(state);
39 }
40}
41
42impl<T: Clone> PlanInputs for Vec<T> {}
43
44impl<T: 'static + Send + Sync> Prepare for Vec<T> {
45 type Prepared<'a> = &'a [T];
46
47 fn prepare<'a>(
48 &'a self,
49 _graphrecord: &'a GraphRecord,
50 _cache: &'a EvaluationCache<'a>,
51 ) -> QueryResult<Self::Prepared<'a>> {
52 Ok(self)
53 }
54}
55
56impl<T> Estimated for Vec<T> {
57 fn estimate(&self, _stats: &Stats) -> Estimate {
58 Estimate {
59 elements: Some(self.len()),
60 ..Estimate::UNKNOWN
61 }
62 }
63}
64
65impl<T, V> SetSource<V> for Vec<T>
66where
67 T: 'static + Clone + Eq + Hash + Display + Send + Sync,
68 for<'a> V: ValueDomain<Value<'a> = T>,
69{
70 fn set<'a>(prepared: Self::Prepared<'a>) -> QueryResult<GrHashSet<V::Value<'a>>>
71 where
72 Self: 'a,
73 {
74 Ok(prepared.iter().cloned().collect())
75 }
76}
77
78impl<T: Display, const N: usize> Explain for [T; N] {
79 fn describe<'a>(&'a self, formatter: &mut ExplainFormatter<'a, '_>) -> fmt::Result {
80 formatter.write_char('[')?;
81
82 for (position, member) in self.iter().enumerate() {
83 if position > 0 {
84 formatter.write_str(", ")?;
85 }
86
87 write!(formatter, "{member}")?;
88 }
89
90 formatter.write_char(']')
91 }
92}
93
94impl<T: PartialEq + Hash, const N: usize> PlanIdentity for [T; N] {
95 fn identity_eq(&self, other: &Self) -> bool {
96 self == other
97 }
98
99 fn identity_hash<H: Hasher>(&self, state: &mut H) {
100 self.hash(state);
101 }
102}
103
104impl<T: Clone, const N: usize> PlanInputs for [T; N] {}
105
106impl<T: 'static + Send + Sync, const N: usize> Prepare for [T; N] {
107 type Prepared<'a> = &'a [T];
108
109 fn prepare<'a>(
110 &'a self,
111 _graphrecord: &'a GraphRecord,
112 _cache: &'a EvaluationCache<'a>,
113 ) -> QueryResult<Self::Prepared<'a>> {
114 Ok(self)
115 }
116}
117
118impl<T, const N: usize> Estimated for [T; N] {
119 fn estimate(&self, _stats: &Stats) -> Estimate {
120 Estimate {
121 elements: Some(N),
122 ..Estimate::UNKNOWN
123 }
124 }
125}
126
127impl<T, V, const N: usize> SetSource<V> for [T; N]
128where
129 T: 'static + Clone + Eq + Hash + Display + Send + Sync,
130 for<'a> V: ValueDomain<Value<'a> = T>,
131{
132 fn set<'a>(prepared: Self::Prepared<'a>) -> QueryResult<GrHashSet<V::Value<'a>>>
133 where
134 Self: 'a,
135 {
136 Ok(prepared.iter().cloned().collect())
137 }
138}
139
140impl<T: Display> Explain for GrHashSet<T> {
141 fn describe<'a>(&'a self, formatter: &mut ExplainFormatter<'a, '_>) -> fmt::Result {
142 let mut members: Vec<_> = self.iter().map(ToString::to_string).collect();
143 members.sort_unstable();
144
145 formatter.write_char('[')?;
146
147 for (position, member) in members.iter().enumerate() {
148 if position > 0 {
149 formatter.write_str(", ")?;
150 }
151
152 formatter.write_str(member)?;
153 }
154
155 formatter.write_char(']')
156 }
157}
158
159impl<T: Eq + Hash> PlanIdentity for GrHashSet<T> {
160 fn identity_eq(&self, other: &Self) -> bool {
161 self == other
162 }
163
164 fn identity_hash<H: Hasher>(&self, state: &mut H) {
165 state.write_usize(self.len());
166
167 let combined = self
168 .iter()
169 .map(|member| {
170 let mut hasher = DefaultHasher::new();
171 member.hash(&mut hasher);
172 hasher.finish()
173 })
174 .fold(0_u64, u64::wrapping_add);
175
176 state.write_u64(combined);
177 }
178}
179
180impl<T: Clone> PlanInputs for GrHashSet<T> {}
181
182impl<T: 'static + Send + Sync> Prepare for GrHashSet<T> {
183 type Prepared<'a> = &'a Self;
184
185 fn prepare<'a>(
186 &'a self,
187 _graphrecord: &'a GraphRecord,
188 _cache: &'a EvaluationCache<'a>,
189 ) -> QueryResult<Self::Prepared<'a>> {
190 Ok(self)
191 }
192}
193
194impl<T> Estimated for GrHashSet<T> {
195 fn estimate(&self, _stats: &Stats) -> Estimate {
196 Estimate::values(self.len(), self.len())
197 }
198}
199
200impl<T, V> SetSource<V> for GrHashSet<T>
201where
202 T: 'static + Clone + Eq + Hash + Display + Send + Sync,
203 for<'a> V: ValueDomain<Value<'a> = T>,
204{
205 fn set<'a>(prepared: Self::Prepared<'a>) -> QueryResult<GrHashSet<V::Value<'a>>>
206 where
207 Self: 'a,
208 {
209 Ok(prepared.clone())
210 }
211}
212
213impl<T: Display, S> Explain for HashSet<T, S> {
214 fn describe<'a>(&'a self, formatter: &mut ExplainFormatter<'a, '_>) -> fmt::Result {
215 let mut members: Vec<_> = self.iter().map(ToString::to_string).collect();
216 members.sort_unstable();
217
218 formatter.write_char('[')?;
219
220 for (position, member) in members.iter().enumerate() {
221 if position > 0 {
222 formatter.write_str(", ")?;
223 }
224
225 formatter.write_str(member)?;
226 }
227
228 formatter.write_char(']')
229 }
230}
231
232impl<T: Eq + Hash, S: BuildHasher> PlanIdentity for HashSet<T, S> {
233 fn identity_eq(&self, other: &Self) -> bool {
234 self == other
235 }
236
237 fn identity_hash<H: Hasher>(&self, state: &mut H) {
238 state.write_usize(self.len());
239
240 let combined = self
241 .iter()
242 .map(|member| {
243 let mut hasher = DefaultHasher::new();
244 member.hash(&mut hasher);
245 hasher.finish()
246 })
247 .fold(0_u64, u64::wrapping_add);
248
249 state.write_u64(combined);
250 }
251}
252
253impl<T: Clone, S: Clone> PlanInputs for HashSet<T, S> {}
254
255impl<T: 'static + Send + Sync, S: 'static + Send + Sync> Prepare for HashSet<T, S> {
256 type Prepared<'a> = &'a Self;
257
258 fn prepare<'a>(
259 &'a self,
260 _graphrecord: &'a GraphRecord,
261 _cache: &'a EvaluationCache<'a>,
262 ) -> QueryResult<Self::Prepared<'a>> {
263 Ok(self)
264 }
265}
266
267impl<T, S> Estimated for HashSet<T, S> {
268 fn estimate(&self, _stats: &Stats) -> Estimate {
269 Estimate::values(self.len(), self.len())
270 }
271}
272
273impl<T, S, V> SetSource<V> for HashSet<T, S>
274where
275 T: 'static + Clone + Eq + Hash + Display + Send + Sync,
276 for<'a> V: ValueDomain<Value<'a> = T>,
277 S: 'static + Clone + BuildHasher + Send + Sync,
278{
279 fn set<'a>(prepared: Self::Prepared<'a>) -> QueryResult<GrHashSet<V::Value<'a>>>
280 where
281 Self: 'a,
282 {
283 Ok(prepared.iter().cloned().collect())
284 }
285}