Skip to main content

solverforge_scoring/stream/
existence_target.rs

1use std::hash::Hash;
2use std::marker::PhantomData;
3
4use solverforge_core::score::Score;
5
6use super::collection_extract::{FlattenExtract, TrackedCollectionExtract};
7use super::existence_stream::{DirectExistenceStream, ExistenceMode, ExistsConstraintStream};
8use super::filter::UniFilter;
9use super::joiner::EqualJoiner;
10use super::uni_stream::UniConstraintStream;
11use crate::constraint::exists::SelfFlatten;
12
13pub struct FlattenedCollectionTarget<S, P, B, EP, FP, Flatten, Sc>
14where
15    Sc: Score,
16{
17    pub(crate) right_stream: UniConstraintStream<S, P, EP, FP, Sc>,
18    pub(crate) flatten: Flatten,
19    pub(crate) _phantom: PhantomData<(fn() -> B, fn() -> Sc)>,
20}
21
22pub trait ExistenceTarget<S, A, EA, FA, Sc: Score>
23where
24    EA: TrackedCollectionExtract<S, Item = A>,
25    FA: UniFilter<S, A>,
26{
27    type Output;
28
29    fn apply(self, mode: ExistenceMode, extractor_a: EA, filter_a: FA) -> Self::Output;
30}
31
32impl<S, A, B, EA, FA, EP, FP, K, KA, KB, Sc> ExistenceTarget<S, A, EA, FA, Sc>
33    for (
34        UniConstraintStream<S, B, EP, FP, Sc>,
35        EqualJoiner<KA, KB, K>,
36    )
37where
38    S: Send + Sync + 'static,
39    A: Clone + Send + Sync + 'static,
40    B: Clone + Send + Sync + 'static,
41    EA: TrackedCollectionExtract<S, Item = A>,
42    FA: UniFilter<S, A>,
43    EP: TrackedCollectionExtract<S, Item = B>,
44    FP: UniFilter<S, B>,
45    K: Eq + Hash + Clone + Send + Sync,
46    KA: Fn(&A) -> K + Send + Sync,
47    KB: Fn(&B) -> K + Send + Sync,
48    Sc: Score + 'static,
49{
50    type Output = DirectExistenceStream<S, A, B, K, EA, EP, KA, KB, FA, FP, Sc>;
51
52    fn apply(self, mode: ExistenceMode, extractor_a: EA, filter_a: FA) -> Self::Output {
53        let (right_stream, joiner) = self;
54        let (extractor_parent, filter_parent) = right_stream.into_parts();
55        let (key_a, key_b) = joiner.into_keys();
56        ExistsConstraintStream::new(
57            mode,
58            extractor_a,
59            extractor_parent,
60            (key_a, key_b),
61            filter_a,
62            filter_parent,
63            SelfFlatten,
64        )
65    }
66}
67
68impl<S, A, P, B, EA, FA, EP, FP, K, KA, KB, Flatten, Sc> ExistenceTarget<S, A, EA, FA, Sc>
69    for (
70        FlattenedCollectionTarget<S, P, B, EP, FP, Flatten, Sc>,
71        EqualJoiner<KA, KB, K>,
72    )
73where
74    S: Send + Sync + 'static,
75    A: Clone + Send + Sync + 'static,
76    P: Clone + Send + Sync + 'static,
77    B: Clone + Send + Sync + 'static,
78    EA: TrackedCollectionExtract<S, Item = A>,
79    FA: UniFilter<S, A>,
80    EP: TrackedCollectionExtract<S, Item = P>,
81    FP: UniFilter<S, P>,
82    K: Eq + Hash + Clone + Send + Sync,
83    KA: Fn(&A) -> K + Send + Sync,
84    KB: Fn(&B) -> K + Send + Sync,
85    Flatten: FlattenExtract<P, Item = B> + Send + Sync,
86    Sc: Score + 'static,
87{
88    type Output = ExistsConstraintStream<S, A, P, B, K, EA, EP, KA, KB, FA, FP, Flatten, Sc>;
89
90    fn apply(self, mode: ExistenceMode, extractor_a: EA, filter_a: FA) -> Self::Output {
91        let (target, joiner) = self;
92        let FlattenedCollectionTarget {
93            right_stream,
94            flatten,
95            ..
96        } = target;
97        let (extractor_parent, filter_parent) = right_stream.into_parts();
98        let (key_a, key_b) = joiner.into_keys();
99        ExistsConstraintStream::new(
100            mode,
101            extractor_a,
102            extractor_parent,
103            (key_a, key_b),
104            filter_a,
105            filter_parent,
106            flatten,
107        )
108    }
109}