solverforge_scoring/stream/
join_target.rs1use std::hash::Hash;
10
11use solverforge_core::score::Score;
12
13use super::bi_stream::BiConstraintStream;
14use super::collection_extract::CollectionExtract;
15use super::cross_bi_stream::CrossBiConstraintStream;
16use super::filter::{UniFilter, UniLeftBiFilter, UniLeftPredBiFilter};
17use super::joiner::EqualJoiner;
18use super::key_extract::EntityKeyAdapter;
19use super::UniConstraintStream;
20
21pub trait JoinTarget<S, A, E, F, Sc: Score> {
29 type Output;
31
32 fn apply(self, extractor_a: E, filter_a: F) -> Self::Output;
34}
35
36impl<S, A, E, F, K, KA, Sc> JoinTarget<S, A, E, F, Sc> for EqualJoiner<KA, KA, K>
38where
39 S: Send + Sync + 'static,
40 A: Clone + Hash + PartialEq + Send + Sync + 'static,
41 E: CollectionExtract<S, Item = A>,
42 F: UniFilter<S, A>,
43 K: Eq + Hash + Clone + Send + Sync,
44 KA: Fn(&A) -> K + Send + Sync,
45 Sc: Score + 'static,
46{
47 type Output = BiConstraintStream<S, A, K, E, EntityKeyAdapter<KA>, UniLeftBiFilter<F, A>, Sc>;
48
49 fn apply(self, extractor_a: E, filter_a: F) -> Self::Output {
50 let (key_fn, _) = self.into_keys();
51 let key_extractor = EntityKeyAdapter::new(key_fn);
52 let bi_filter = UniLeftBiFilter::new(filter_a);
53 BiConstraintStream::new_self_join_with_filter(extractor_a, key_extractor, bi_filter)
54 }
55}
56
57impl<S, A, B, E, F, EB, K, KA, KB, Sc> JoinTarget<S, A, E, F, Sc> for (EB, EqualJoiner<KA, KB, K>)
59where
60 S: Send + Sync + 'static,
61 A: Clone + Send + Sync + 'static,
62 B: Clone + Send + Sync + 'static,
63 E: CollectionExtract<S, Item = A>,
64 F: UniFilter<S, A>,
65 EB: CollectionExtract<S, Item = B>,
66 K: Eq + Hash + Clone + Send + Sync,
67 KA: Fn(&A) -> K + Send + Sync,
68 KB: Fn(&B) -> K + Send + Sync,
69 Sc: Score + 'static,
70{
71 type Output = CrossBiConstraintStream<S, A, B, K, E, EB, KA, KB, UniLeftBiFilter<F, B>, Sc>;
72
73 fn apply(self, extractor_a: E, filter_a: F) -> Self::Output {
74 let (extractor_b, joiner) = self;
75 let (key_a, key_b) = joiner.into_keys();
76 let bi_filter = UniLeftBiFilter::new(filter_a);
77 CrossBiConstraintStream::new_with_filter(extractor_a, extractor_b, key_a, key_b, bi_filter)
78 }
79}
80
81impl<S, A, B, E, F, EB, FB, P, Sc> JoinTarget<S, A, E, F, Sc>
83 for (UniConstraintStream<S, B, EB, FB, Sc>, P)
84where
85 S: Send + Sync + 'static,
86 A: Clone + Send + Sync + 'static,
87 B: Clone + Send + Sync + 'static,
88 E: CollectionExtract<S, Item = A>,
89 F: UniFilter<S, A>,
90 EB: CollectionExtract<S, Item = B>,
91 FB: UniFilter<S, B>,
92 P: Fn(&A, &B) -> bool + Send + Sync + 'static,
93 Sc: Score + 'static,
94{
95 type Output = CrossBiConstraintStream<
96 S,
97 A,
98 B,
99 u8,
100 E,
101 EB,
102 fn(&A) -> u8,
103 fn(&B) -> u8,
104 UniLeftPredBiFilter<F, P, A>,
105 Sc,
106 >;
107
108 fn apply(self, extractor_a: E, filter_a: F) -> Self::Output {
109 let (other_stream, predicate) = self;
110 let (extractor_b, _filter_b) = other_stream.into_parts();
111 let combined_filter = UniLeftPredBiFilter::new(filter_a, predicate);
112 CrossBiConstraintStream::new_with_filter(
113 extractor_a,
114 extractor_b,
115 (|_: &A| 0u8) as fn(&A) -> u8,
116 (|_: &B| 0u8) as fn(&B) -> u8,
117 combined_filter,
118 )
119 }
120}