1mod collection;
2mod constant;
3
4use crate::{
5 Arity, Bare, BareValueDomain, Definite, Diagnostic, ElementShape, EvaluateOperand, Explain,
6 Failure, IndexDomain, Indexed, Multiple, OrderState, QueryResult, Single, ValueDomain,
7 element::{ElementEmission, Preserving, Retention},
8 error::{
9 argument::{Absent, ArgumentAbsent},
10 index::DuplicateIndex,
11 },
12 execution::EvaluationCache,
13 explain::ExplainFormatter,
14 operands::OperandHandle,
15 optimizer::{
16 Estimate, Estimated, PlanIdentity, PlanInputs, PlanNode, Session, Stats, Transformed,
17 },
18};
19use graphrecords_core::GraphRecord;
20use graphrecords_utils::aliases::{GrHashMap, GrHashSet};
21use std::{
22 any::Any,
23 fmt,
24 hash::{Hash, Hasher},
25 iter::once,
26 marker::PhantomData,
27 sync::Arc,
28};
29
30pub trait Prepare: 'static + Send + Sync {
31 type Prepared<'a>: Clone + 'a
32 where
33 Self: 'a;
34
35 fn prepare<'a>(
36 &'a self,
37 graphrecord: &'a GraphRecord,
38 cache: &'a EvaluationCache<'a>,
39 ) -> QueryResult<Self::Prepared<'a>>;
40}
41
42pub trait Alignment: 'static {
43 type Address<'a>;
44
45 fn raise_at(
46 operation: &'static str,
47 cause: impl Diagnostic,
48 address: &Self::Address<'_>,
49 ) -> Box<Failure>;
50}
51
52pub struct Keyed<I: IndexDomain>(PhantomData<I>);
53
54impl<I: IndexDomain> Alignment for Keyed<I> {
55 type Address<'a> = I::Index<'a>;
56
57 fn raise_at(
58 operation: &'static str,
59 cause: impl Diagnostic,
60 address: &Self::Address<'_>,
61 ) -> Box<Failure> {
62 Failure::new_at::<I, _>(operation, cause, address)
63 }
64}
65
66pub struct Unaligned;
67
68impl Alignment for Unaligned {
69 type Address<'a> = ();
70
71 fn raise_at(
72 operation: &'static str,
73 cause: impl Diagnostic,
74 _address: &Self::Address<'_>,
75 ) -> Box<Failure> {
76 Failure::new(operation, cause)
77 }
78}
79
80pub trait SourceDomain {
81 type ValueDomain: ValueDomain;
82}
83
84pub enum Lookup<'a, W> {
85 Present(&'a W),
86 Absent(Absent),
87}
88
89pub trait ArgumentSource<A: Alignment, V: ValueDomain = <Self as SourceDomain>::ValueDomain>:
90 SourceDomain + Prepare + Explain + PlanIdentity + PlanInputs + Estimated
91{
92 type Retention: Retention;
93
94 fn lookup<'a, 'prepared>(
95 prepared: &'prepared Self::Prepared<'a>,
96 address: &A::Address<'a>,
97 ) -> Lookup<'prepared, QueryResult<V::Value<'a>>>
98 where
99 Self: 'a;
100
101 fn resolve<'a>(
102 prepared: &Self::Prepared<'a>,
103 address: &A::Address<'a>,
104 label: &'static str,
105 ) -> <Self::Retention as ElementEmission>::Step<QueryResult<V::Value<'a>>>
106 where
107 Self: 'a,
108 {
109 match Self::lookup(prepared, address) {
110 Lookup::Present(wrapped) => Self::Retention::keep(wrapped.clone()),
111 Lookup::Absent(absent) => {
112 Self::Retention::absent(|| A::raise_at(label, ArgumentAbsent::new(absent), address))
113 }
114 }
115 }
116}
117
118pub struct PreparedArgument<'a, A, V, R>
119where
120 A: Alignment,
121 V: ValueDomain,
122 R: Retention,
123{
124 plan: Arc<dyn PreparedArgumentPlan<'a, A, V, R> + 'a>,
125}
126
127impl<A, V, R> Clone for PreparedArgument<'_, A, V, R>
128where
129 A: Alignment,
130 V: ValueDomain,
131 R: Retention,
132{
133 fn clone(&self) -> Self {
134 Self {
135 plan: Arc::clone(&self.plan),
136 }
137 }
138}
139
140pub trait ArgumentPlan<A, V, R>: Any + Send + Sync
141where
142 A: Alignment,
143 V: ValueDomain,
144 R: Retention,
145{
146 fn as_any(&self) -> &dyn Any;
147
148 fn prepare<'a>(
149 &'a self,
150 graphrecord: &'a GraphRecord,
151 cache: &'a EvaluationCache<'a>,
152 ) -> QueryResult<PreparedArgument<'a, A, V, R>>;
153
154 fn inputs(&self) -> Vec<&dyn PlanNode>;
155
156 fn identity_eq(&self, other: &dyn ArgumentPlan<A, V, R>) -> bool;
157
158 fn identity_hash(&self, state: &mut dyn Hasher);
159
160 fn describe<'a>(&'a self, formatter: &mut ExplainFormatter<'a, '_>) -> fmt::Result;
161
162 fn estimate(&self, stats: &Stats) -> Estimate;
163
164 fn optimize(&self, session: &Session) -> Transformed<Argument<A, V, R>>;
165}
166
167pub struct Argument<A, V, R>
168where
169 A: Alignment,
170 V: ValueDomain,
171 R: Retention,
172{
173 plan: Arc<dyn ArgumentPlan<A, V, R>>,
174}
175
176impl<A, V, R> Argument<A, V, R>
177where
178 A: Alignment,
179 V: ValueDomain,
180 R: Retention,
181{
182 fn new<S>(source: S) -> Self
183 where
184 S: ArgumentSource<A, V, Retention = R>,
185 {
186 Self {
187 plan: Arc::new(SourceArgumentPlan { source }),
188 }
189 }
190}
191
192impl<A, V, R> Clone for Argument<A, V, R>
193where
194 A: Alignment,
195 V: ValueDomain,
196 R: Retention,
197{
198 fn clone(&self) -> Self {
199 Self {
200 plan: Arc::clone(&self.plan),
201 }
202 }
203}
204
205pub trait IntoArgument<A, V>: ArgumentSource<A, V> + Sized
206where
207 A: Alignment,
208 V: ValueDomain,
209{
210 fn into_argument(self) -> Argument<A, V, Self::Retention>;
211}
212
213impl<A, V, S> IntoArgument<A, V> for S
214where
215 A: Alignment,
216 V: ValueDomain,
217 S: ArgumentSource<A, V>,
218{
219 fn into_argument(self) -> Argument<A, V, Self::Retention> {
220 Argument::new(self)
221 }
222}
223
224trait PreparedArgumentPlan<'a, A, V, R>
225where
226 A: Alignment,
227 V: ValueDomain,
228 R: Retention,
229{
230 fn lookup<'prepared>(
231 &'prepared self,
232 address: &A::Address<'a>,
233 ) -> Lookup<'prepared, QueryResult<V::Value<'a>>>;
234
235 fn resolve(
236 &self,
237 address: &A::Address<'a>,
238 label: &'static str,
239 ) -> R::Step<QueryResult<V::Value<'a>>>;
240}
241
242struct PreparedSourceArgument<'a, A, V, R, S>
243where
244 A: Alignment,
245 V: ValueDomain,
246 R: Retention,
247 S: ArgumentSource<A, V, Retention = R> + 'a,
248{
249 prepared: S::Prepared<'a>,
250 #[allow(clippy::type_complexity)]
251 source: PhantomData<fn() -> (A, V, R, S)>,
252}
253
254impl<'a, A, V, R, S> PreparedArgumentPlan<'a, A, V, R> for PreparedSourceArgument<'a, A, V, R, S>
255where
256 A: Alignment,
257 V: ValueDomain,
258 R: Retention,
259 S: ArgumentSource<A, V, Retention = R> + 'a,
260{
261 fn lookup<'prepared>(
262 &'prepared self,
263 address: &A::Address<'a>,
264 ) -> Lookup<'prepared, QueryResult<V::Value<'a>>> {
265 S::lookup(&self.prepared, address)
266 }
267
268 fn resolve(
269 &self,
270 address: &A::Address<'a>,
271 label: &'static str,
272 ) -> R::Step<QueryResult<V::Value<'a>>> {
273 S::resolve(&self.prepared, address, label)
274 }
275}
276
277struct SourceArgumentPlan<S> {
278 source: S,
279}
280
281impl<A, V, R, S> ArgumentPlan<A, V, R> for SourceArgumentPlan<S>
282where
283 A: Alignment,
284 V: ValueDomain,
285 R: Retention,
286 S: ArgumentSource<A, V, Retention = R>,
287{
288 fn as_any(&self) -> &dyn Any {
289 self
290 }
291
292 fn prepare<'a>(
293 &'a self,
294 graphrecord: &'a GraphRecord,
295 cache: &'a EvaluationCache<'a>,
296 ) -> QueryResult<PreparedArgument<'a, A, V, R>> {
297 Ok(PreparedArgument {
298 plan: Arc::new(PreparedSourceArgument::<_, _, _, S> {
299 prepared: self.source.prepare(graphrecord, cache)?,
300 source: PhantomData,
301 }),
302 })
303 }
304
305 fn inputs(&self) -> Vec<&dyn PlanNode> {
306 self.source.inputs()
307 }
308
309 fn identity_eq(&self, other: &dyn ArgumentPlan<A, V, R>) -> bool {
310 other
311 .as_any()
312 .downcast_ref::<Self>()
313 .is_some_and(|other| self.source.identity_eq(&other.source))
314 }
315
316 fn identity_hash(&self, mut state: &mut dyn Hasher) {
317 self.source.identity_hash(&mut state);
318 }
319
320 fn describe<'a>(&'a self, formatter: &mut ExplainFormatter<'a, '_>) -> fmt::Result {
321 self.source.describe(formatter)
322 }
323
324 fn estimate(&self, stats: &Stats) -> Estimate {
325 self.source.estimate(stats)
326 }
327
328 fn optimize(&self, session: &Session) -> Transformed<Argument<A, V, R>> {
329 let source = PlanInputs::optimize(&self.source, session);
330 let (source, changed) = source.into_parts();
331 let argument = Argument::new(source);
332
333 if changed {
334 Transformed::changed(argument)
335 } else {
336 Transformed::unchanged(argument)
337 }
338 }
339}
340
341impl<A, V, R> Explain for Argument<A, V, R>
342where
343 A: Alignment,
344 V: ValueDomain,
345 R: Retention,
346{
347 fn describe<'a>(&'a self, formatter: &mut ExplainFormatter<'a, '_>) -> fmt::Result {
348 self.plan.describe(formatter)
349 }
350}
351
352impl<A, V, R> PlanIdentity for Argument<A, V, R>
353where
354 A: Alignment,
355 V: ValueDomain,
356 R: Retention,
357{
358 fn identity_eq(&self, other: &Self) -> bool {
359 self.plan.identity_eq(other.plan.as_ref())
360 }
361
362 fn identity_hash<H: Hasher>(&self, state: &mut H) {
363 self.plan.identity_hash(state);
364 }
365}
366
367impl<A, V, R> PlanInputs for Argument<A, V, R>
368where
369 A: Alignment,
370 V: ValueDomain,
371 R: Retention,
372{
373 fn inputs(&self) -> Vec<&dyn PlanNode> {
374 self.plan.inputs()
375 }
376
377 fn optimize(&self, session: &Session) -> Transformed<Self> {
378 self.plan.optimize(session)
379 }
380}
381
382impl<A, V, R> Estimated for Argument<A, V, R>
383where
384 A: Alignment,
385 V: ValueDomain,
386 R: Retention,
387{
388 fn estimate(&self, stats: &Stats) -> Estimate {
389 self.plan.estimate(stats)
390 }
391}
392
393impl<A, V, R> Prepare for Argument<A, V, R>
394where
395 A: Alignment,
396 V: ValueDomain,
397 R: Retention,
398{
399 type Prepared<'a>
400 = PreparedArgument<'a, A, V, R>
401 where
402 Self: 'a;
403
404 fn prepare<'a>(
405 &'a self,
406 graphrecord: &'a GraphRecord,
407 cache: &'a EvaluationCache<'a>,
408 ) -> QueryResult<Self::Prepared<'a>> {
409 self.plan.prepare(graphrecord, cache)
410 }
411}
412
413impl<A, V, R> SourceDomain for Argument<A, V, R>
414where
415 A: Alignment,
416 V: ValueDomain,
417 R: Retention,
418{
419 type ValueDomain = V;
420}
421
422impl<A, V, R> ArgumentSource<A, V> for Argument<A, V, R>
423where
424 A: Alignment,
425 V: ValueDomain,
426 R: Retention,
427{
428 type Retention = R;
429
430 fn lookup<'a, 'prepared>(
431 prepared: &'prepared Self::Prepared<'a>,
432 address: &A::Address<'a>,
433 ) -> Lookup<'prepared, QueryResult<V::Value<'a>>>
434 where
435 Self: 'a,
436 {
437 prepared.plan.lookup(address)
438 }
439
440 fn resolve<'a>(
441 prepared: &Self::Prepared<'a>,
442 address: &A::Address<'a>,
443 label: &'static str,
444 ) -> R::Step<QueryResult<V::Value<'a>>>
445 where
446 Self: 'a,
447 {
448 prepared.plan.resolve(address, label)
449 }
450}
451
452pub type IndexedElementContainer<'a, I, V, C> =
453 <C as Arity>::Container<'a, (<I as IndexDomain>::Index<'a>, QueryResult<V>)>;
454
455pub trait IndexedElementSource:
456 SourceDomain + Prepare + Explain + PlanIdentity + PlanInputs + Estimated
457{
458 type IndexDomain: IndexDomain;
459 type Arity: Arity;
460
461 fn elements<'a>(
462 prepared: Self::Prepared<'a>,
463 ) -> IndexedElementContainer<
464 'a,
465 Self::IndexDomain,
466 <Self::ValueDomain as ValueDomain>::Value<'a>,
467 Self::Arity,
468 >
469 where
470 Self: 'a;
471}
472
473pub trait SetSource<V: ValueDomain>:
474 Prepare + Explain + PlanIdentity + PlanInputs + Estimated
475{
476 fn set<'a>(prepared: Self::Prepared<'a>) -> QueryResult<GrHashSet<V::Value<'a>>>
477 where
478 Self: 'a,
479 V::Value<'a>: Eq + Hash;
480}
481
482pub trait PreparedArity<S: ElementShape>: Arity {
483 type Prepared<'a>: Clone + 'a
484 where
485 S: 'a;
486
487 fn prepare<'a>(
488 container: Self::Container<'a, S::Element<'a>>,
489 ) -> QueryResult<Self::Prepared<'a>>
490 where
491 S: 'a;
492}
493
494pub trait AlignableArity<S: ElementShape, A: Alignment>: PreparedArity<S> {
495 type Retention: Retention;
496
497 fn lookup<'a, 'prepared>(
498 prepared: &'prepared Self::Prepared<'a>,
499 address: &A::Address<'a>,
500 ) -> Lookup<'prepared, QueryResult<<S::ValueDomain as ValueDomain>::Value<'a>>>
501 where
502 S: 'a;
503}
504
505pub trait EnumerableArity<S: ElementShape, I: IndexDomain>: PreparedArity<S> {
506 fn elements<'a>(
507 prepared: Self::Prepared<'a>,
508 ) -> IndexedElementContainer<'a, I, <S::ValueDomain as ValueDomain>::Value<'a>, Self>
509 where
510 S: 'a;
511}
512
513pub trait SetArity<S: ElementShape>: PreparedArity<S> {
514 fn set<'a>(
515 prepared: Self::Prepared<'a>,
516 ) -> QueryResult<GrHashSet<<S::ValueDomain as ValueDomain>::Value<'a>>>
517 where
518 S: 'a,
519 <S::ValueDomain as ValueDomain>::Value<'a>: Eq + Hash;
520}
521
522pub struct PreparedIndexedMultiple<'a, I: IndexDomain, V: ValueDomain> {
523 elements: Vec<(I::Index<'a>, QueryResult<V::Value<'a>>)>,
524 positions: GrHashMap<I::Index<'a>, usize>,
525}
526
527impl<S: ElementShape, C: PreparedArity<S>> Prepare for OperandHandle<S, C> {
528 type Prepared<'a>
529 = C::Prepared<'a>
530 where
531 Self: 'a;
532
533 fn prepare<'a>(
534 &'a self,
535 graphrecord: &'a GraphRecord,
536 cache: &'a EvaluationCache<'a>,
537 ) -> QueryResult<Self::Prepared<'a>> {
538 C::prepare(self.evaluate(graphrecord, cache)?)
539 }
540}
541
542impl<S: ElementShape, C: Arity> SourceDomain for OperandHandle<S, C> {
543 type ValueDomain = S::ValueDomain;
544}
545
546impl<S: ElementShape, C: AlignableArity<S, A>, A: Alignment> ArgumentSource<A>
547 for OperandHandle<S, C>
548{
549 type Retention = C::Retention;
550
551 fn lookup<'a, 'prepared>(
552 prepared: &'prepared Self::Prepared<'a>,
553 address: &A::Address<'a>,
554 ) -> Lookup<'prepared, QueryResult<<S::ValueDomain as ValueDomain>::Value<'a>>>
555 where
556 Self: 'a,
557 {
558 C::lookup(prepared, address)
559 }
560}
561
562impl<I: IndexDomain, V: ValueDomain, C: EnumerableArity<Indexed<I, V>, I>> IndexedElementSource
563 for OperandHandle<Indexed<I, V>, C>
564{
565 type Arity = C;
566 type IndexDomain = I;
567
568 fn elements<'a>(
569 prepared: Self::Prepared<'a>,
570 ) -> C::Container<'a, (I::Index<'a>, QueryResult<<V as ValueDomain>::Value<'a>>)>
571 where
572 Self: 'a,
573 {
574 C::elements(prepared)
575 }
576}
577
578impl<S: ElementShape, C: SetArity<S>> SetSource<S::ValueDomain> for OperandHandle<S, C> {
579 fn set<'a>(
580 prepared: Self::Prepared<'a>,
581 ) -> QueryResult<GrHashSet<<S::ValueDomain as ValueDomain>::Value<'a>>>
582 where
583 Self: 'a,
584 <S::ValueDomain as ValueDomain>::Value<'a>: Eq + Hash,
585 {
586 C::set(prepared)
587 }
588}
589
590impl<I: IndexDomain, V: ValueDomain, O: OrderState> PreparedArity<Indexed<I, V>> for Multiple<O> {
591 type Prepared<'a>
592 = Arc<PreparedIndexedMultiple<'a, I, V>>
593 where
594 Indexed<I, V>: 'a;
595
596 fn prepare<'a>(
597 container: Self::Container<'a, <Indexed<I, V> as ElementShape>::Element<'a>>,
598 ) -> QueryResult<Self::Prepared<'a>>
599 where
600 Indexed<I, V>: 'a,
601 {
602 let mut elements = Vec::new();
603 let mut positions = GrHashMap::default();
604
605 for (index, outcome) in container {
606 if positions.contains_key(&index) {
607 return Err(Failure::new_at::<I, _>(
608 "operand preparation",
609 DuplicateIndex::<I>::new(I::to_owned(&index)),
610 &index,
611 ));
612 }
613
614 positions.insert(index.clone(), elements.len());
615 elements.push((index, outcome));
616 }
617
618 Ok(Arc::new(PreparedIndexedMultiple {
619 elements,
620 positions,
621 }))
622 }
623}
624
625impl<I: IndexDomain, V: ValueDomain, O: OrderState> AlignableArity<Indexed<I, V>, Keyed<I>>
626 for Multiple<O>
627{
628 type Retention = Preserving;
629
630 fn lookup<'a, 'prepared>(
631 prepared: &'prepared Self::Prepared<'a>,
632 address: &<Keyed<I> as Alignment>::Address<'a>,
633 ) -> Lookup<'prepared, QueryResult<V::Value<'a>>>
634 where
635 Indexed<I, V>: 'a,
636 {
637 match prepared.positions.get(address) {
638 Some(position) => Lookup::Present(&prepared.elements[*position].1),
639 None => Lookup::Absent(Absent::Uncovered),
640 }
641 }
642}
643
644impl<I: IndexDomain, V: ValueDomain, O: OrderState> EnumerableArity<Indexed<I, V>, I>
645 for Multiple<O>
646{
647 fn elements<'a>(
648 prepared: Self::Prepared<'a>,
649 ) -> Self::Container<'a, (I::Index<'a>, QueryResult<V::Value<'a>>)>
650 where
651 Indexed<I, V>: 'a,
652 {
653 let element_count = prepared.elements.len();
654
655 Box::new((0..element_count).map(move |position| prepared.elements[position].clone()))
656 }
657}
658
659impl<I, V, O> SetArity<Indexed<I, V>> for Multiple<O>
660where
661 I: IndexDomain,
662 V: ValueDomain,
663 O: OrderState,
664 for<'a> V::Value<'a>: Eq + Hash,
665{
666 fn set<'a>(prepared: Self::Prepared<'a>) -> QueryResult<GrHashSet<V::Value<'a>>>
667 where
668 Indexed<I, V>: 'a,
669 {
670 prepared
671 .elements
672 .iter()
673 .map(|element| element.1.clone())
674 .collect()
675 }
676}
677
678impl<I: IndexDomain, V: ValueDomain> PreparedArity<Indexed<I, V>> for Single {
679 type Prepared<'a>
680 = Option<(I::Index<'a>, QueryResult<V::Value<'a>>)>
681 where
682 Indexed<I, V>: 'a;
683
684 fn prepare<'a>(
685 container: Self::Container<'a, <Indexed<I, V> as ElementShape>::Element<'a>>,
686 ) -> QueryResult<Self::Prepared<'a>>
687 where
688 Indexed<I, V>: 'a,
689 {
690 Ok(container)
691 }
692}
693
694impl<I: IndexDomain, V: ValueDomain> EnumerableArity<Indexed<I, V>, I> for Single {
695 fn elements<'a>(
696 prepared: Self::Prepared<'a>,
697 ) -> Self::Container<'a, (I::Index<'a>, QueryResult<V::Value<'a>>)>
698 where
699 Indexed<I, V>: 'a,
700 {
701 prepared
702 }
703}
704
705impl<I, V> SetArity<Indexed<I, V>> for Single
706where
707 I: IndexDomain,
708 V: ValueDomain,
709 for<'a> V::Value<'a>: Eq + Hash,
710{
711 fn set<'a>(prepared: Self::Prepared<'a>) -> QueryResult<GrHashSet<V::Value<'a>>>
712 where
713 Indexed<I, V>: 'a,
714 {
715 match prepared {
716 Some(element) => Ok(once(element.1?).collect()),
717 None => Ok(GrHashSet::default()),
718 }
719 }
720}
721
722impl<I: IndexDomain, V: ValueDomain> PreparedArity<Indexed<I, V>> for Definite {
723 type Prepared<'a>
724 = (I::Index<'a>, QueryResult<V::Value<'a>>)
725 where
726 Indexed<I, V>: 'a;
727
728 fn prepare<'a>(
729 container: Self::Container<'a, <Indexed<I, V> as ElementShape>::Element<'a>>,
730 ) -> QueryResult<Self::Prepared<'a>>
731 where
732 Indexed<I, V>: 'a,
733 {
734 Ok(container)
735 }
736}
737
738impl<I: IndexDomain, V: ValueDomain> EnumerableArity<Indexed<I, V>, I> for Definite {
739 fn elements<'a>(
740 prepared: Self::Prepared<'a>,
741 ) -> Self::Container<'a, (I::Index<'a>, QueryResult<V::Value<'a>>)>
742 where
743 Indexed<I, V>: 'a,
744 {
745 prepared
746 }
747}
748
749impl<I, V> SetArity<Indexed<I, V>> for Definite
750where
751 I: IndexDomain,
752 V: ValueDomain,
753 for<'a> V::Value<'a>: Eq + Hash,
754{
755 fn set<'a>(prepared: Self::Prepared<'a>) -> QueryResult<GrHashSet<V::Value<'a>>>
756 where
757 Indexed<I, V>: 'a,
758 {
759 Ok(once(prepared.1?).collect())
760 }
761}
762
763impl<V: BareValueDomain, O: OrderState> PreparedArity<Bare<V>> for Multiple<O> {
764 type Prepared<'a>
765 = Arc<Vec<QueryResult<V::Value<'a>>>>
766 where
767 Bare<V>: 'a;
768
769 fn prepare<'a>(
770 container: Self::Container<'a, <Bare<V> as ElementShape>::Element<'a>>,
771 ) -> QueryResult<Self::Prepared<'a>>
772 where
773 Bare<V>: 'a,
774 {
775 Ok(Arc::new(container.collect()))
776 }
777}
778
779impl<V, O> SetArity<Bare<V>> for Multiple<O>
780where
781 V: BareValueDomain,
782 O: OrderState,
783 for<'a> V::Value<'a>: Eq + Hash,
784{
785 fn set<'a>(prepared: Self::Prepared<'a>) -> QueryResult<GrHashSet<V::Value<'a>>>
786 where
787 Bare<V>: 'a,
788 {
789 prepared.iter().cloned().collect()
790 }
791}
792
793impl<V: BareValueDomain> PreparedArity<Bare<V>> for Single {
794 type Prepared<'a>
795 = Option<QueryResult<V::Value<'a>>>
796 where
797 Bare<V>: 'a;
798
799 fn prepare<'a>(
800 container: Self::Container<'a, <Bare<V> as ElementShape>::Element<'a>>,
801 ) -> QueryResult<Self::Prepared<'a>>
802 where
803 Bare<V>: 'a,
804 {
805 Ok(container)
806 }
807}
808
809impl<A: Alignment, V: BareValueDomain> AlignableArity<Bare<V>, A> for Single {
810 type Retention = Preserving;
811
812 fn lookup<'a, 'prepared>(
813 prepared: &'prepared Self::Prepared<'a>,
814 _address: &A::Address<'a>,
815 ) -> Lookup<'prepared, QueryResult<V::Value<'a>>>
816 where
817 Bare<V>: 'a,
818 {
819 match prepared {
820 Some(value) => Lookup::Present(value),
821 None => Lookup::Absent(Absent::Empty),
822 }
823 }
824}
825
826impl<V> SetArity<Bare<V>> for Single
827where
828 V: BareValueDomain,
829 for<'a> V::Value<'a>: Eq + Hash,
830{
831 fn set<'a>(prepared: Self::Prepared<'a>) -> QueryResult<GrHashSet<V::Value<'a>>>
832 where
833 Bare<V>: 'a,
834 {
835 match prepared {
836 Some(outcome) => Ok(once(outcome?).collect()),
837 None => Ok(GrHashSet::default()),
838 }
839 }
840}
841
842impl<V: BareValueDomain> PreparedArity<Bare<V>> for Definite {
843 type Prepared<'a>
844 = QueryResult<V::Value<'a>>
845 where
846 Bare<V>: 'a;
847
848 fn prepare<'a>(
849 container: Self::Container<'a, <Bare<V> as ElementShape>::Element<'a>>,
850 ) -> QueryResult<Self::Prepared<'a>>
851 where
852 Bare<V>: 'a,
853 {
854 Ok(container)
855 }
856}
857
858impl<A: Alignment, V: BareValueDomain> AlignableArity<Bare<V>, A> for Definite {
859 type Retention = Preserving;
860
861 fn lookup<'a, 'prepared>(
862 prepared: &'prepared Self::Prepared<'a>,
863 _address: &A::Address<'a>,
864 ) -> Lookup<'prepared, QueryResult<V::Value<'a>>>
865 where
866 Bare<V>: 'a,
867 {
868 Lookup::Present(prepared)
869 }
870}
871
872impl<V> SetArity<Bare<V>> for Definite
873where
874 V: BareValueDomain,
875 for<'a> V::Value<'a>: Eq + Hash,
876{
877 fn set<'a>(prepared: Self::Prepared<'a>) -> QueryResult<GrHashSet<V::Value<'a>>>
878 where
879 Bare<V>: 'a,
880 {
881 Ok(once(prepared?).collect())
882 }
883}