use crate::OwnedProjection;
use alloc::{borrow::ToOwned, boxed::Box};
use core::{
borrow::Borrow,
mem::{self},
ops::Deref,
pin::Pin,
};
use tap::Pipe;
mod sealed {
use crate::OwnedProjection;
use core::pin::Pin;
pub trait Sealed: Sized {}
impl<K, V> Sealed for Pin<OwnedProjection<K, V>> {}
}
use sealed::Sealed;
pub trait PinningOwnedProjection: Sealed {
type K;
type V;
fn unpin(self) -> OwnedProjection<Self::K, Self::V>
where
Self::V: Unpin;
fn get<Q>(&self, key: &Q) -> Option<Pin<&Self::V>>
where
Self::K: Borrow<Q>,
Q: ?Sized + Eq;
fn get_mut<Q>(&mut self, key: &Q) -> Option<Pin<&mut Self::V>>
where
Self::K: Borrow<Q>,
Q: ?Sized + Eq;
#[allow(clippy::type_complexity)]
fn reproject_try_by_keyed_try_with_keyed<'a: 'b, 'b, T, Q, S, F, I, E>(
&'a mut self,
items_selectors_factories: I,
) -> Box<dyn 'b + Iterator<Item = Result<(T, Pin<&'a mut Self::V>), E>>>
where
Self::K: Borrow<Q>,
T: 'b,
Q: 'b + ?Sized + Eq + ToOwned<Owned = Self::K>,
S: 'b + FnOnce(&mut T) -> Result<&Q, E>,
F: 'b + FnOnce(&mut T, &Self::K) -> Result<Self::V, E>,
I: 'b + IntoIterator<Item = (T, S, F)>,
E: 'b;
#[allow(clippy::type_complexity)]
fn reproject_try_by_try_with<'a: 'b, 'b, T, Q, S, F, I, E>(
&'a mut self,
items: I,
selector: S,
factory: F,
) -> Box<dyn 'b + Iterator<Item = Result<(T, Pin<&'a mut Self::V>), E>>>
where
Self::K: Borrow<Q>,
T: 'b,
Q: 'b + ?Sized + Eq + ToOwned<Owned = Self::K>,
S: 'b + FnMut(&mut T) -> Result<&Q, E>,
F: 'b + FnMut(&mut T, &Self::K) -> Result<Self::V, E>,
I: 'b + IntoIterator<Item = T>,
E: 'b;
fn reproject_by_keyed_with_keyed<'a: 'b, 'b, T, Q, S, F, I>(
&'a mut self,
items_selectors_factories: I,
) -> Box<dyn 'b + Iterator<Item = (T, Pin<&'a mut Self::V>)>>
where
Self::K: Borrow<Q>,
T: 'b,
Q: 'b + ?Sized + Eq + ToOwned<Owned = Self::K>,
S: 'b + FnOnce(&mut T) -> &Q,
F: 'b + FnOnce(&mut T, &Self::K) -> Self::V,
I: 'b + IntoIterator<Item = (T, S, F)>;
fn reproject_by_with<'a: 'b, 'b, T, Q, S, F, I>(
&'a mut self,
items: I,
selector: S,
factory: F,
) -> Box<dyn 'b + Iterator<Item = (T, Pin<&'a mut Self::V>)>>
where
Self::K: Borrow<Q>,
T: 'b,
Q: 'b + ?Sized + Eq + ToOwned<Owned = Self::K>,
S: 'b + FnMut(&mut T) -> &Q,
F: 'b + FnMut(&mut T, &Self::K) -> Self::V,
I: 'b + IntoIterator<Item = T>;
}
impl<K, V> PinningOwnedProjection for Pin<OwnedProjection<K, V>> {
type K = K;
type V = V;
fn unpin(self) -> OwnedProjection<K, V>
where
V: Unpin,
{
let mut this: OwnedProjection<K, V> = unsafe { mem::transmute(self) };
this.pinning = false;
this
}
fn get<Q>(&self, key: &Q) -> Option<Pin<&V>>
where
K: Borrow<Q>,
Q: ?Sized + Eq,
{
self.as_non_pin().get(key).map(wrap_in_pin)
}
fn get_mut<Q>(&mut self, key: &Q) -> Option<Pin<&mut V>>
where
K: Borrow<Q>,
Q: ?Sized + Eq,
{
self.as_non_pin_mut().get_mut(key).map(wrap_in_pin)
}
#[allow(clippy::type_complexity)]
fn reproject_try_by_keyed_try_with_keyed<'a: 'b, 'b, T, Q, S, F, I, E>(
&'a mut self,
items_selectors_factories: I,
) -> Box<dyn 'b + Iterator<Item = Result<(T, Pin<&'a mut V>), E>>>
where
K: Borrow<Q>,
T: 'b,
Q: 'b + ?Sized + Eq + ToOwned<Owned = K>,
S: 'b + FnOnce(&mut T) -> Result<&Q, E>,
F: 'b + FnOnce(&mut T, &K) -> Result<V, E>,
I: 'b + IntoIterator<Item = (T, S, F)>,
E: 'b,
{
self.as_non_pin_mut()
.reproject_try_by_keyed_try_with_keyed(items_selectors_factories)
.map(wrap_value_in_result_in_pin)
.pipe(Box::new)
}
#[allow(clippy::type_complexity)]
fn reproject_try_by_try_with<'a: 'b, 'b, T, Q, S, F, I, E>(
&'a mut self,
items: I,
selector: S,
factory: F,
) -> Box<dyn 'b + Iterator<Item = Result<(T, Pin<&'a mut V>), E>>>
where
K: Borrow<Q>,
T: 'b,
Q: 'b + ?Sized + Eq + ToOwned<Owned = K>,
S: 'b + FnMut(&mut T) -> Result<&Q, E>,
F: 'b + FnMut(&mut T, &K) -> Result<V, E>,
I: 'b + IntoIterator<Item = T>,
E: 'b,
{
self.as_non_pin_mut()
.reproject_try_by_try_with(items, selector, factory)
.map(wrap_value_in_result_in_pin)
.pipe(Box::new)
}
fn reproject_by_keyed_with_keyed<'a: 'b, 'b, T, Q, S, F, I>(
&'a mut self,
items_selectors_factories: I,
) -> Box<dyn 'b + Iterator<Item = (T, Pin<&'a mut V>)>>
where
K: Borrow<Q>,
T: 'b,
Q: 'b + ?Sized + Eq + ToOwned<Owned = K>,
S: 'b + FnOnce(&mut T) -> &Q,
F: 'b + FnOnce(&mut T, &K) -> V,
I: 'b + IntoIterator<Item = (T, S, F)>,
{
self.as_non_pin_mut()
.reproject_by_keyed_with_keyed(items_selectors_factories)
.map(wrap_value_in_pin)
.pipe(Box::new)
}
fn reproject_by_with<'a: 'b, 'b, T, Q, S, F, I>(
&'a mut self,
items: I,
selector: S,
factory: F,
) -> Box<dyn 'b + Iterator<Item = (T, Pin<&'a mut V>)>>
where
K: Borrow<Q>,
T: 'b,
Q: 'b + ?Sized + Eq + ToOwned<Owned = K>,
S: 'b + FnMut(&mut T) -> &Q,
F: 'b + FnMut(&mut T, &K) -> V,
I: 'b + IntoIterator<Item = T>,
{
self.as_non_pin_mut()
.reproject_by_with(items, selector, factory)
.map(wrap_value_in_pin)
.pipe(Box::new)
}
}
unsafe trait PinHelper {
type T;
fn as_non_pin(&self) -> &Self::T;
fn as_non_pin_mut(&mut self) -> &mut Self::T;
}
unsafe impl<K, V> PinHelper for Pin<OwnedProjection<K, V>> {
type T = OwnedProjection<K, V>;
fn as_non_pin(&self) -> &Self::T {
unsafe { &*(self as *const Pin<OwnedProjection<K, V>>).cast::<OwnedProjection<K, V>>() }
}
fn as_non_pin_mut(&mut self) -> &mut Self::T {
unsafe { &mut *(self as *mut Pin<OwnedProjection<K, V>>).cast::<OwnedProjection<K, V>>() }
}
}
fn wrap_in_pin<V: Deref>(value: V) -> Pin<V> {
unsafe { Pin::new_unchecked(value) }
}
fn wrap_value_in_pin<T, V: Deref>((item, value): (T, V)) -> (T, Pin<V>) {
(item, wrap_in_pin(value))
}
fn wrap_value_in_result_in_pin<T, V: Deref, E>(
result: Result<(T, V), E>,
) -> Result<(T, Pin<V>), E> {
result.map(wrap_value_in_pin)
}