pub enum RHS<'a, R> {
Unsorted(&'a [R]),
Sorted(&'a [R]),
}
impl<'a, R> From<&'a [R]> for RHS<'a, R> {
fn from(rhs: &'a [R]) -> Self {
RHS::Unsorted(rhs)
}
}
impl<'a, R> RHS<'a, R> {
pub fn new_unsorted(rhs: &'a [R]) -> Self {
RHS::Unsorted(rhs)
}
pub fn new_sorted(rhs: &'a [R]) -> Self {
RHS::Sorted(rhs)
}
pub(crate) fn has_value<L, P>(&self, l: &L, predicate: P) -> bool
where
P: Fn(&L, &R) -> std::cmp::Ordering,
{
match self {
RHS::Unsorted(rs) => rs.iter().any(|r| (predicate)(l, r).is_eq()),
RHS::Sorted(rs) => rs.binary_search_by(|r| (predicate)(l, r)).is_ok(),
}
}
pub(crate) fn get_range<L, P>(&'a self, left: &L, predicate: &P) -> (usize, usize)
where
P: Fn(&L, &R) -> std::cmp::Ordering,
{
match self {
RHS::Unsorted(rs) => (0, rs.len()),
RHS::Sorted(rs) => {
if let Ok(pos) = rs.binary_search_by(|r| (predicate)(left, r).reverse()) {
let mut start = pos;
while start > 0 && (predicate)(left, &rs[start - 1]).is_eq() {
start -= 1;
}
let mut end = pos;
while end < rs.len() && (predicate)(left, &rs[end]).is_eq() {
end += 1;
}
(start, end)
} else {
(1, 0)
}
}
}
}
}
#[test]
fn test_has_value_sorted() {
use crate::joined_grouped::JoinableGrouped;
let left = [1, 2, 3];
let right = vec![(1, "hello"), (2, "world"), (2, "!")];
let right = RHS::new_sorted(&right);
let mut joined = left
.iter()
.inner_join_grouped(right, |l, r| r.0.cmp(l))
.flat_map(|x| x.1);
assert_eq!(joined.next(), Some(&(1, "hello")));
assert_eq!(joined.next(), Some(&(2, "world")));
assert_eq!(joined.next(), Some(&(2, "!")));
}
#[test]
fn test_has_value_unsorted() {
use crate::JoinableGrouped;
let left = [1, 2, 3];
let right = vec![(1, "hello"), (2, "world")];
let right = RHS::new_unsorted(&right);
let mut joined = left
.iter()
.inner_join_grouped(right, |l, r| (*l).cmp(&r.0))
.flat_map(|x| x.1);
assert_eq!(joined.next(), Some(&(1, "hello")));
assert_eq!(joined.next(), Some(&(2, "world")));
}