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