Skip to main content

graphrecords_query/operations/argument/
mod.rs

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}