use crate::{AccessorTrait, Kp, KpTrait};
use async_trait::async_trait;
use std::fmt;
#[cfg(feature = "tokio")]
pub use tokio::sync::{Mutex as TokioMutex, RwLock as TokioRwLock};
#[async_trait]
pub trait AsyncLockLike<Lock, Inner>: Send + Sync {
async fn lock_read(&self, lock: &Lock) -> Option<Inner>;
async fn lock_write(&self, lock: &mut Lock) -> Option<Inner>;
}
pub trait SyncKeyPathLike<Root, Value, MutRoot, MutValue> {
fn sync_get(&self, root: Root) -> Option<Value>;
fn sync_get_mut(&self, root: MutRoot) -> Option<MutValue>;
}
impl<R, V, Root, Value, MutRoot, MutValue, G, S> SyncKeyPathLike<Root, Value, MutRoot, MutValue>
for crate::Kp<R, V, Root, Value, MutRoot, MutValue, G, S>
where
Root: std::borrow::Borrow<R>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutValue: std::borrow::BorrowMut<V>,
G: Fn(Root) -> Option<Value>,
S: Fn(MutRoot) -> Option<MutValue>,
{
fn sync_get(&self, root: Root) -> Option<Value> {
(self.get)(root)
}
fn sync_get_mut(&self, root: MutRoot) -> Option<MutValue> {
(self.set)(root)
}
}
impl<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
> SyncKeyPathLike<Root, Value, MutRoot, MutValue>
for crate::lock::LockKp<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
>
where
Root: std::borrow::Borrow<R>,
LockValue: std::borrow::Borrow<Lock>,
MidValue: std::borrow::Borrow<Mid>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutLock: std::borrow::BorrowMut<Lock>,
MutMid: std::borrow::BorrowMut<Mid>,
MutValue: std::borrow::BorrowMut<V>,
G1: Fn(Root) -> Option<LockValue>,
S1: Fn(MutRoot) -> Option<MutLock>,
L: crate::lock::LockAccess<Lock, MidValue> + crate::lock::LockAccess<Lock, MutMid>,
G2: Fn(MidValue) -> Option<Value>,
S2: Fn(MutMid) -> Option<MutValue>,
V: Clone,
{
#[inline]
fn sync_get(&self, root: Root) -> Option<Value> {
self.get(root)
}
#[inline]
fn sync_get_mut(&self, root: MutRoot) -> Option<MutValue> {
self.get_mut(root)
}
}
#[async_trait(?Send)]
pub trait AsyncKeyPathLike<Root, MutRoot> {
type Value;
type MutValue;
async fn get(&self, root: Root) -> Option<Self::Value>;
async fn get_mut(&self, root: MutRoot) -> Option<Self::MutValue>;
}
#[derive(Clone)] pub struct AsyncLockKp<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
> where
Root: std::borrow::Borrow<R>,
LockValue: std::borrow::Borrow<Lock>,
MidValue: std::borrow::Borrow<Mid>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutLock: std::borrow::BorrowMut<Lock>,
MutMid: std::borrow::BorrowMut<Mid>,
MutValue: std::borrow::BorrowMut<V>,
G1: Fn(Root) -> Option<LockValue> + Clone,
S1: Fn(MutRoot) -> Option<MutLock> + Clone,
L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
G2: Fn(MidValue) -> Option<Value> + Clone,
S2: Fn(MutMid) -> Option<MutValue> + Clone,
{
pub(crate) prev: Kp<R, Lock, Root, LockValue, MutRoot, MutLock, G1, S1>,
pub(crate) mid: L,
pub(crate) next: Kp<Mid, V, MidValue, Value, MutMid, MutValue, G2, S2>,
}
impl<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
> fmt::Debug
for AsyncLockKp<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
>
where
Root: std::borrow::Borrow<R>,
LockValue: std::borrow::Borrow<Lock>,
MidValue: std::borrow::Borrow<Mid>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutLock: std::borrow::BorrowMut<Lock>,
MutMid: std::borrow::BorrowMut<Mid>,
MutValue: std::borrow::BorrowMut<V>,
G1: Fn(Root) -> Option<LockValue> + Clone,
S1: Fn(MutRoot) -> Option<MutLock> + Clone,
L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
G2: Fn(MidValue) -> Option<Value> + Clone,
S2: Fn(MutMid) -> Option<MutValue> + Clone,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("AsyncLockKp")
.field("root_ty", &std::any::type_name::<R>())
.field("lock_ty", &std::any::type_name::<Lock>())
.field("mid_ty", &std::any::type_name::<Mid>())
.field("value_ty", &std::any::type_name::<V>())
.finish_non_exhaustive()
}
}
impl<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
> fmt::Display
for AsyncLockKp<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
>
where
Root: std::borrow::Borrow<R>,
LockValue: std::borrow::Borrow<Lock>,
MidValue: std::borrow::Borrow<Mid>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutLock: std::borrow::BorrowMut<Lock>,
MutMid: std::borrow::BorrowMut<Mid>,
MutValue: std::borrow::BorrowMut<V>,
G1: Fn(Root) -> Option<LockValue> + Clone,
S1: Fn(MutRoot) -> Option<MutLock> + Clone,
L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
G2: Fn(MidValue) -> Option<Value> + Clone,
S2: Fn(MutMid) -> Option<MutValue> + Clone,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"AsyncLockKp<{}, {}, {}, {}>",
std::any::type_name::<R>(),
std::any::type_name::<Lock>(),
std::any::type_name::<Mid>(),
std::any::type_name::<V>()
)
}
}
impl<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
>
AsyncLockKp<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
>
where
Root: std::borrow::Borrow<R>,
LockValue: std::borrow::Borrow<Lock>,
MidValue: std::borrow::Borrow<Mid>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutLock: std::borrow::BorrowMut<Lock>,
MutMid: std::borrow::BorrowMut<Mid>,
MutValue: std::borrow::BorrowMut<V>,
G1: Fn(Root) -> Option<LockValue> + Clone,
S1: Fn(MutRoot) -> Option<MutLock> + Clone,
L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
G2: Fn(MidValue) -> Option<Value> + Clone,
S2: Fn(MutMid) -> Option<MutValue> + Clone,
{
pub fn new(
prev: Kp<R, Lock, Root, LockValue, MutRoot, MutLock, G1, S1>,
mid: L,
next: Kp<Mid, V, MidValue, Value, MutMid, MutValue, G2, S2>,
) -> Self {
Self { prev, mid, next }
}
#[inline]
pub async fn get(&self, root: Root) -> Option<Value>
where
Lock: Clone,
{
let lock_value = (self.prev.get)(root)?;
let lock: &Lock = lock_value.borrow();
let lock_clone = lock.clone();
let mid_value = self.mid.lock_read(&lock_clone).await?;
(self.next.get)(mid_value)
}
#[inline]
pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue>
where
Lock: Clone,
{
let mut lock_value = (self.prev.set)(root)?;
let lock: &mut Lock = lock_value.borrow_mut();
let mut lock_clone = lock.clone();
let mid_value = self.mid.lock_write(&mut lock_clone).await?;
(self.next.set)(mid_value)
}
#[inline]
pub async fn get_optional(&self, root: Option<Root>) -> Option<Value>
where
Lock: Clone,
{
match root {
Some(r) => self.get(r).await,
None => None,
}
}
#[inline]
pub async fn get_mut_optional(&self, root: Option<MutRoot>) -> Option<MutValue>
where
Lock: Clone,
{
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) -> Value
where
Lock: Clone,
F: FnOnce() -> Value,
{
self.get_optional(root).await.unwrap_or_else(f)
}
#[inline]
pub async fn get_mut_or_else<F>(&self, root: Option<MutRoot>, f: F) -> MutValue
where
Lock: Clone,
F: FnOnce() -> MutValue,
{
self.get_mut_optional(root).await.unwrap_or_else(f)
}
pub async fn set<F>(&self, root: Root, updater: F) -> Result<(), String>
where
Lock: Clone,
F: FnOnce(&mut V),
{
let lock_value = (self.prev.get)(root).ok_or("Failed to get lock from root")?;
let lock: &Lock = lock_value.borrow();
let lock_clone = lock.clone();
let mid_value = self
.mid
.lock_read(&lock_clone)
.await
.ok_or("Failed to lock")?;
let mut mut_value = (self.next.set)(mid_value).ok_or("Failed to navigate to value")?;
let v: &mut V = mut_value.borrow_mut();
updater(v);
Ok(())
}
pub fn then<V2, Value2, MutValue2, G3, S3>(
self,
next_kp: crate::Kp<V, V2, Value, Value2, MutValue, MutValue2, G3, S3>,
) -> AsyncLockKp<
R,
Lock,
Mid,
V2,
Root,
LockValue,
MidValue,
Value2,
MutRoot,
MutLock,
MutMid,
MutValue2,
G1,
S1,
L,
impl Fn(MidValue) -> Option<Value2>
+ Clone
+ use<
G1,
G2,
G3,
L,
Lock,
LockValue,
Mid,
MidValue,
MutLock,
MutMid,
MutRoot,
MutValue,
MutValue2,
R,
Root,
S1,
S2,
S3,
Value,
Value2,
V,
V2,
>,
impl Fn(MutMid) -> Option<MutValue2>
+ Clone
+ use<
G1,
G2,
G3,
L,
Lock,
LockValue,
Mid,
MidValue,
MutLock,
MutMid,
MutRoot,
MutValue,
MutValue2,
R,
Root,
S1,
S2,
S3,
Value,
Value2,
V,
V2,
>,
>
where
V: 'static,
V2: 'static,
Value: std::borrow::Borrow<V>,
Value2: std::borrow::Borrow<V2>,
MutValue: std::borrow::BorrowMut<V>,
MutValue2: std::borrow::BorrowMut<V2>,
G3: Fn(Value) -> Option<Value2> + Clone,
S3: Fn(MutValue) -> Option<MutValue2> + Clone,
{
let next_get = self.next.get;
let next_set = self.next.set;
let chained_kp = crate::Kp::new(
move |mid_value: MidValue| next_get(mid_value).and_then(|v| (next_kp.get)(v)),
move |mid_value: MutMid| next_set(mid_value).and_then(|v| (next_kp.set)(v)),
);
AsyncLockKp::new(self.prev, self.mid, chained_kp)
}
pub fn then_lock<
Lock2,
Mid2,
V2,
LockValue2,
MidValue2,
Value2,
MutLock2,
MutMid2,
MutValue2,
G2_1,
S2_1,
L2,
G2_2,
S2_2,
>(
self,
lock_kp: crate::lock::LockKp<
V,
Lock2,
Mid2,
V2,
Value,
LockValue2,
MidValue2,
Value2,
MutValue,
MutLock2,
MutMid2,
MutValue2,
G2_1,
S2_1,
L2,
G2_2,
S2_2,
>,
) -> AsyncLockKpThenLockKp<
R,
V2,
Root,
Value2,
MutRoot,
MutValue2,
Self,
crate::lock::LockKp<
V,
Lock2,
Mid2,
V2,
Value,
LockValue2,
MidValue2,
Value2,
MutValue,
MutLock2,
MutMid2,
MutValue2,
G2_1,
S2_1,
L2,
G2_2,
S2_2,
>,
>
where
V: 'static,
V2: 'static,
Value: std::borrow::Borrow<V>,
Value2: std::borrow::Borrow<V2>,
MutValue: std::borrow::BorrowMut<V>,
MutValue2: std::borrow::BorrowMut<V2>,
LockValue2: std::borrow::Borrow<Lock2>,
MidValue2: std::borrow::Borrow<Mid2>,
MutLock2: std::borrow::BorrowMut<Lock2>,
MutMid2: std::borrow::BorrowMut<Mid2>,
G2_1: Fn(Value) -> Option<LockValue2>,
S2_1: Fn(MutValue) -> Option<MutLock2>,
L2: crate::lock::LockAccess<Lock2, MidValue2> + crate::lock::LockAccess<Lock2, MutMid2>,
G2_2: Fn(MidValue2) -> Option<Value2>,
S2_2: Fn(MutMid2) -> Option<MutValue2>,
{
AsyncLockKpThenLockKp {
first: self,
second: lock_kp,
_p: std::marker::PhantomData,
}
}
pub fn then_async<
Lock2,
Mid2,
V2,
LockValue2,
MidValue2,
Value2,
MutLock2,
MutMid2,
MutValue2,
G2_1,
S2_1,
L2,
G2_2,
S2_2,
>(
self,
other: AsyncLockKp<
V,
Lock2,
Mid2,
V2,
Value,
LockValue2,
MidValue2,
Value2,
MutValue,
MutLock2,
MutMid2,
MutValue2,
G2_1,
S2_1,
L2,
G2_2,
S2_2,
>,
) -> ComposedAsyncLockKp<
R,
V2,
Root,
Value2,
MutRoot,
MutValue2,
Self,
AsyncLockKp<
V,
Lock2,
Mid2,
V2,
Value,
LockValue2,
MidValue2,
Value2,
MutValue,
MutLock2,
MutMid2,
MutValue2,
G2_1,
S2_1,
L2,
G2_2,
S2_2,
>,
>
where
Lock: Clone,
Lock2: Clone,
V: 'static,
V2: 'static,
Value: std::borrow::Borrow<V>,
LockValue2: std::borrow::Borrow<Lock2>,
MidValue2: std::borrow::Borrow<Mid2>,
Value2: std::borrow::Borrow<V2>,
MutValue: std::borrow::BorrowMut<V>,
MutLock2: std::borrow::BorrowMut<Lock2>,
MutMid2: std::borrow::BorrowMut<Mid2>,
MutValue2: std::borrow::BorrowMut<V2>,
G2_1: Fn(Value) -> Option<LockValue2> + Clone,
S2_1: Fn(MutValue) -> Option<MutLock2> + Clone,
L2: AsyncLockLike<Lock2, MidValue2> + AsyncLockLike<Lock2, MutMid2> + Clone,
G2_2: Fn(MidValue2) -> Option<Value2> + Clone,
S2_2: Fn(MutMid2) -> Option<MutValue2> + Clone,
{
ComposedAsyncLockKp {
first: self,
second: other,
_p: std::marker::PhantomData,
}
}
}
#[async_trait(?Send)]
impl<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
> AsyncKeyPathLike<Root, MutRoot>
for AsyncLockKp<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
>
where
Root: std::borrow::Borrow<R>,
LockValue: std::borrow::Borrow<Lock>,
MidValue: std::borrow::Borrow<Mid>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutLock: std::borrow::BorrowMut<Lock>,
MutMid: std::borrow::BorrowMut<Mid>,
MutValue: std::borrow::BorrowMut<V>,
G1: Fn(Root) -> Option<LockValue> + Clone,
S1: Fn(MutRoot) -> Option<MutLock> + Clone,
L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
G2: Fn(MidValue) -> Option<Value> + Clone,
S2: Fn(MutMid) -> Option<MutValue> + Clone,
Lock: Clone,
{
type Value = Value;
type MutValue = MutValue;
async fn get(&self, root: Root) -> Option<Value> {
AsyncLockKp::get(self, root).await
}
async fn get_mut(&self, root: MutRoot) -> Option<MutValue> {
AsyncLockKp::get_mut(self, root).await
}
}
#[derive(Clone)]
pub struct ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> {
pub(crate) first: First,
pub(crate) second: Second,
_p: std::marker::PhantomData<(R, V2, Root, Value2, MutRoot, MutValue2)>,
}
impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
where
First: AsyncKeyPathLike<Root, MutRoot>,
Second: AsyncKeyPathLike<First::Value, First::MutValue, Value = Value2, MutValue = MutValue2>,
{
pub async fn get(&self, root: Root) -> Option<Value2> {
let value = self.first.get(root).await?;
self.second.get(value).await
}
pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
let mut_value = self.first.get_mut(root).await?;
self.second.get_mut(mut_value).await
}
pub fn then_async<
Lock3,
Mid3,
V3,
LockValue3,
MidValue3,
Value3,
MutLock3,
MutMid3,
MutValue3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>(
self,
other: AsyncLockKp<
V2,
Lock3,
Mid3,
V3,
Value2,
LockValue3,
MidValue3,
Value3,
MutValue2,
MutLock3,
MutMid3,
MutValue3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>,
) -> ComposedAsyncLockKp<
R,
V3,
Root,
Value3,
MutRoot,
MutValue3,
Self,
AsyncLockKp<
V2,
Lock3,
Mid3,
V3,
Value2,
LockValue3,
MidValue3,
Value3,
MutValue2,
MutLock3,
MutMid3,
MutValue3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>,
>
where
V2: 'static,
V3: 'static,
Value2: std::borrow::Borrow<V2>,
Value3: std::borrow::Borrow<V3>,
MutValue2: std::borrow::BorrowMut<V2>,
MutValue3: std::borrow::BorrowMut<V3>,
LockValue3: std::borrow::Borrow<Lock3>,
MidValue3: std::borrow::Borrow<Mid3>,
MutLock3: std::borrow::BorrowMut<Lock3>,
MutMid3: std::borrow::BorrowMut<Mid3>,
G3_1: Fn(Value2) -> Option<LockValue3> + Clone,
S3_1: Fn(MutValue2) -> Option<MutLock3> + Clone,
L3: AsyncLockLike<Lock3, MidValue3> + AsyncLockLike<Lock3, MutMid3> + Clone,
G3_2: Fn(MidValue3) -> Option<Value3> + Clone,
S3_2: Fn(MutMid3) -> Option<MutValue3> + Clone,
Lock3: Clone,
{
ComposedAsyncLockKp {
first: self,
second: other,
_p: std::marker::PhantomData,
}
}
pub fn then<V3, Value3, MutValue3, G3, S3>(
self,
next_kp: crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
) -> AsyncKeyPathThenKp<
R,
V3,
Root,
Value3,
MutRoot,
MutValue3,
Self,
crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
>
where
V2: 'static,
V3: 'static,
Value2: std::borrow::Borrow<V2>,
Value3: std::borrow::Borrow<V3>,
MutValue2: std::borrow::BorrowMut<V2>,
MutValue3: std::borrow::BorrowMut<V3>,
G3: Fn(Value2) -> Option<Value3> + Clone,
S3: Fn(MutValue2) -> Option<MutValue3> + Clone,
{
AsyncKeyPathThenKp {
first: self,
second: next_kp,
_p: std::marker::PhantomData,
}
}
pub fn then_lock<
Lock3,
Mid3,
V3,
LockValue3,
MidValue3,
Value3,
MutLock3,
MutMid3,
MutValue3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>(
self,
lock_kp: crate::lock::LockKp<
V2,
Lock3,
Mid3,
V3,
Value2,
LockValue3,
MidValue3,
Value3,
MutValue2,
MutLock3,
MutMid3,
MutValue3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>,
) -> AsyncLockKpThenLockKp<
R,
V3,
Root,
Value3,
MutRoot,
MutValue3,
Self,
crate::lock::LockKp<
V2,
Lock3,
Mid3,
V3,
Value2,
LockValue3,
MidValue3,
Value3,
MutValue2,
MutLock3,
MutMid3,
MutValue3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>,
>
where
V2: 'static,
V3: 'static,
Value2: std::borrow::Borrow<V2>,
Value3: std::borrow::Borrow<V3>,
MutValue2: std::borrow::BorrowMut<V2>,
MutValue3: std::borrow::BorrowMut<V3>,
LockValue3: std::borrow::Borrow<Lock3>,
MidValue3: std::borrow::Borrow<Mid3>,
MutLock3: std::borrow::BorrowMut<Lock3>,
MutMid3: std::borrow::BorrowMut<Mid3>,
G3_1: Fn(Value2) -> Option<LockValue3>,
S3_1: Fn(MutValue2) -> Option<MutLock3>,
L3: crate::lock::LockAccess<Lock3, MidValue3> + crate::lock::LockAccess<Lock3, MutMid3>,
G3_2: Fn(MidValue3) -> Option<Value3>,
S3_2: Fn(MutMid3) -> Option<MutValue3>,
{
AsyncLockKpThenLockKp {
first: self,
second: lock_kp,
_p: std::marker::PhantomData,
}
}
}
#[derive(Clone)]
pub struct KpThenAsyncKeyPath<
R,
V,
V2,
Root,
Value,
Value2,
MutRoot,
MutValue,
MutValue2,
First,
Second,
> {
pub(crate) first: First,
pub(crate) second: Second,
pub(crate) _p:
std::marker::PhantomData<(R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2)>,
}
impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
KpThenAsyncKeyPath<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
where
First: SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
Second: AsyncKeyPathLike<Value, MutValue, Value = Value2, MutValue = MutValue2>,
{
#[inline]
pub async fn get(&self, root: Root) -> Option<Value2> {
let v = self.first.sync_get(root)?;
self.second.get(v).await
}
#[inline]
pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
let mut_v = self.first.sync_get_mut(root)?;
self.second.get_mut(mut_v).await
}
}
#[async_trait(?Send)]
impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
AsyncKeyPathLike<Root, MutRoot>
for KpThenAsyncKeyPath<
R,
V,
V2,
Root,
Value,
Value2,
MutRoot,
MutValue,
MutValue2,
First,
Second,
>
where
First: SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
Second: AsyncKeyPathLike<Value, MutValue, Value = Value2, MutValue = MutValue2>,
{
type Value = Value2;
type MutValue = MutValue2;
async fn get(&self, root: Root) -> Option<Value2> {
let v = self.first.sync_get(root)?;
self.second.get(v).await
}
async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
let mut_v = self.first.sync_get_mut(root)?;
self.second.get_mut(mut_v).await
}
}
impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
KpThenAsyncKeyPath<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
where
First: SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
Second: AsyncKeyPathLike<Value, MutValue, Value = Value2, MutValue = MutValue2>,
{
pub fn then<V3, Value3, MutValue3, G3, S3>(
self,
next_kp: crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
) -> AsyncKeyPathThenKp<
R,
V3,
Root,
Value3,
MutRoot,
MutValue3,
Self,
crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
>
where
V3: 'static,
Value2: std::borrow::Borrow<V2>,
MutValue2: std::borrow::BorrowMut<V2>,
Value3: std::borrow::Borrow<V3>,
MutValue3: std::borrow::BorrowMut<V3>,
G3: Fn(Value2) -> Option<Value3> + Clone,
S3: Fn(MutValue2) -> Option<MutValue3> + Clone,
{
AsyncKeyPathThenKp {
first: self,
second: next_kp,
_p: std::marker::PhantomData,
}
}
}
#[derive(Clone)]
pub struct AsyncKeyPathThenKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> {
pub(crate) first: First,
pub(crate) second: Second,
_p: std::marker::PhantomData<(R, V2, Root, Value2, MutRoot, MutValue2)>,
}
impl<R, V2, Root, Value2, MutRoot, MutValue2, First, RKp, G, S>
AsyncKeyPathThenKp<
R,
V2,
Root,
Value2,
MutRoot,
MutValue2,
First,
crate::Kp<RKp, V2, First::Value, Value2, First::MutValue, MutValue2, G, S>,
>
where
First: AsyncKeyPathLike<Root, MutRoot>,
First::Value: std::borrow::Borrow<RKp>,
First::MutValue: std::borrow::BorrowMut<RKp>,
Value2: std::borrow::Borrow<V2>,
MutValue2: std::borrow::BorrowMut<V2>,
G: Fn(First::Value) -> Option<Value2>,
S: Fn(First::MutValue) -> Option<MutValue2>,
{
#[inline]
pub async fn get(&self, root: Root) -> Option<Value2> {
let value = self.first.get(root).await?;
(self.second.get)(value)
}
#[inline]
pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
let mut_value = self.first.get_mut(root).await?;
(self.second.set)(mut_value)
}
}
#[async_trait(?Send)]
impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> AsyncKeyPathLike<Root, MutRoot>
for ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
where
First: AsyncKeyPathLike<Root, MutRoot>,
Second: AsyncKeyPathLike<First::Value, First::MutValue, Value = Value2, MutValue = MutValue2>,
{
type Value = Value2;
type MutValue = MutValue2;
async fn get(&self, root: Root) -> Option<Value2> {
ComposedAsyncLockKp::get(self, root).await
}
async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
ComposedAsyncLockKp::get_mut(self, root).await
}
}
#[derive(Clone)]
pub struct AsyncLockKpThenLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> {
pub(crate) first: First,
pub(crate) second: Second,
_p: std::marker::PhantomData<(R, V2, Root, Value2, MutRoot, MutValue2)>,
}
impl<
R,
V2,
Root,
Value2,
MutRoot,
MutValue2,
Lock,
Mid,
V,
LockValue,
MidValue,
Value,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
Lock2,
Mid2,
LockValue2,
MidValue2,
MutLock2,
MutMid2,
G2_1,
S2_1,
L2,
G2_2,
S2_2,
>
AsyncLockKpThenLockKp<
R,
V2,
Root,
Value2,
MutRoot,
MutValue2,
AsyncLockKp<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
>,
crate::lock::LockKp<
V,
Lock2,
Mid2,
V2,
Value,
LockValue2,
MidValue2,
Value2,
MutValue,
MutLock2,
MutMid2,
MutValue2,
G2_1,
S2_1,
L2,
G2_2,
S2_2,
>,
>
where
Root: std::borrow::Borrow<R>,
LockValue: std::borrow::Borrow<Lock>,
MidValue: std::borrow::Borrow<Mid>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutLock: std::borrow::BorrowMut<Lock>,
MutMid: std::borrow::BorrowMut<Mid>,
MutValue: std::borrow::BorrowMut<V>,
Value2: std::borrow::Borrow<V2>,
MutValue2: std::borrow::BorrowMut<V2>,
G1: Fn(Root) -> Option<LockValue> + Clone,
S1: Fn(MutRoot) -> Option<MutLock> + Clone,
L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
G2: Fn(MidValue) -> Option<Value> + Clone,
S2: Fn(MutMid) -> Option<MutValue> + Clone,
LockValue2: std::borrow::Borrow<Lock2>,
MidValue2: std::borrow::Borrow<Mid2>,
MutLock2: std::borrow::BorrowMut<Lock2>,
MutMid2: std::borrow::BorrowMut<Mid2>,
G2_1: Fn(Value) -> Option<LockValue2>,
S2_1: Fn(MutValue) -> Option<MutLock2>,
L2: crate::lock::LockAccess<Lock2, MidValue2> + crate::lock::LockAccess<Lock2, MutMid2>,
G2_2: Fn(MidValue2) -> Option<Value2>,
S2_2: Fn(MutMid2) -> Option<MutValue2>,
Lock: Clone,
V: Clone,
V2: Clone,
{
pub async fn get(&self, root: Root) -> Option<Value2> {
let value = self.first.get(root).await?;
self.second.get(value)
}
pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
let mut_value = self.first.get_mut(root).await?;
self.second.get_mut(mut_value)
}
}
impl<
R,
V2,
Root,
Value2,
MutRoot,
MutValue2,
Lock3,
Mid3,
LockValue3,
MidValue3,
MutLock3,
MutMid3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
First,
Second,
>
AsyncLockKpThenLockKp<
R,
V2,
Root,
Value2,
MutRoot,
MutValue2,
ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>,
crate::lock::LockKp<
Value2,
Lock3,
Mid3,
V2,
Value2,
LockValue3,
MidValue3,
Value2,
MutValue2,
MutLock3,
MutMid3,
MutValue2,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>,
>
where
First: AsyncKeyPathLike<Root, MutRoot>,
Second: AsyncKeyPathLike<First::Value, First::MutValue, Value = Value2, MutValue = MutValue2>,
Value2: std::borrow::Borrow<V2>,
MutValue2: std::borrow::BorrowMut<Value2> + std::borrow::BorrowMut<V2>,
LockValue3: std::borrow::Borrow<Lock3>,
MidValue3: std::borrow::Borrow<Mid3>,
MutLock3: std::borrow::BorrowMut<Lock3>,
MutMid3: std::borrow::BorrowMut<Mid3>,
G3_1: Fn(Value2) -> Option<LockValue3>,
S3_1: Fn(MutValue2) -> Option<MutLock3>,
L3: crate::lock::LockAccess<Lock3, MidValue3> + crate::lock::LockAccess<Lock3, MutMid3>,
G3_2: Fn(MidValue3) -> Option<Value2>,
S3_2: Fn(MutMid3) -> Option<MutValue2>,
Value2: Clone,
V2: Clone,
{
pub async fn get(&self, root: Root) -> Option<Value2> {
let value = self.first.get(root).await?;
self.second.get(value)
}
pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
let mut_value = self.first.get_mut(root).await?;
self.second.get_mut(mut_value)
}
}
impl<
R,
V2,
Root,
Value2,
MutRoot,
MutValue2,
Lock3,
Mid3,
LockValue3,
MidValue3,
MutLock3,
MutMid3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
F,
S,
>
AsyncLockKpThenLockKp<
R,
V2,
Root,
Value2,
MutRoot,
MutValue2,
AsyncLockKpThenLockKp<R, V2, Root, Value2, MutRoot, MutValue2, F, S>,
crate::lock::LockKp<
Value2,
Lock3,
Mid3,
V2,
Value2,
LockValue3,
MidValue3,
Value2,
MutValue2,
MutLock3,
MutMid3,
MutValue2,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>,
>
where
F: AsyncKeyPathLike<Root, MutRoot, Value = Value2, MutValue = MutValue2>,
S: SyncKeyPathLike<Value2, Value2, MutValue2, MutValue2>,
Value2: std::borrow::Borrow<V2>,
MutValue2: std::borrow::BorrowMut<Value2> + std::borrow::BorrowMut<V2>,
LockValue3: std::borrow::Borrow<Lock3>,
MidValue3: std::borrow::Borrow<Mid3>,
MutLock3: std::borrow::BorrowMut<Lock3>,
MutMid3: std::borrow::BorrowMut<Mid3>,
G3_1: Fn(Value2) -> Option<LockValue3>,
S3_1: Fn(MutValue2) -> Option<MutLock3>,
L3: crate::lock::LockAccess<Lock3, MidValue3> + crate::lock::LockAccess<Lock3, MutMid3>,
G3_2: Fn(MidValue3) -> Option<Value2>,
S3_2: Fn(MutMid3) -> Option<MutValue2>,
Value2: Clone,
V2: Clone,
{
pub async fn get(&self, root: Root) -> Option<Value2> {
let value = AsyncKeyPathLike::get(&self.first, root).await?;
self.second.get(value)
}
pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
let mut_value = AsyncKeyPathLike::get_mut(&self.first, root).await?;
self.second.get_mut(mut_value)
}
}
#[async_trait(?Send)]
impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> AsyncKeyPathLike<Root, MutRoot>
for AsyncLockKpThenLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
where
First: AsyncKeyPathLike<Root, MutRoot>,
Second: SyncKeyPathLike<First::Value, Value2, First::MutValue, MutValue2>,
{
type Value = Value2;
type MutValue = MutValue2;
async fn get(&self, root: Root) -> Option<Value2> {
let value = AsyncKeyPathLike::get(&self.first, root).await?;
SyncKeyPathLike::sync_get(&self.second, value)
}
async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
let mut_value = AsyncKeyPathLike::get_mut(&self.first, root).await?;
SyncKeyPathLike::sync_get_mut(&self.second, mut_value)
}
}
impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
AsyncLockKpThenLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
where
First: AsyncKeyPathLike<Root, MutRoot>,
{
pub fn then_async<
Lock3,
Mid3,
V3,
LockValue3,
MidValue3,
Value3,
MutLock3,
MutMid3,
MutValue3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>(
self,
other: AsyncLockKp<
Value2,
Lock3,
Mid3,
V3,
Value2,
LockValue3,
MidValue3,
Value3,
MutValue2,
MutLock3,
MutMid3,
MutValue3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>,
) -> ComposedAsyncLockKp<
Root,
V3,
Root,
Value3,
MutRoot,
MutValue3,
Self,
AsyncLockKp<
Value2,
Lock3,
Mid3,
V3,
Value2,
LockValue3,
MidValue3,
Value3,
MutValue2,
MutLock3,
MutMid3,
MutValue3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>,
>
where
V2: 'static,
V3: 'static,
Value2: std::borrow::Borrow<V2>,
Value3: std::borrow::Borrow<V3>,
MutValue2: std::borrow::BorrowMut<V2> + std::borrow::BorrowMut<Value2>,
MutValue3: std::borrow::BorrowMut<V3>,
LockValue3: std::borrow::Borrow<Lock3>,
MidValue3: std::borrow::Borrow<Mid3>,
MutLock3: std::borrow::BorrowMut<Lock3>,
MutMid3: std::borrow::BorrowMut<Mid3>,
G3_1: Fn(Value2) -> Option<LockValue3> + Clone,
S3_1: Fn(MutValue2) -> Option<MutLock3> + Clone,
L3: AsyncLockLike<Lock3, MidValue3> + AsyncLockLike<Lock3, MutMid3> + Clone,
G3_2: Fn(MidValue3) -> Option<Value3> + Clone,
S3_2: Fn(MutMid3) -> Option<MutValue3> + Clone,
Lock3: Clone,
{
ComposedAsyncLockKp {
first: self,
second: other,
_p: std::marker::PhantomData,
}
}
pub fn then_lock<
Lock3,
Mid3,
V3,
LockValue3,
MidValue3,
Value3,
MutLock3,
MutMid3,
MutValue3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>(
self,
lock_kp: crate::lock::LockKp<
Value2,
Lock3,
Mid3,
V3,
Value2,
LockValue3,
MidValue3,
Value3,
MutValue2,
MutLock3,
MutMid3,
MutValue3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>,
) -> AsyncLockKpThenLockKp<
R,
V3,
Root,
Value3,
MutRoot,
MutValue3,
Self,
crate::lock::LockKp<
Value2,
Lock3,
Mid3,
V3,
Value2,
LockValue3,
MidValue3,
Value3,
MutValue2,
MutLock3,
MutMid3,
MutValue3,
G3_1,
S3_1,
L3,
G3_2,
S3_2,
>,
>
where
V3: 'static,
Value2: std::borrow::Borrow<V2>,
Value3: std::borrow::Borrow<V3>,
MutValue2: std::borrow::BorrowMut<Value2>,
MutValue3: std::borrow::BorrowMut<V3>,
LockValue3: std::borrow::Borrow<Lock3>,
MidValue3: std::borrow::Borrow<Mid3>,
MutLock3: std::borrow::BorrowMut<Lock3>,
MutMid3: std::borrow::BorrowMut<Mid3>,
G3_1: Fn(Value2) -> Option<LockValue3>,
S3_1: Fn(MutValue2) -> Option<MutLock3>,
L3: crate::lock::LockAccess<Lock3, MidValue3> + crate::lock::LockAccess<Lock3, MutMid3>,
G3_2: Fn(MidValue3) -> Option<Value3>,
S3_2: Fn(MutMid3) -> Option<MutValue3>,
{
AsyncLockKpThenLockKp {
first: self,
second: lock_kp,
_p: std::marker::PhantomData,
}
}
pub fn then<V3, Value3, MutValue3, G3, S3>(
self,
next_kp: crate::Kp<Value2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
) -> AsyncKeyPathThenKp<
R,
V3,
Root,
Value3,
MutRoot,
MutValue3,
Self,
crate::Kp<Value2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
>
where
V3: 'static,
Value2: std::borrow::Borrow<V2>,
Value3: std::borrow::Borrow<V3>,
MutValue2: std::borrow::BorrowMut<Value2>,
MutValue3: std::borrow::BorrowMut<V3>,
G3: Fn(Value2) -> Option<Value3> + Clone,
S3: Fn(MutValue2) -> Option<MutValue3> + Clone,
{
AsyncKeyPathThenKp {
first: self,
second: next_kp,
_p: std::marker::PhantomData,
}
}
}
#[cfg(feature = "tokio")]
#[derive(Clone)] pub struct TokioMutexAccess<T> {
_phantom: std::marker::PhantomData<T>,
}
#[cfg(feature = "tokio")]
impl<T> TokioMutexAccess<T> {
pub fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
#[cfg(feature = "tokio")]
impl<T> Default for TokioMutexAccess<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "tokio")]
#[async_trait]
impl<'a, T: 'static + Send + Sync> AsyncLockLike<std::sync::Arc<tokio::sync::Mutex<T>>, &'a T>
for TokioMutexAccess<T>
{
#[inline]
async fn lock_read(&self, lock: &std::sync::Arc<tokio::sync::Mutex<T>>) -> Option<&'a T> {
let guard = lock.lock().await;
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
#[inline]
async fn lock_write(&self, lock: &mut std::sync::Arc<tokio::sync::Mutex<T>>) -> Option<&'a T> {
let guard = lock.lock().await;
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
}
#[cfg(feature = "tokio")]
#[async_trait]
impl<'a, T: 'static + Send + Sync> AsyncLockLike<std::sync::Arc<tokio::sync::Mutex<T>>, &'a mut T>
for TokioMutexAccess<T>
{
#[inline]
async fn lock_read(&self, lock: &std::sync::Arc<tokio::sync::Mutex<T>>) -> Option<&'a mut T> {
let mut guard = lock.lock().await;
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
#[inline]
async fn lock_write(
&self,
lock: &mut std::sync::Arc<tokio::sync::Mutex<T>>,
) -> Option<&'a mut T> {
let mut guard = lock.lock().await;
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
}
#[cfg(feature = "tokio")]
pub struct TokioRwLockAccess<T> {
_phantom: std::marker::PhantomData<T>,
}
#[cfg(feature = "tokio")]
impl<T> TokioRwLockAccess<T> {
pub fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
#[cfg(feature = "tokio")]
impl<T> Default for TokioRwLockAccess<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "tokio")]
impl<T> Clone for TokioRwLockAccess<T> {
fn clone(&self) -> Self {
Self {
_phantom: self._phantom,
}
}
}
#[cfg(feature = "tokio")]
#[async_trait]
impl<'a, T: 'static + Send + Sync> AsyncLockLike<std::sync::Arc<tokio::sync::RwLock<T>>, &'a T>
for TokioRwLockAccess<T>
{
async fn lock_read(&self, lock: &std::sync::Arc<tokio::sync::RwLock<T>>) -> Option<&'a T> {
let guard = lock.read().await;
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
async fn lock_write(&self, lock: &mut std::sync::Arc<tokio::sync::RwLock<T>>) -> Option<&'a T> {
let guard = lock.read().await;
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
}
#[cfg(feature = "tokio")]
#[async_trait]
impl<'a, T: 'static + Send + Sync> AsyncLockLike<std::sync::Arc<tokio::sync::RwLock<T>>, &'a mut T>
for TokioRwLockAccess<T>
{
async fn lock_read(&self, lock: &std::sync::Arc<tokio::sync::RwLock<T>>) -> Option<&'a mut T> {
let mut guard = lock.write().await;
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
async fn lock_write(
&self,
lock: &mut std::sync::Arc<tokio::sync::RwLock<T>>,
) -> Option<&'a mut T> {
let mut guard = lock.write().await;
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
}
#[cfg(feature = "tokio")]
pub type AsyncLockKpMutexFor<Root, Lock, Inner> = AsyncLockKp<
Root,
Lock,
Inner,
Inner,
&'static Root,
&'static Lock,
&'static Inner,
&'static Inner,
&'static mut Root,
&'static mut Lock,
&'static mut Inner,
&'static mut Inner,
for<'b> fn(&'b Root) -> Option<&'b Lock>,
for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
TokioMutexAccess<Inner>,
for<'b> fn(&'b Inner) -> Option<&'b Inner>,
for<'b> fn(&'b mut Inner) -> Option<&'b mut Inner>,
>;
#[cfg(feature = "tokio")]
pub type AsyncLockKpRwLockFor<Root, Lock, Inner> = AsyncLockKp<
Root,
Lock,
Inner,
Inner,
&'static Root,
&'static Lock,
&'static Inner,
&'static Inner,
&'static mut Root,
&'static mut Lock,
&'static mut Inner,
&'static mut Inner,
for<'b> fn(&'b Root) -> Option<&'b Lock>,
for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
TokioRwLockAccess<Inner>,
for<'b> fn(&'b Inner) -> Option<&'b Inner>,
for<'b> fn(&'b mut Inner) -> Option<&'b mut Inner>,
>;
#[cfg(all(test, feature = "tokio"))]
mod tests {
use super::*;
use crate::KpType;
#[tokio::test]
async fn test_async_lock_kp_tokio_mutex_basic() {
use tokio::sync::Mutex;
#[derive(Clone)]
struct Root {
data: std::sync::Arc<Mutex<String>>,
}
let root = Root {
data: std::sync::Arc::new(Mutex::new("hello".to_string())),
};
let lock_kp = {
let prev: KpType<Root, std::sync::Arc<Mutex<String>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<String, String> =
Kp::new(|s: &String| Some(s), |s: &mut String| Some(s));
AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
};
let value = lock_kp.get(&root).await;
assert!(value.is_some());
assert_eq!(value.unwrap(), &"hello".to_string());
}
#[tokio::test]
async fn test_async_lock_kp_get_optional_or_else() {
use tokio::sync::Mutex;
#[derive(Clone)]
struct Root {
data: std::sync::Arc<Mutex<i32>>,
}
let mut root = Root {
data: std::sync::Arc::new(Mutex::new(42)),
};
let lock_kp = {
let prev: KpType<Root, std::sync::Arc<Mutex<i32>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
};
assert!(lock_kp.get_optional(None).await.is_none());
assert_eq!(lock_kp.get_optional(Some(&root)).await, Some(&42));
assert!(lock_kp.get_mut_optional(None).await.is_none());
if let Some(m) = lock_kp.get_mut_optional(Some(&mut root)).await {
*m = 99;
}
assert_eq!(lock_kp.get(&root).await, Some(&99));
assert_eq!(*lock_kp.get_or_else(None, || &0).await, 0);
assert_eq!(*lock_kp.get_or_else(Some(&root), || &0).await, 99);
let m = lock_kp
.get_mut_or_else(Some(&mut root), || panic!("unexpected"))
.await;
*m = 100;
assert_eq!(lock_kp.get(&root).await, Some(&100));
}
#[tokio::test]
async fn test_async_lock_kp_tokio_rwlock_basic() {
use tokio::sync::RwLock;
#[derive(Clone)]
struct Root {
data: std::sync::Arc<RwLock<Vec<i32>>>,
}
let root = Root {
data: std::sync::Arc::new(RwLock::new(vec![1, 2, 3, 4, 5])),
};
let lock_kp = {
let prev: KpType<Root, std::sync::Arc<RwLock<Vec<i32>>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<Vec<i32>, Vec<i32>> =
Kp::new(|v: &Vec<i32>| Some(v), |v: &mut Vec<i32>| Some(v));
AsyncLockKp::new(prev, TokioRwLockAccess::new(), next)
};
let value = lock_kp.get(&root).await;
assert!(value.is_some());
assert_eq!(value.unwrap().len(), 5);
}
#[tokio::test]
async fn test_async_lock_kp_concurrent_reads() {
use tokio::sync::RwLock;
#[derive(Clone)]
struct Root {
data: std::sync::Arc<RwLock<i32>>,
}
let root = Root {
data: std::sync::Arc::new(RwLock::new(42)),
};
let lock_kp = {
let prev: KpType<Root, std::sync::Arc<RwLock<i32>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
AsyncLockKp::new(prev, TokioRwLockAccess::new(), next)
};
let lock_kp2 = {
let prev: KpType<Root, std::sync::Arc<RwLock<i32>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
AsyncLockKp::new(prev, TokioRwLockAccess::new(), next)
};
let (a, b) = tokio::join!(lock_kp.get(&root), lock_kp2.get(&root));
assert_eq!(a, Some(&42));
assert_eq!(b, Some(&42));
let value = lock_kp.get(&root).await;
assert_eq!(value, Some(&42));
}
#[tokio::test]
async fn test_async_lock_kp_panic_on_clone_proof() {
use tokio::sync::Mutex;
struct PanicOnClone {
data: String,
}
impl Clone for PanicOnClone {
fn clone(&self) -> Self {
panic!("❌ ASYNC DEEP CLONE DETECTED! PanicOnClone was cloned!");
}
}
#[derive(Clone)]
struct Root {
level1: std::sync::Arc<Mutex<Level1>>,
}
struct Level1 {
panic_data: PanicOnClone,
value: i32,
}
impl Clone for Level1 {
fn clone(&self) -> Self {
panic!("❌ Level1 was deeply cloned in async context!");
}
}
let root = Root {
level1: std::sync::Arc::new(Mutex::new(Level1 {
panic_data: PanicOnClone {
data: "test".to_string(),
},
value: 123,
})),
};
let lock_kp = {
let prev: KpType<Root, std::sync::Arc<Mutex<Level1>>> = Kp::new(
|r: &Root| Some(&r.level1),
|r: &mut Root| Some(&mut r.level1),
);
let next: KpType<Level1, i32> = Kp::new(
|l: &Level1| Some(&l.value),
|l: &mut Level1| Some(&mut l.value),
);
AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
};
let value = lock_kp.get(&root).await;
assert_eq!(value, Some(&123));
}
#[tokio::test]
async fn test_async_lock_kp_structure() {
use tokio::sync::Mutex;
#[derive(Clone)]
struct Root {
data: std::sync::Arc<Mutex<String>>,
}
let lock_kp = {
let prev: KpType<Root, std::sync::Arc<Mutex<String>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<String, String> =
Kp::new(|s: &String| Some(s), |s: &mut String| Some(s));
AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
};
let _ = &lock_kp.prev;
let _ = &lock_kp.mid;
let _ = &lock_kp.next;
}
#[tokio::test]
async fn test_async_kp_then() {
use tokio::sync::Mutex;
#[derive(Clone)]
struct Root {
data: std::sync::Arc<Mutex<Inner>>,
}
#[derive(Clone)]
struct Inner {
value: i32,
}
let root = Root {
data: std::sync::Arc::new(Mutex::new(Inner { value: 42 })),
};
let async_kp = {
let prev: KpType<Root, std::sync::Arc<Mutex<Inner>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<Inner, Inner> = Kp::new(|i: &Inner| Some(i), |i: &mut Inner| Some(i));
AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
};
let value_kp: KpType<Inner, i32> = Kp::new(
|i: &Inner| Some(&i.value),
|i: &mut Inner| Some(&mut i.value),
);
let chained = async_kp.then(value_kp);
let result = chained.get(&root).await;
assert_eq!(result, Some(&42));
}
#[tokio::test]
async fn test_async_kp_later_then() {
use tokio::sync::Mutex;
#[derive(Clone)]
struct Root {
lock1: std::sync::Arc<Mutex<Container>>,
}
#[derive(Clone)]
struct Container {
lock2: std::sync::Arc<Mutex<i32>>,
}
let root = Root {
lock1: std::sync::Arc::new(Mutex::new(Container {
lock2: std::sync::Arc::new(Mutex::new(999)),
})),
};
let async_kp1 = {
let prev: KpType<Root, std::sync::Arc<Mutex<Container>>> =
Kp::new(|r: &Root| Some(&r.lock1), |r: &mut Root| Some(&mut r.lock1));
let next: KpType<Container, Container> =
Kp::new(|c: &Container| Some(c), |c: &mut Container| Some(c));
AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
};
let async_kp2 = {
let prev: KpType<Container, std::sync::Arc<Mutex<i32>>> = Kp::new(
|c: &Container| Some(&c.lock2),
|c: &mut Container| Some(&mut c.lock2),
);
let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
};
let chained = async_kp1.then_async(async_kp2);
let result = chained.get(&root).await;
assert_eq!(result, Some(&999));
}
#[tokio::test]
async fn test_async_kp_then_async_three_levels() {
use tokio::sync::Mutex;
#[derive(Clone)]
struct Root {
a: std::sync::Arc<Mutex<Level1>>,
}
#[derive(Clone)]
struct Level1 {
b: std::sync::Arc<Mutex<Level2>>,
}
#[derive(Clone)]
struct Level2 {
c: std::sync::Arc<Mutex<i32>>,
}
let root = Root {
a: std::sync::Arc::new(Mutex::new(Level1 {
b: std::sync::Arc::new(Mutex::new(Level2 {
c: std::sync::Arc::new(Mutex::new(42)),
})),
})),
};
let kp1 = {
let prev: KpType<Root, std::sync::Arc<Mutex<Level1>>> =
Kp::new(|r: &Root| Some(&r.a), |r: &mut Root| Some(&mut r.a));
let next: KpType<Level1, Level1> =
Kp::new(|l: &Level1| Some(l), |l: &mut Level1| Some(l));
AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
};
let kp2 = {
let prev: KpType<Level1, std::sync::Arc<Mutex<Level2>>> =
Kp::new(|l: &Level1| Some(&l.b), |l: &mut Level1| Some(&mut l.b));
let next: KpType<Level2, Level2> =
Kp::new(|l: &Level2| Some(l), |l: &mut Level2| Some(l));
AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
};
let kp3 = {
let prev: KpType<Level2, std::sync::Arc<Mutex<i32>>> =
Kp::new(|l: &Level2| Some(&l.c), |l: &mut Level2| Some(&mut l.c));
let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
};
let chained = kp1.then_async(kp2).then_async(kp3);
let result = chained.get(&root).await;
assert_eq!(result, Some(&42));
}
}