use async_trait::async_trait;
use std::pin::Pin;
use crate::async_lock::SyncKeyPathLike;
#[async_trait(?Send)]
pub trait PinFutureAwaitLike<S, Output> {
async fn get_await(&self, this: Pin<&mut S>) -> Option<Output>;
}
#[derive(Clone)]
pub struct PinFutureAwaitKp<S, Output, L>
where
L: Clone,
{
inner: L,
_p: std::marker::PhantomData<fn() -> (S, Output)>,
}
impl<S, Output, L> PinFutureAwaitKp<S, Output, L>
where
L: PinFutureAwaitLike<S, Output> + Clone,
{
pub fn new(inner: L) -> Self {
Self {
inner,
_p: std::marker::PhantomData,
}
}
}
#[async_trait(?Send)]
impl<S, Output, L> PinFutureAwaitLike<S, Output> for PinFutureAwaitKp<S, Output, L>
where
L: PinFutureAwaitLike<S, Output> + Sync + Clone,
{
async fn get_await(&self, this: Pin<&mut S>) -> Option<Output> {
self.inner.get_await(this).await
}
}
#[macro_export]
macro_rules! pin_future_await_kp {
($ty:ty, $method:ident -> $output:ty) => {{
#[derive(Clone, Copy)]
struct KpImpl;
#[::async_trait::async_trait(?Send)]
impl $crate::pin::PinFutureAwaitLike<$ty, $output> for KpImpl {
async fn get_await(&self, this: std::pin::Pin<&mut $ty>) -> Option<$output> {
<$ty>::$method(this).await
}
}
$crate::pin::PinFutureAwaitKp::new(KpImpl)
}};
}
#[derive(Clone)]
pub struct KpThenPinFuture<R, S, Output, Root, MutRoot, Value, MutValue, First, Second> {
pub(crate) first: First,
pub(crate) second: Second,
pub(crate) _p: std::marker::PhantomData<(R, S, Output, Root, MutRoot, Value, MutValue)>,
}
impl<R, S, Output, Root, MutRoot, Value, MutValue, First, Second>
KpThenPinFuture<R, S, Output, Root, MutRoot, Value, MutValue, First, Second>
where
S: Unpin,
Output: 'static,
MutValue: std::borrow::BorrowMut<S>,
First: SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
Second: PinFutureAwaitLike<S, Output>,
{
pub async fn get(&self, _root: Root) -> Option<Output> {
None
}
pub async fn get_mut(&self, root: MutRoot) -> Option<Output> {
let mut mut_value = self.first.sync_get_mut(root)?;
let s: &mut S = mut_value.borrow_mut();
self.second.get_await(Pin::new(s)).await
}
#[inline]
pub async fn get_optional(&self, root: Option<Root>) -> Option<Output> {
match root {
Some(r) => self.get(r).await,
None => None,
}
}
#[inline]
pub async fn get_mut_optional(&self, root: Option<MutRoot>) -> Option<Output> {
match root {
Some(r) => self.get_mut(r).await,
None => None,
}
}
#[inline]
pub async fn get_or_else<F>(&self, root: Option<Root>, f: F) -> Output
where
F: FnOnce() -> Output,
{
self.get_optional(root).await.unwrap_or_else(f)
}
#[inline]
pub async fn get_mut_or_else<F>(&self, root: Option<MutRoot>, f: F) -> Output
where
F: FnOnce() -> Output,
{
self.get_mut_optional(root).await.unwrap_or_else(f)
}
}