use crate::{cons, Concat, Cons};
use super::{MapGet, MapMut};
use core::{borrow::Borrow, iter::FusedIterator};
pub trait MapJoin<'a, K: 'a, V>: Iterator<Item = (&'a K, V)> + Sized {
#[inline(always)]
fn cons(self) -> core::iter::Map<Self, fn((&'a K, V)) -> (&'a K, (V, ()))> {
self.map(|(k, v)| (k, (v, ())))
}
#[inline(always)]
fn map_join<M>(self, rhs: &'a M) -> MapJoinIter<Self, &'a M>
where
M: MapGet<K>,
M::Key: Borrow<K>,
Self::Item: Cons,
{
MapJoinIter {
iter: self,
map: rhs,
}
}
#[inline(always)]
fn map_join_left<M>(self, rhs: &'a M) -> MapJoinLeftIter<Self, &'a M>
where
M: MapGet<K>,
M::Key: Borrow<K>,
Self::Item: Cons,
{
MapJoinLeftIter {
iter: self,
map: rhs,
}
}
#[inline(always)]
fn map_join_left_excl<M>(self, rhs: &'a M) -> MapJoinLeftExclIter<Self, &'a M>
where
M: MapGet<K>,
M::Key: Borrow<K>,
{
MapJoinLeftExclIter {
iter: self,
map: rhs,
}
}
#[inline(always)]
fn map_join_mut<M>(self, rhs: &'a mut M) -> MapJoinIter<Self, &'a mut M>
where
M: MapMut<K>,
M::Key: Borrow<K>,
{
MapJoinIter {
iter: self,
map: rhs,
}
}
#[inline(always)]
fn map_join_left_mut<M>(self, rhs: &'a mut M) -> MapJoinLeftIter<Self, &'a mut M>
where
M: MapMut<K>,
M::Key: Borrow<K>,
{
MapJoinLeftIter {
iter: self,
map: rhs,
}
}
}
impl<'a, T, K: 'a, V> MapJoin<'a, K, V> for T where T: Iterator<Item = (&'a K, V)> {}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct MapJoinIter<LHS: Iterator, RHS> {
iter: LHS,
map: RHS,
}
impl<'a, K: 'a, V, LHS, RHS> Iterator for MapJoinIter<LHS, &'a RHS>
where
LHS: Iterator<Item = (&'a K, V)>,
RHS: MapGet<K>,
RHS::Key: Borrow<K>,
V: Concat<Cons!(&'a RHS::Value)>,
{
type Item = <(&'a K, V) as Concat<Cons!(&'a RHS::Value)>>::Output;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
while let Some((key, lval)) = self.iter.next() {
if let Some(rval) = self.map.get(key) {
return Some((key, lval).concat(cons!(rval)));
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, self.iter.size_hint().1)
}
}
impl<'a, K: 'a, V, LHS, RHS> Iterator for MapJoinIter<LHS, &'a mut RHS>
where
LHS: Iterator<Item = (&'a K, V)>,
RHS: MapMut<K>,
RHS::Key: Borrow<K>,
V: Concat<Cons!(&'a mut RHS::Value)>,
{
type Item = <(&'a K, V) as Concat<Cons!(&'a mut RHS::Value)>>::Output;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
while let Some((key, lval)) = self.iter.next() {
if let Some(rval) = self.map.get_mut(key) {
let rval = unsafe { &mut *(rval as *mut _) };
return Some((key, lval).concat(cons!(rval)));
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, self.iter.size_hint().1)
}
}
impl<LHS, RHS> FusedIterator for MapJoinIter<LHS, RHS>
where
Self: Iterator,
LHS: FusedIterator,
{
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct MapJoinLeftIter<LHS: Iterator, RHS> {
iter: LHS,
map: RHS,
}
impl<'a, K: 'a, V, LHS, RHS> Iterator for MapJoinLeftIter<LHS, &'a RHS>
where
LHS: Iterator<Item = (&'a K, V)>,
RHS: MapGet<K>,
RHS::Key: Borrow<K>,
V: Concat<Cons!(Option<&'a RHS::Value>)>,
{
type Item = <(&'a K, V) as Concat<Cons!(Option<&'a RHS::Value>)>>::Output;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter
.next()
.map(|(key, lval)| (key, lval).concat(cons!(self.map.get(key))))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, K: 'a, V, LHS, RHS> Iterator for MapJoinLeftIter<LHS, &'a mut RHS>
where
LHS: Iterator<Item = (&'a K, V)>,
RHS: MapMut<K>,
RHS::Key: Borrow<K>,
V: Concat<Cons!(Option<&'a mut RHS::Value>)>,
{
type Item = <(&'a K, V) as Concat<Cons!(Option<&'a mut RHS::Value>)>>::Output;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(key, lval)| {
let rval = self
.map
.get_mut(key)
.map(|rval| unsafe { &mut *(rval as *mut _) });
(key, lval).concat(cons!(rval))
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<LHS, RHS> FusedIterator for MapJoinLeftIter<LHS, RHS>
where
Self: Iterator,
LHS: FusedIterator,
{
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct MapJoinLeftExclIter<LHS: Iterator, RHS> {
iter: LHS,
map: RHS,
}
impl<'a, K: 'a, V, LHS, RHS> Iterator for MapJoinLeftExclIter<LHS, &'a RHS>
where
LHS: Iterator<Item = (&'a K, V)>,
RHS: MapGet<K>,
RHS::Key: Borrow<K>,
{
type Item = LHS::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
while let Some((key, val)) = self.iter.next() {
if !self.map.contains_key(key) {
return Some((key, val));
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, self.iter.size_hint().1)
}
}
impl<LHS, RHS> FusedIterator for MapJoinLeftExclIter<LHS, RHS>
where
Self: Iterator,
LHS: FusedIterator,
{
}