solverforge_scoring/stream/joiner/
comparison.rs

1//! Comparison joiners for less than / greater than matching.
2
3use std::marker::PhantomData;
4
5use super::Joiner;
6
7/// Creates a joiner that matches when `left(a) < right(b)`.
8///
9/// # Example
10///
11/// ```
12/// use solverforge_scoring::stream::joiner::{Joiner, less_than};
13///
14/// #[derive(Clone)]
15/// struct Task { end: i64, start: i64 }
16///
17/// // Task A must end before Task B starts
18/// let sequential = less_than(|t: &Task| t.end, |t: &Task| t.start);
19///
20/// assert!(sequential.matches(
21///     &Task { end: 10, start: 0 },
22///     &Task { end: 20, start: 15 }
23/// ));
24///
25/// assert!(!sequential.matches(
26///     &Task { end: 10, start: 0 },
27///     &Task { end: 20, start: 5 }
28/// ));
29/// ```
30pub fn less_than<A, B, T, Fa, Fb>(left: Fa, right: Fb) -> LessThanJoiner<Fa, Fb, T>
31where
32    T: Ord,
33    Fa: Fn(&A) -> T + Send + Sync,
34    Fb: Fn(&B) -> T + Send + Sync,
35{
36    LessThanJoiner {
37        left,
38        right,
39        _phantom: PhantomData,
40    }
41}
42
43/// A joiner that matches when `left(a) < right(b)`.
44pub struct LessThanJoiner<Fa, Fb, T> {
45    left: Fa,
46    right: Fb,
47    _phantom: PhantomData<fn() -> T>,
48}
49
50impl<A, B, T, Fa, Fb> Joiner<A, B> for LessThanJoiner<Fa, Fb, T>
51where
52    T: Ord,
53    Fa: Fn(&A) -> T + Send + Sync,
54    Fb: Fn(&B) -> T + Send + Sync,
55{
56    #[inline]
57    fn matches(&self, a: &A, b: &B) -> bool {
58        (self.left)(a) < (self.right)(b)
59    }
60}
61
62/// Creates a joiner that matches when `left(a) <= right(b)`.
63///
64/// # Example
65///
66/// ```
67/// use solverforge_scoring::stream::joiner::{Joiner, less_than_or_equal};
68///
69/// let joiner = less_than_or_equal(|x: &i32| *x, |y: &i32| *y);
70///
71/// assert!(joiner.matches(&5, &10));
72/// assert!(joiner.matches(&5, &5));
73/// assert!(!joiner.matches(&10, &5));
74/// ```
75pub fn less_than_or_equal<A, B, T, Fa, Fb>(left: Fa, right: Fb) -> LessThanOrEqualJoiner<Fa, Fb, T>
76where
77    T: Ord,
78    Fa: Fn(&A) -> T + Send + Sync,
79    Fb: Fn(&B) -> T + Send + Sync,
80{
81    LessThanOrEqualJoiner {
82        left,
83        right,
84        _phantom: PhantomData,
85    }
86}
87
88/// A joiner that matches when `left(a) <= right(b)`.
89pub struct LessThanOrEqualJoiner<Fa, Fb, T> {
90    left: Fa,
91    right: Fb,
92    _phantom: PhantomData<fn() -> T>,
93}
94
95impl<A, B, T, Fa, Fb> Joiner<A, B> for LessThanOrEqualJoiner<Fa, Fb, T>
96where
97    T: Ord,
98    Fa: Fn(&A) -> T + Send + Sync,
99    Fb: Fn(&B) -> T + Send + Sync,
100{
101    #[inline]
102    fn matches(&self, a: &A, b: &B) -> bool {
103        (self.left)(a) <= (self.right)(b)
104    }
105}
106
107/// Creates a joiner that matches when `left(a) > right(b)`.
108///
109/// # Example
110///
111/// ```
112/// use solverforge_scoring::stream::joiner::{Joiner, greater_than};
113///
114/// let joiner = greater_than(|x: &i32| *x, |y: &i32| *y);
115///
116/// assert!(joiner.matches(&10, &5));
117/// assert!(!joiner.matches(&5, &10));
118/// assert!(!joiner.matches(&5, &5));
119/// ```
120pub fn greater_than<A, B, T, Fa, Fb>(left: Fa, right: Fb) -> GreaterThanJoiner<Fa, Fb, T>
121where
122    T: Ord,
123    Fa: Fn(&A) -> T + Send + Sync,
124    Fb: Fn(&B) -> T + Send + Sync,
125{
126    GreaterThanJoiner {
127        left,
128        right,
129        _phantom: PhantomData,
130    }
131}
132
133/// A joiner that matches when `left(a) > right(b)`.
134pub struct GreaterThanJoiner<Fa, Fb, T> {
135    left: Fa,
136    right: Fb,
137    _phantom: PhantomData<fn() -> T>,
138}
139
140impl<A, B, T, Fa, Fb> Joiner<A, B> for GreaterThanJoiner<Fa, Fb, T>
141where
142    T: Ord,
143    Fa: Fn(&A) -> T + Send + Sync,
144    Fb: Fn(&B) -> T + Send + Sync,
145{
146    #[inline]
147    fn matches(&self, a: &A, b: &B) -> bool {
148        (self.left)(a) > (self.right)(b)
149    }
150}
151
152/// Creates a joiner that matches when `left(a) >= right(b)`.
153///
154/// # Example
155///
156/// ```
157/// use solverforge_scoring::stream::joiner::{Joiner, greater_than_or_equal};
158///
159/// let joiner = greater_than_or_equal(|x: &i32| *x, |y: &i32| *y);
160///
161/// assert!(joiner.matches(&10, &5));
162/// assert!(joiner.matches(&5, &5));
163/// assert!(!joiner.matches(&5, &10));
164/// ```
165pub fn greater_than_or_equal<A, B, T, Fa, Fb>(
166    left: Fa,
167    right: Fb,
168) -> GreaterThanOrEqualJoiner<Fa, Fb, T>
169where
170    T: Ord,
171    Fa: Fn(&A) -> T + Send + Sync,
172    Fb: Fn(&B) -> T + Send + Sync,
173{
174    GreaterThanOrEqualJoiner {
175        left,
176        right,
177        _phantom: PhantomData,
178    }
179}
180
181/// A joiner that matches when `left(a) >= right(b)`.
182pub struct GreaterThanOrEqualJoiner<Fa, Fb, T> {
183    left: Fa,
184    right: Fb,
185    _phantom: PhantomData<fn() -> T>,
186}
187
188impl<A, B, T, Fa, Fb> Joiner<A, B> for GreaterThanOrEqualJoiner<Fa, Fb, T>
189where
190    T: Ord,
191    Fa: Fn(&A) -> T + Send + Sync,
192    Fb: Fn(&B) -> T + Send + Sync,
193{
194    #[inline]
195    fn matches(&self, a: &A, b: &B) -> bool {
196        (self.left)(a) >= (self.right)(b)
197    }
198}