#![allow(dead_code)]
use std::borrow::Cow;
use std::hash::Hash;
use std::marker::PhantomData;
use super::index::HashIndex;
use super::operator::FlattenView;
use super::{Leaf, RowHandle};
use crate::stream::joiner::plan::{CompileCondition, EqualityKind, ExecutablePlan, IndexedPlan};
use crate::stream::joiner::Joiner;
pub trait ViewKey<V> {
type Key;
fn key(&self, view: &V) -> Self::Key;
}
pub struct EntityKey<F>(F);
impl<F> EntityKey<F> {
pub fn new(inner: F) -> Self {
Self(inner)
}
}
impl<A, F, K> ViewKey<Leaf<'_, A>> for EntityKey<F>
where
F: Fn(&A) -> K + Send + Sync,
{
type Key = K;
#[inline]
fn key(&self, view: &Leaf<'_, A>) -> K {
(self.0)(view.entity)
}
}
pub struct ChildKey<F>(F);
impl<F> ChildKey<F> {
pub fn new(inner: F) -> Self {
Self(inner)
}
}
impl<V, B, F, K> ViewKey<FlattenView<'_, V, B>> for ChildKey<F>
where
F: Fn(&B) -> K + Send + Sync,
{
type Key = K;
#[inline]
fn key(&self, view: &FlattenView<'_, V, B>) -> K {
(self.0)(view.value)
}
}
pub struct PairKey<A, B>(A, B);
impl<A, B> PairKey<A, B> {
pub fn new(first: A, second: B) -> Self {
Self(first, second)
}
}
impl<V, A, B> ViewKey<V> for PairKey<A, B>
where
A: ViewKey<V>,
B: ViewKey<V>,
{
type Key = (A::Key, B::Key);
#[inline]
fn key(&self, view: &V) -> Self::Key {
(self.0.key(view), self.1.key(view))
}
}
pub struct FlattenedPairKey<KB, CK>(KB, CK);
impl<KB, CK> FlattenedPairKey<KB, CK> {
pub fn new(owner_key: KB, child_key: CK) -> Self {
Self(owner_key, child_key)
}
}
impl<B, C, KB, CK, K, K2> ViewKey<FlattenView<'_, Leaf<'_, B>, C>> for FlattenedPairKey<KB, CK>
where
KB: Fn(&B) -> K + Send + Sync,
CK: Fn(&C) -> K2 + Send + Sync,
{
type Key = (K, K2);
#[inline]
fn key(&self, view: &FlattenView<'_, Leaf<'_, B>, C>) -> Self::Key {
((self.0)(view.input.entity), (self.1)(view.value))
}
}
pub struct GroupKey;
impl<S, O, K, A, V, R> ViewKey<super::operator::GroupView<'_, S, O, K, A, V, R>> for GroupKey
where
S: 'static,
O: super::operator::Operator<S>,
K: Clone,
A: super::super::collector::Accumulator<V, R>,
{
type Key = K;
#[inline]
fn key(&self, view: &super::operator::GroupView<'_, S, O, K, A, V, R>) -> K {
view.key.clone()
}
}
pub struct ViewEqualPlan<K, KeyA, KeyB> {
key_a: KeyA,
key_b: KeyB,
marker: PhantomData<fn() -> K>,
}
impl<K, KeyA, KeyB> ViewEqualPlan<K, KeyA, KeyB> {
pub fn new(key_a: KeyA, key_b: KeyB) -> Self {
Self {
key_a,
key_b,
marker: PhantomData,
}
}
}
impl<K, KeyA, KeyB> CompileCondition for ViewEqualPlan<K, KeyA, KeyB> {
type Plan = Self;
fn compile(self) -> Self {
self
}
}
impl<K: Eq + Hash + Clone, KeyA, KeyB> crate::stream::joiner::plan::EqualityPlan
for ViewEqualPlan<K, KeyA, KeyB>
{
type Key = K;
}
impl<'x, A, B, K, KeyA, KeyB> crate::stream::joiner::plan::EqualityKeys<Leaf<'x, A>, Leaf<'x, B>>
for ViewEqualPlan<K, KeyA, KeyB>
where
K: Eq + Hash + Clone,
KeyA: ViewKey<Leaf<'x, A>, Key = K>,
KeyB: ViewKey<Leaf<'x, B>, Key = K>,
{
fn left_key(&self, row: &Leaf<'x, A>) -> K {
self.key_a.key(row)
}
fn right_key(&self, row: &Leaf<'x, B>) -> K {
self.key_b.key(row)
}
}
impl<K: Eq + Hash + Clone, KeyA, KeyB> IndexedPlan for ViewEqualPlan<K, KeyA, KeyB> {
type Kind = EqualityKind;
type Indexes = (HashIndex<K>, HashIndex<K>);
fn new_indexes(&self) -> Self::Indexes {
(HashIndex::new(), HashIndex::new())
}
fn remove_left(&self, i: &mut Self::Indexes, h: RowHandle) {
i.0.remove(h);
}
fn remove_right(&self, i: &mut Self::Indexes, h: RowHandle) {
i.1.remove(h);
}
}
impl<L, R, K, KeyA, KeyB> Joiner<L, R> for ViewEqualPlan<K, KeyA, KeyB>
where
K: PartialEq,
KeyA: ViewKey<L, Key = K> + Send + Sync,
KeyB: ViewKey<R, Key = K> + Send + Sync,
{
fn matches(&self, left: &L, right: &R) -> bool {
self.key_a.key(left) == self.key_b.key(right)
}
}
impl<L, R, K, KeyA, KeyB> ExecutablePlan<L, R> for ViewEqualPlan<K, KeyA, KeyB>
where
K: Eq + Hash + Clone,
KeyA: ViewKey<L, Key = K> + Send + Sync,
KeyB: ViewKey<R, Key = K> + Send + Sync,
{
fn candidate_matches(&self, _left: &L, _right: &R) -> bool {
true
}
fn insert_left(&self, i: &mut Self::Indexes, h: RowHandle, row: &L) {
i.0.insert(h, self.key_a.key(row));
}
fn insert_right(&self, i: &mut Self::Indexes, h: RowHandle, row: &R) {
i.1.insert(h, self.key_b.key(row));
}
fn insert_right_transient(&self, i: &mut Self::Indexes, h: RowHandle, row: &R) {
i.1.insert_transient(h, self.key_b.key(row));
}
fn right_candidates<'i>(&self, i: &'i Self::Indexes, row: &L) -> Cow<'i, [RowHandle]> {
Cow::Borrowed(i.1.lookup(&self.key_a.key(row)))
}
fn left_candidates<'i>(&self, i: &'i Self::Indexes, row: &R) -> Cow<'i, [RowHandle]> {
Cow::Borrowed(i.0.lookup(&self.key_b.key(row)))
}
}