Skip to main content

rust_key_paths/
async_lock.rs

1//! # Async Lock Keypath Module
2//!
3//! This module provides `AsyncLockKp` for safely navigating through async locked/synchronized data structures.
4//!
5//! # Naming convention (aligned with [crate::sync_kp::SyncKp] and [crate::Kp])
6//!
7//! - **`then`** – chain with a plain [crate::Kp]
8//! - **`then_sync`** – chain with a sync [crate::sync_kp::SyncKp]
9//! - **`then_async`** – chain with another async keypath (e.g. tokio RwLock)
10//! - **`then_pin_future`** – chain with a #[pin] Future field await ([crate::pin])
11//!
12//! Example: `root_lock.then_sync(parking_kp).then_async(async_kp).then_sync(std_lock_kp)`
13//!
14//! # SHALLOW CLONING GUARANTEE
15//!
16//! **IMPORTANT**: All cloning operations in this module are SHALLOW (reference-counted) clones:
17//!
18//! 1. **`AsyncLockKp` derives `Clone`**: Clones function pointers and PhantomData only
19//!    - `prev` and `next` fields contain function pointers (cheap to copy)
20//!    - `mid` field is typically just `PhantomData<T>` (zero-sized, zero-cost)
21//!    - No heap allocations or deep data copies
22//!
23//! 2. **`Lock: Clone` bound** (e.g., `Arc<tokio::sync::Mutex<T>>`):
24//!    - For `Arc<T>`: Only increments the atomic reference count (one atomic operation)
25//!    - The actual data `T` inside is **NEVER** cloned
26//!    - This is the whole point of Arc - shared ownership without copying data
27//!
28//! 3. **`L: Clone` bound** (e.g., `TokioMutexAccess<T>`):
29//!    - Only clones `PhantomData<T>` which is zero-sized
30//!    - Compiled away completely - zero runtime cost
31
32use crate::Kp;
33use async_trait::async_trait;
34use std::fmt;
35// Re-export tokio sync types for convenience
36#[cfg(feature = "tokio")]
37pub use tokio::sync::{Mutex as TokioMutex, RwLock as TokioRwLock};
38
39// =============================================================================
40// Why two traits: AsyncLockLike and AsyncKeyPathLike
41// =============================================================================
42//
43// - AsyncLockLike<Lock, Inner>: One "step" through a lock. Given a Lock (e.g.
44//   std::sync::Arc<Mutex<T>>), it async yields Inner (e.g. &T). Used by the `mid` field of
45//   AsyncLockKp to go from "container" to "value inside the lock". Implemented
46//   by TokioMutexAccess, TokioRwLockAccess, etc.
47//
48// - AsyncKeyPathLike<Root, MutRoot>: A full keypath from Root to a value. Used
49//   so we can chain at any depth: both AsyncLockKp and ComposedAsyncLockKp
50//   implement it, so we can write `kp1.then_async(kp2).then_async(kp3).get(&root)`.
51//   Without this trait we could not express "first and second can be either a
52//   single AsyncLockKp or another ComposedAsyncLockKp" in the type system.
53
54/// Async trait for types that can provide async lock/unlock behavior
55/// Converts from a Lock type to Inner or InnerMut value asynchronously
56#[async_trait]
57pub trait AsyncLockLike<Lock, Inner>: Send + Sync {
58    /// Get immutable access to the inner value asynchronously
59    async fn lock_read(&self, lock: &Lock) -> Option<Inner>;
60
61    /// Get mutable access to the inner value asynchronously
62    async fn lock_write(&self, lock: &mut Lock) -> Option<Inner>;
63}
64
65/// Sync keypath that can be used as the "second" in [AsyncLockKpThenSyncKp] for blanket impls.
66/// Also implemented for [crate::Kp] so [crate::Kp::then_sync] and [crate::Kp::then_async] can chain.
67pub trait SyncKeyPathLike<Root, Value, MutRoot, MutValue> {
68    /// Get an immutable reference through the keypath (sync, non-blocking).
69    ///
70    /// For [crate::sync_kp::SyncKp], this acquires a read/write lock and returns the value.
71    /// For plain [crate::Kp], this navigates to the field directly.
72    ///
73    /// # Example
74    /// ```
75    /// use rust_key_paths::async_lock::SyncKeyPathLike;
76    /// use rust_key_paths::{KpType, SyncKp};
77    /// use std::sync::Mutex;
78    ///
79    /// #[derive(key_paths_derive::Kp)]
80    /// struct WithLocks {
81    ///     std_mutex: std::sync::Mutex<i32>,
82    ///     std_rwlock: std::sync::RwLock<String>,
83    /// }
84    ///
85    /// let locks = WithLocks {
86    ///     std_mutex: Mutex::new(99),
87    ///     std_rwlock: std::sync::RwLock::new("hello".to_string()),
88    /// };
89    /// let mutex_kp = WithLocks::std_mutex();
90    /// let rwlock_kp = WithLocks::std_rwlock();
91    /// let next: KpType<i32, i32> = rust_key_paths::Kp::new(|i: &i32| Some(i), |i: &mut i32| Some(i));
92    /// let lock_kp = SyncKp::new(mutex_kp, rust_key_paths::StdMutexAccess::new(), next);
93    ///
94    /// // sync_get works with SyncKp (same as .get())
95    /// let value = lock_kp.sync_get(&locks).unwrap();
96    /// assert_eq!(*value, 99);
97    /// ```
98    fn sync_get(&self, root: Root) -> Option<Value>;
99
100    /// Get a mutable reference through the keypath (sync, non-blocking).
101    ///
102    /// For [crate::sync_kp::SyncKp], this acquires a write lock and returns a mutable reference.
103    /// For plain [crate::Kp], this navigates to the field mutably.
104    ///
105    /// # Example
106    /// ```
107    /// use rust_key_paths::async_lock::SyncKeyPathLike;
108    /// use rust_key_paths::{KpType, SyncKp};
109    /// use std::sync::Mutex;
110    ///
111    /// #[derive(key_paths_derive::Kp)]
112    /// struct WithLocks {
113    ///     std_mutex: std::sync::Mutex<i32>,
114    ///     std_rwlock: std::sync::RwLock<String>,
115    /// }
116    ///
117    /// let mut locks = WithLocks {
118    ///     std_mutex: Mutex::new(99),
119    ///     std_rwlock: std::sync::RwLock::new("hello".to_string()),
120    /// };
121    /// let mutex_kp = WithLocks::std_mutex();
122    /// let next: KpType<i32, i32> = rust_key_paths::Kp::new(|i: &i32| Some(i), |i: &mut i32| Some(i));
123    /// let lock_kp = SyncKp::new(mutex_kp, rust_key_paths::StdMutexAccess::new(), next);
124    ///
125    /// // sync_get_mut works with SyncKp (same as .get_mut())
126    /// let value = lock_kp.sync_get_mut(&mut locks).unwrap();
127    /// *value = 42;
128    /// assert_eq!(*locks.std_mutex.lock().unwrap(), 42);
129    /// ```
130    fn sync_get_mut(&self, root: MutRoot) -> Option<MutValue>;
131}
132
133impl<R, V, Root, Value, MutRoot, MutValue, G, S> SyncKeyPathLike<Root, Value, MutRoot, MutValue>
134    for crate::Kp<R, V, Root, Value, MutRoot, MutValue, G, S>
135where
136    Root: std::borrow::Borrow<R>,
137    Value: std::borrow::Borrow<V>,
138    MutRoot: std::borrow::BorrowMut<R>,
139    MutValue: std::borrow::BorrowMut<V>,
140    G: Fn(Root) -> Option<Value>,
141    S: Fn(MutRoot) -> Option<MutValue>,
142    // Kp<R, V, Root, Value, MutRoot, MutValue, G, S>: AccessorTrait<R, V, Root, Value, MutRoot, MutValue, G, S>
143{
144    fn sync_get(&self, root: Root) -> Option<Value> {
145        (self.get)(root)
146    }
147    fn sync_get_mut(&self, root: MutRoot) -> Option<MutValue> {
148        (self.set)(root)
149    }
150}
151
152impl<
153    R,
154    Lock,
155    Mid,
156    V,
157    Root,
158    LockValue,
159    MidValue,
160    Value,
161    MutRoot,
162    MutLock,
163    MutMid,
164    MutValue,
165    G1,
166    S1,
167    L,
168    G2,
169    S2,
170> SyncKeyPathLike<Root, Value, MutRoot, MutValue>
171    for crate::sync_kp::SyncKp<
172        R,
173        Lock,
174        Mid,
175        V,
176        Root,
177        LockValue,
178        MidValue,
179        Value,
180        MutRoot,
181        MutLock,
182        MutMid,
183        MutValue,
184        G1,
185        S1,
186        L,
187        G2,
188        S2,
189    >
190where
191    Root: std::borrow::Borrow<R>,
192    LockValue: std::borrow::Borrow<Lock>,
193    MidValue: std::borrow::Borrow<Mid>,
194    Value: std::borrow::Borrow<V>,
195    MutRoot: std::borrow::BorrowMut<R>,
196    MutLock: std::borrow::BorrowMut<Lock>,
197    MutMid: std::borrow::BorrowMut<Mid>,
198    MutValue: std::borrow::BorrowMut<V>,
199    G1: Fn(Root) -> Option<LockValue>,
200    S1: Fn(MutRoot) -> Option<MutLock>,
201    L: crate::sync_kp::LockAccess<Lock, MidValue> + crate::sync_kp::LockAccess<Lock, MutMid>,
202    G2: Fn(MidValue) -> Option<Value>,
203    S2: Fn(MutMid) -> Option<MutValue>,
204{
205    #[inline]
206    fn sync_get(&self, root: Root) -> Option<Value> {
207        self.get(root)
208    }
209    #[inline]
210    fn sync_get_mut(&self, root: MutRoot) -> Option<MutValue> {
211        self.get_mut(root)
212    }
213}
214
215/// Trait for async keypaths (both [AsyncLockKp] and [ComposedAsyncLockKp]) so composition can be any depth.
216///
217/// # Why MutRoot? (RwLock/Mutex interior mutability)
218///
219/// RwLock and Mutex provide **interior mutability**—their `lock()` / `write()` methods take `&self`,
220/// so you can mutate through an immutable reference. For **async lock keypaths**, the mutation
221/// happens inside the lock; you do *not* need a mutable root. `MutRoot` exists for composition
222/// with sync keypaths (e.g. [Kp]) that may require `&mut` along the path. When the path goes
223/// entirely through locks (RwLock/Mutex), `Root` and `MutRoot` are typically the same type
224/// (e.g. `&Root` for both).
225#[async_trait(?Send)]
226pub trait AsyncKeyPathLike<Root, MutRoot> {
227    /// Value type at the end of the keypath.
228    type Value;
229    /// Mutable value type at the end of the keypath.
230    type MutValue;
231    /// Get the value at the end of the keypath.
232    async fn get(&self, root: Root) -> Option<Self::Value>;
233    /// Get mutable access to the value at the end of the keypath.
234    async fn get_mut(&self, root: MutRoot) -> Option<Self::MutValue>;
235}
236
237/// An async keypath that handles async locked values (e.g., std::sync::Arc<tokio::sync::Mutex<T>>)
238///
239/// Structure:
240/// - `prev`: Keypath from Root to Lock container (e.g., std::sync::Arc<tokio::sync::Mutex<Mid>>)
241/// - `mid`: Async lock access handler that goes from Lock to Inner value
242/// - `next`: Keypath from Inner value to final Value
243///
244/// # Type Parameters
245/// - `R`: Root type (base)
246/// - `Lock`: Lock container type (e.g., std::sync::Arc<tokio::sync::Mutex<Mid>>)
247/// - `Mid`: The type inside the lock
248/// - `V`: Final value type
249/// - Rest are the same generic parameters as Kp
250///
251/// # Cloning Behavior
252///
253/// **IMPORTANT**: All `Clone` operations in this struct are SHALLOW clones:
254///
255/// - `AsyncLockKp` itself derives `Clone` - this clones the three field references/closures
256/// - `prev` and `next` fields are `Kp` structs containing function pointers (cheap to clone)
257/// - `mid` field implements `AsyncLockLike` trait - typically just `PhantomData` (zero-cost clone)
258/// - When `Lock: Clone` (e.g., `Arc<tokio::sync::Mutex<T>>`), cloning is just incrementing reference count
259/// - NO deep data cloning occurs - all clones are pointer/reference increments
260#[derive(Clone)] // SHALLOW: Clones function pointers and PhantomData only
261pub struct AsyncLockKp<
262    R,
263    Lock,
264    Mid,
265    V,
266    Root,
267    LockValue,
268    MidValue,
269    Value,
270    MutRoot,
271    MutLock,
272    MutMid,
273    MutValue,
274    G1,
275    S1,
276    L,
277    G2,
278    S2,
279> where
280    Root: std::borrow::Borrow<R>,
281    LockValue: std::borrow::Borrow<Lock>,
282    MidValue: std::borrow::Borrow<Mid>,
283    Value: std::borrow::Borrow<V>,
284    MutRoot: std::borrow::BorrowMut<R>,
285    MutLock: std::borrow::BorrowMut<Lock>,
286    MutMid: std::borrow::BorrowMut<Mid>,
287    MutValue: std::borrow::BorrowMut<V>,
288    G1: Fn(Root) -> Option<LockValue> + Clone,
289    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
290    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
291    G2: Fn(MidValue) -> Option<Value> + Clone,
292    S2: Fn(MutMid) -> Option<MutValue> + Clone,
293{
294    /// Keypath from Root to Lock container
295    prev: Kp<R, Lock, Root, LockValue, MutRoot, MutLock, G1, S1>,
296
297    /// Async lock access handler (converts Lock -> Inner)
298    mid: L,
299
300    /// Keypath from Inner to final Value
301    next: Kp<Mid, V, MidValue, Value, MutMid, MutValue, G2, S2>,
302}
303
304impl<
305    R,
306    Lock,
307    Mid,
308    V,
309    Root,
310    LockValue,
311    MidValue,
312    Value,
313    MutRoot,
314    MutLock,
315    MutMid,
316    MutValue,
317    G1,
318    S1,
319    L,
320    G2,
321    S2,
322> fmt::Debug
323    for AsyncLockKp<
324        R,
325        Lock,
326        Mid,
327        V,
328        Root,
329        LockValue,
330        MidValue,
331        Value,
332        MutRoot,
333        MutLock,
334        MutMid,
335        MutValue,
336        G1,
337        S1,
338        L,
339        G2,
340        S2,
341    >
342where
343    Root: std::borrow::Borrow<R>,
344    LockValue: std::borrow::Borrow<Lock>,
345    MidValue: std::borrow::Borrow<Mid>,
346    Value: std::borrow::Borrow<V>,
347    MutRoot: std::borrow::BorrowMut<R>,
348    MutLock: std::borrow::BorrowMut<Lock>,
349    MutMid: std::borrow::BorrowMut<Mid>,
350    MutValue: std::borrow::BorrowMut<V>,
351    G1: Fn(Root) -> Option<LockValue> + Clone,
352    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
353    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
354    G2: Fn(MidValue) -> Option<Value> + Clone,
355    S2: Fn(MutMid) -> Option<MutValue> + Clone,
356{
357    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358        f.debug_struct("AsyncLockKp")
359            .field("root_ty", &std::any::type_name::<R>())
360            .field("lock_ty", &std::any::type_name::<Lock>())
361            .field("mid_ty", &std::any::type_name::<Mid>())
362            .field("value_ty", &std::any::type_name::<V>())
363            .finish_non_exhaustive()
364    }
365}
366
367impl<
368    R,
369    Lock,
370    Mid,
371    V,
372    Root,
373    LockValue,
374    MidValue,
375    Value,
376    MutRoot,
377    MutLock,
378    MutMid,
379    MutValue,
380    G1,
381    S1,
382    L,
383    G2,
384    S2,
385> fmt::Display
386    for AsyncLockKp<
387        R,
388        Lock,
389        Mid,
390        V,
391        Root,
392        LockValue,
393        MidValue,
394        Value,
395        MutRoot,
396        MutLock,
397        MutMid,
398        MutValue,
399        G1,
400        S1,
401        L,
402        G2,
403        S2,
404    >
405where
406    Root: std::borrow::Borrow<R>,
407    LockValue: std::borrow::Borrow<Lock>,
408    MidValue: std::borrow::Borrow<Mid>,
409    Value: std::borrow::Borrow<V>,
410    MutRoot: std::borrow::BorrowMut<R>,
411    MutLock: std::borrow::BorrowMut<Lock>,
412    MutMid: std::borrow::BorrowMut<Mid>,
413    MutValue: std::borrow::BorrowMut<V>,
414    G1: Fn(Root) -> Option<LockValue> + Clone,
415    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
416    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
417    G2: Fn(MidValue) -> Option<Value> + Clone,
418    S2: Fn(MutMid) -> Option<MutValue> + Clone,
419{
420    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
421        write!(
422            f,
423            "AsyncLockKp<{}, {}, {}, {}>",
424            std::any::type_name::<R>(),
425            std::any::type_name::<Lock>(),
426            std::any::type_name::<Mid>(),
427            std::any::type_name::<V>()
428        )
429    }
430}
431
432impl<
433    R,
434    Lock,
435    Mid,
436    V,
437    Root,
438    LockValue,
439    MidValue,
440    Value,
441    MutRoot,
442    MutLock,
443    MutMid,
444    MutValue,
445    G1,
446    S1,
447    L,
448    G2,
449    S2,
450>
451    AsyncLockKp<
452        R,
453        Lock,
454        Mid,
455        V,
456        Root,
457        LockValue,
458        MidValue,
459        Value,
460        MutRoot,
461        MutLock,
462        MutMid,
463        MutValue,
464        G1,
465        S1,
466        L,
467        G2,
468        S2,
469    >
470where
471    Root: std::borrow::Borrow<R>,
472    LockValue: std::borrow::Borrow<Lock>,
473    MidValue: std::borrow::Borrow<Mid>,
474    Value: std::borrow::Borrow<V>,
475    MutRoot: std::borrow::BorrowMut<R>,
476    MutLock: std::borrow::BorrowMut<Lock>,
477    MutMid: std::borrow::BorrowMut<Mid>,
478    MutValue: std::borrow::BorrowMut<V>,
479    G1: Fn(Root) -> Option<LockValue> + Clone,
480    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
481    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
482    G2: Fn(MidValue) -> Option<Value> + Clone,
483    S2: Fn(MutMid) -> Option<MutValue> + Clone,
484{
485    /// Create a new AsyncLockKp with prev, mid, and next components
486    pub fn new(
487        prev: Kp<R, Lock, Root, LockValue, MutRoot, MutLock, G1, S1>,
488        mid: L,
489        next: Kp<Mid, V, MidValue, Value, MutMid, MutValue, G2, S2>,
490    ) -> Self {
491        Self { prev, mid, next }
492    }
493
494    /// Get the value through the lock
495    ///
496    /// This will:
497    /// 1. Use `prev` to get to the Lock
498    /// 2. Use `mid` to asynchronously lock and get the Inner value
499    /// 3. Use `next` to get to the final Value
500    ///
501    /// # SHALLOW CLONING NOTE
502    ///
503    /// When `lock` is cloned (e.g., `Arc<tokio::sync::Mutex<T>>`):
504    /// - Only the Arc reference count is incremented (one atomic operation)
505    /// - The actual data `T` inside the Mutex is **NEVER** cloned
506    /// - This is safe and efficient - the whole point of Arc
507    #[inline]
508    pub async fn get(&self, root: Root) -> Option<Value>
509    where
510        Lock: Clone,
511    {
512        // SHALLOW CLONE: For std::sync::Arc<Mutex<T>>, only increments Arc refcount
513        // The actual data T is NOT cloned
514        let lock_value = (self.prev.get)(root)?;
515        let lock: &Lock = lock_value.borrow();
516        let lock_clone = lock.clone(); // SHALLOW: Arc refcount++
517
518        // Async lock and get the mid value
519        let mid_value = self.mid.lock_read(&lock_clone).await?;
520
521        // Navigate from mid to final value
522        (self.next.get)(mid_value)
523    }
524
525    /// Get mutable access to the value through the lock
526    #[inline]
527    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue>
528    where
529        Lock: Clone,
530    {
531        // SHALLOW CLONE: For std::sync::Arc<Mutex<T>>, only increments Arc refcount
532        let mut lock_value = (self.prev.set)(root)?;
533        let lock: &mut Lock = lock_value.borrow_mut();
534        let mut lock_clone = lock.clone(); // SHALLOW: Arc refcount++
535
536        // Async lock and get the mid value
537        let mid_value = self.mid.lock_write(&mut lock_clone).await?;
538
539        // Navigate from mid to final value
540        (self.next.set)(mid_value)
541    }
542
543    /// Like [get](AsyncLockKp::get), but takes an optional root: returns `None` if `root` is `None`, otherwise the result of the getter.
544    #[inline]
545    pub async fn get_optional(&self, root: Option<Root>) -> Option<Value>
546    where
547        Lock: Clone,
548    {
549        match root {
550            Some(r) => self.get(r).await,
551            None => None,
552        }
553    }
554
555    /// Like [get_mut](AsyncLockKp::get_mut), but takes an optional root: returns `None` if `root` is `None`, otherwise the result of the setter.
556    #[inline]
557    pub async fn get_mut_optional(&self, root: Option<MutRoot>) -> Option<MutValue>
558    where
559        Lock: Clone,
560    {
561        match root {
562            Some(r) => self.get_mut(r).await,
563            None => None,
564        }
565    }
566
567    /// Returns the value if the keypath succeeds (root is `Some` and get returns `Some`), otherwise calls `f` and returns its result.
568    #[inline]
569    pub async fn get_or_else<F>(&self, root: Option<Root>, f: F) -> Value
570    where
571        Lock: Clone,
572        F: FnOnce() -> Value,
573    {
574        self.get_optional(root).await.unwrap_or_else(f)
575    }
576
577    /// Returns the mutable value if the keypath succeeds (root is `Some` and get_mut returns `Some`), otherwise calls `f` and returns its result.
578    #[inline]
579    pub async fn get_mut_or_else<F>(&self, root: Option<MutRoot>, f: F) -> MutValue
580    where
581        Lock: Clone,
582        F: FnOnce() -> MutValue,
583    {
584        self.get_mut_optional(root).await.unwrap_or_else(f)
585    }
586
587    /// Set the value through the lock using an updater function.
588    ///
589    /// Uses interior mutability—no mutable root required. RwLock/Mutex allow mutation through
590    /// `&self` (lock().write() etc.), so `root` can be `&Root`.
591    ///
592    /// Internally uses: `prev.get` → `mid.lock_read`/`lock_write` → `next.set` (the setter path).
593    pub async fn set<F>(&self, root: Root, updater: F) -> Result<(), String>
594    where
595        Lock: Clone,
596        F: FnOnce(&mut V),
597    {
598        // SHALLOW CLONE: For std::sync::Arc<Mutex<T>>, only increments Arc refcount
599        let lock_value = (self.prev.get)(root).ok_or("Failed to get lock from root")?;
600        let lock: &Lock = lock_value.borrow();
601        let lock_clone = lock.clone(); // SHALLOW: Arc refcount++
602
603        // Async lock and get the mid value
604        let mid_value = self
605            .mid
606            .lock_read(&lock_clone)
607            .await
608            .ok_or("Failed to lock")?;
609
610        // Get the final value
611        let mut mut_value = (self.next.set)(mid_value).ok_or("Failed to navigate to value")?;
612        let v: &mut V = mut_value.borrow_mut();
613
614        // Apply the updater
615        updater(v);
616
617        Ok(())
618    }
619
620    // ========================================================================
621    // Interoperability: then (Kp), then_sync (sync SyncKp), then_async (async keypath)
622    // ========================================================================
623
624    /// Chain this AsyncLockKp with a regular [crate::Kp] (no root at call site).
625    /// Returns an AsyncLockKp that goes one step further; use [AsyncLockKp::get] or [AsyncLockKp::get_mut] with root later.
626    ///
627    /// # Example
628    /// ```ignore
629    /// // Root -> std::sync::Arc<tokio::Mutex<Inner>> -> Inner -> field
630    /// let async_kp = AsyncLockKp::new(root_to_lock, TokioMutexAccess::new(), lock_to_inner);
631    /// let field_kp = Kp::new(|inner: &Inner| Some(&inner.field), |inner: &mut Inner| Some(&mut inner.field));
632    /// let chained = async_kp.then(field_kp);
633    /// let result = chained.get(&root).await;
634    /// ```
635    pub fn then<V2, Value2, MutValue2, G3, S3>(
636        self,
637        next_kp: crate::Kp<V, V2, Value, Value2, MutValue, MutValue2, G3, S3>,
638    ) -> AsyncLockKp<
639        R,
640        Lock,
641        Mid,
642        V2,
643        Root,
644        LockValue,
645        MidValue,
646        Value2,
647        MutRoot,
648        MutLock,
649        MutMid,
650        MutValue2,
651        G1,
652        S1,
653        L,
654        impl Fn(MidValue) -> Option<Value2>
655        + Clone
656        + use<
657            G1,
658            G2,
659            G3,
660            L,
661            Lock,
662            LockValue,
663            Mid,
664            MidValue,
665            MutLock,
666            MutMid,
667            MutRoot,
668            MutValue,
669            MutValue2,
670            R,
671            Root,
672            S1,
673            S2,
674            S3,
675            Value,
676            Value2,
677            V,
678            V2,
679        >,
680        impl Fn(MutMid) -> Option<MutValue2>
681        + Clone
682        + use<
683            G1,
684            G2,
685            G3,
686            L,
687            Lock,
688            LockValue,
689            Mid,
690            MidValue,
691            MutLock,
692            MutMid,
693            MutRoot,
694            MutValue,
695            MutValue2,
696            R,
697            Root,
698            S1,
699            S2,
700            S3,
701            Value,
702            Value2,
703            V,
704            V2,
705        >,
706    >
707    where
708        V: 'static,
709        V2: 'static,
710        Value: std::borrow::Borrow<V>,
711        Value2: std::borrow::Borrow<V2>,
712        MutValue: std::borrow::BorrowMut<V>,
713        MutValue2: std::borrow::BorrowMut<V2>,
714        G3: Fn(Value) -> Option<Value2> + Clone,
715        S3: Fn(MutValue) -> Option<MutValue2> + Clone,
716    {
717        let next_get = self.next.get;
718        let next_set = self.next.set;
719        let second_get = next_kp.get;
720        let second_set = next_kp.set;
721        let chained_kp = crate::Kp::new(
722            move |mid_value: MidValue| next_get(mid_value).and_then(|v| second_get(v)),
723            move |mid_value: MutMid| next_set(mid_value).and_then(|v| second_set(v)),
724        );
725        AsyncLockKp::new(self.prev, self.mid, chained_kp)
726    }
727
728    /// Chain this AsyncLockKp with a sync [crate::sync_kp::SyncKp] (no root at call site).
729    /// Returns a keypath that first goes through the async lock, then through the sync lock; use `.get(&root).await` later.
730    pub fn then_sync<
731        Lock2,
732        Mid2,
733        V2,
734        LockValue2,
735        MidValue2,
736        Value2,
737        MutLock2,
738        MutMid2,
739        MutValue2,
740        G2_1,
741        S2_1,
742        L2,
743        G2_2,
744        S2_2,
745    >(
746        self,
747        lock_kp: crate::sync_kp::SyncKp<
748            V,
749            Lock2,
750            Mid2,
751            V2,
752            Value,
753            LockValue2,
754            MidValue2,
755            Value2,
756            MutValue,
757            MutLock2,
758            MutMid2,
759            MutValue2,
760            G2_1,
761            S2_1,
762            L2,
763            G2_2,
764            S2_2,
765        >,
766    ) -> AsyncLockKpThenSyncKp<
767        R,
768        V2,
769        Root,
770        Value2,
771        MutRoot,
772        MutValue2,
773        Self,
774        crate::sync_kp::SyncKp<
775            V,
776            Lock2,
777            Mid2,
778            V2,
779            Value,
780            LockValue2,
781            MidValue2,
782            Value2,
783            MutValue,
784            MutLock2,
785            MutMid2,
786            MutValue2,
787            G2_1,
788            S2_1,
789            L2,
790            G2_2,
791            S2_2,
792        >,
793    >
794    where
795        V: 'static,
796        V2: 'static,
797        Value: std::borrow::Borrow<V>,
798        Value2: std::borrow::Borrow<V2>,
799        MutValue: std::borrow::BorrowMut<V>,
800        MutValue2: std::borrow::BorrowMut<V2>,
801        LockValue2: std::borrow::Borrow<Lock2>,
802        MidValue2: std::borrow::Borrow<Mid2>,
803        MutLock2: std::borrow::BorrowMut<Lock2>,
804        MutMid2: std::borrow::BorrowMut<Mid2>,
805        G2_1: Fn(Value) -> Option<LockValue2>,
806        S2_1: Fn(MutValue) -> Option<MutLock2>,
807        L2: crate::sync_kp::LockAccess<Lock2, MidValue2> + crate::sync_kp::LockAccess<Lock2, MutMid2>,
808        G2_2: Fn(MidValue2) -> Option<Value2>,
809        S2_2: Fn(MutMid2) -> Option<MutValue2>,
810    {
811        let first = self;
812        let second = lock_kp;
813
814        AsyncLockKpThenSyncKp {
815            first: first,
816            second: second,
817            _p: std::marker::PhantomData,
818        }
819    }
820
821    /// Chain with another async keypath (like [crate::sync_kp::SyncKp::then_sync] for sync locks).
822    ///
823    /// Chain with another async keypath (e.g. tokio RwLock). Use [ComposedAsyncLockKp::get] or
824    /// [ComposedAsyncLockKp::get_mut] with root later.
825    ///
826    /// Root -> AsyncLock1 -> Container -> AsyncLock2 -> Value
827    ///
828    /// # Example
829    /// ```ignore
830    /// // Root -> std::sync::Arc<tokio::Mutex<Container>> -> Container -> std::sync::Arc<tokio::Mutex<Value>> -> Value
831    /// let async_kp1 = AsyncLockKp::new(...); // Root -> Container
832    /// let async_kp2 = AsyncLockKp::new(...); // Container -> Value
833    /// let chained = async_kp1.then_async(async_kp2);
834    /// let result = chained.get(&root).await;
835    /// ```
836    pub fn then_async<
837        Lock2,
838        Mid2,
839        V2,
840        LockValue2,
841        MidValue2,
842        Value2,
843        MutLock2,
844        MutMid2,
845        MutValue2,
846        G2_1,
847        S2_1,
848        L2,
849        G2_2,
850        S2_2,
851    >(
852        self,
853        other: AsyncLockKp<
854            V,
855            Lock2,
856            Mid2,
857            V2,
858            Value,
859            LockValue2,
860            MidValue2,
861            Value2,
862            MutValue,
863            MutLock2,
864            MutMid2,
865            MutValue2,
866            G2_1,
867            S2_1,
868            L2,
869            G2_2,
870            S2_2,
871        >,
872    ) -> ComposedAsyncLockKp<
873        R,
874        V2,
875        Root,
876        Value2,
877        MutRoot,
878        MutValue2,
879        Self,
880        AsyncLockKp<
881            V,
882            Lock2,
883            Mid2,
884            V2,
885            Value,
886            LockValue2,
887            MidValue2,
888            Value2,
889            MutValue,
890            MutLock2,
891            MutMid2,
892            MutValue2,
893            G2_1,
894            S2_1,
895            L2,
896            G2_2,
897            S2_2,
898        >,
899    >
900    where
901        Lock: Clone,
902        Lock2: Clone,
903        V: 'static,
904        V2: 'static,
905        Value: std::borrow::Borrow<V>,
906        LockValue2: std::borrow::Borrow<Lock2>,
907        MidValue2: std::borrow::Borrow<Mid2>,
908        Value2: std::borrow::Borrow<V2>,
909        MutValue: std::borrow::BorrowMut<V>,
910        MutLock2: std::borrow::BorrowMut<Lock2>,
911        MutMid2: std::borrow::BorrowMut<Mid2>,
912        MutValue2: std::borrow::BorrowMut<V2>,
913        G2_1: Fn(Value) -> Option<LockValue2> + Clone,
914        S2_1: Fn(MutValue) -> Option<MutLock2> + Clone,
915        L2: AsyncLockLike<Lock2, MidValue2> + AsyncLockLike<Lock2, MutMid2> + Clone,
916        G2_2: Fn(MidValue2) -> Option<Value2> + Clone,
917        S2_2: Fn(MutMid2) -> Option<MutValue2> + Clone,
918    {
919        let first = self;
920        let second = other;
921
922        ComposedAsyncLockKp {
923            first: first,
924            second: second,
925            _p: std::marker::PhantomData,
926        }
927    }
928}
929
930// Implement AsyncKeyPathLike for AsyncLockKp so it can be used in composition at any depth.
931#[async_trait(?Send)]
932impl<
933    R,
934    Lock,
935    Mid,
936    V,
937    Root,
938    LockValue,
939    MidValue,
940    Value,
941    MutRoot,
942    MutLock,
943    MutMid,
944    MutValue,
945    G1,
946    S1,
947    L,
948    G2,
949    S2,
950> AsyncKeyPathLike<Root, MutRoot>
951    for AsyncLockKp<
952        R,
953        Lock,
954        Mid,
955        V,
956        Root,
957        LockValue,
958        MidValue,
959        Value,
960        MutRoot,
961        MutLock,
962        MutMid,
963        MutValue,
964        G1,
965        S1,
966        L,
967        G2,
968        S2,
969    >
970where
971    Root: std::borrow::Borrow<R>,
972    LockValue: std::borrow::Borrow<Lock>,
973    MidValue: std::borrow::Borrow<Mid>,
974    Value: std::borrow::Borrow<V>,
975    MutRoot: std::borrow::BorrowMut<R>,
976    MutLock: std::borrow::BorrowMut<Lock>,
977    MutMid: std::borrow::BorrowMut<Mid>,
978    MutValue: std::borrow::BorrowMut<V>,
979    G1: Fn(Root) -> Option<LockValue> + Clone,
980    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
981    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
982    G2: Fn(MidValue) -> Option<Value> + Clone,
983    S2: Fn(MutMid) -> Option<MutValue> + Clone,
984    Lock: Clone,
985{
986    type Value = Value;
987    type MutValue = MutValue;
988    async fn get(&self, root: Root) -> Option<Value> {
989        AsyncLockKp::get(self, root).await
990    }
991    async fn get_mut(&self, root: MutRoot) -> Option<MutValue> {
992        AsyncLockKp::get_mut(self, root).await
993    }
994}
995
996/// Chained async lock keypath: two or more async keypaths (Root -> V -> V2 -> ...). Root is passed at get/get_mut time.
997///
998/// Use [AsyncLockKp::then_async] to create (or [ComposedAsyncLockKp::then_async] for more levels). Then call [ComposedAsyncLockKp::get] or
999/// [ComposedAsyncLockKp::get_mut] with root when you need the value.
1000///
1001/// Chain any depth: `kp1.then_async(kp2).then_async(kp3).then_async(kp4)...` then `.get(&root).await`.
1002#[derive(Clone)]
1003pub struct ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> {
1004    first: First,
1005    second: Second,
1006    _p: std::marker::PhantomData<(R, V2, Root, Value2, MutRoot, MutValue2)>,
1007}
1008
1009impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
1010    ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
1011where
1012    First: AsyncKeyPathLike<Root, MutRoot>,
1013    Second: AsyncKeyPathLike<First::Value, First::MutValue, Value = Value2, MutValue = MutValue2>,
1014{
1015    /// Get through all chained async locks (root is passed here).
1016    pub async fn get(&self, root: Root) -> Option<Value2> {
1017        let value = self.first.get(root).await?;
1018        self.second.get(value).await
1019    }
1020
1021    /// Get mutable through all composed locks (root is passed here).
1022    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1023        let mut_value = self.first.get_mut(root).await?;
1024        self.second.get_mut(mut_value).await
1025    }
1026
1027    /// Chain with another async keypath: `a.then_async(b).then_async(c).get(&root).await`.
1028    pub fn then_async<
1029        Lock3,
1030        Mid3,
1031        V3,
1032        LockValue3,
1033        MidValue3,
1034        Value3,
1035        MutLock3,
1036        MutMid3,
1037        MutValue3,
1038        G3_1,
1039        S3_1,
1040        L3,
1041        G3_2,
1042        S3_2,
1043    >(
1044        self,
1045        other: AsyncLockKp<
1046            V2,
1047            Lock3,
1048            Mid3,
1049            V3,
1050            Value2,
1051            LockValue3,
1052            MidValue3,
1053            Value3,
1054            MutValue2,
1055            MutLock3,
1056            MutMid3,
1057            MutValue3,
1058            G3_1,
1059            S3_1,
1060            L3,
1061            G3_2,
1062            S3_2,
1063        >,
1064    ) -> ComposedAsyncLockKp<
1065        R,
1066        V3,
1067        Root,
1068        Value3,
1069        MutRoot,
1070        MutValue3,
1071        Self,
1072        AsyncLockKp<
1073            V2,
1074            Lock3,
1075            Mid3,
1076            V3,
1077            Value2,
1078            LockValue3,
1079            MidValue3,
1080            Value3,
1081            MutValue2,
1082            MutLock3,
1083            MutMid3,
1084            MutValue3,
1085            G3_1,
1086            S3_1,
1087            L3,
1088            G3_2,
1089            S3_2,
1090        >,
1091    >
1092    where
1093        V2: 'static,
1094        V3: 'static,
1095        Value2: std::borrow::Borrow<V2>,
1096        Value3: std::borrow::Borrow<V3>,
1097        MutValue2: std::borrow::BorrowMut<V2>,
1098        MutValue3: std::borrow::BorrowMut<V3>,
1099        LockValue3: std::borrow::Borrow<Lock3>,
1100        MidValue3: std::borrow::Borrow<Mid3>,
1101        MutLock3: std::borrow::BorrowMut<Lock3>,
1102        MutMid3: std::borrow::BorrowMut<Mid3>,
1103        G3_1: Fn(Value2) -> Option<LockValue3> + Clone,
1104        S3_1: Fn(MutValue2) -> Option<MutLock3> + Clone,
1105        L3: AsyncLockLike<Lock3, MidValue3> + AsyncLockLike<Lock3, MutMid3> + Clone,
1106        G3_2: Fn(MidValue3) -> Option<Value3> + Clone,
1107        S3_2: Fn(MutMid3) -> Option<MutValue3> + Clone,
1108        Lock3: Clone,
1109    {
1110        let first = self;
1111        let second = other;
1112
1113        ComposedAsyncLockKp {
1114            first: first,
1115            second: second,
1116            _p: std::marker::PhantomData,
1117        }
1118    }
1119
1120    /// Chain with a regular [crate::Kp] (no root at call site). Use `.get(&root).await` later.
1121    pub fn then<V3, Value3, MutValue3, G3, S3>(
1122        self,
1123        next_kp: crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
1124    ) -> AsyncKeyPathThenKp<
1125        R,
1126        V3,
1127        Root,
1128        Value3,
1129        MutRoot,
1130        MutValue3,
1131        Self,
1132        crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
1133    >
1134    where
1135        V2: 'static,
1136        V3: 'static,
1137        Value2: std::borrow::Borrow<V2>,
1138        Value3: std::borrow::Borrow<V3>,
1139        MutValue2: std::borrow::BorrowMut<V2>,
1140        MutValue3: std::borrow::BorrowMut<V3>,
1141        G3: Fn(Value2) -> Option<Value3> + Clone,
1142        S3: Fn(MutValue2) -> Option<MutValue3> + Clone,
1143    {
1144        let first = self;
1145        let second = next_kp;
1146
1147        AsyncKeyPathThenKp {
1148            first: first,
1149            second: second,
1150            _p: std::marker::PhantomData,
1151        }
1152    }
1153
1154    /// Chain with a sync [crate::sync_kp::SyncKp] (no root at call site). Use `.get(&root).await` later.
1155    pub fn then_sync<
1156        Lock3,
1157        Mid3,
1158        V3,
1159        LockValue3,
1160        MidValue3,
1161        Value3,
1162        MutLock3,
1163        MutMid3,
1164        MutValue3,
1165        G3_1,
1166        S3_1,
1167        L3,
1168        G3_2,
1169        S3_2,
1170    >(
1171        self,
1172        lock_kp: crate::sync_kp::SyncKp<
1173            V2,
1174            Lock3,
1175            Mid3,
1176            V3,
1177            Value2,
1178            LockValue3,
1179            MidValue3,
1180            Value3,
1181            MutValue2,
1182            MutLock3,
1183            MutMid3,
1184            MutValue3,
1185            G3_1,
1186            S3_1,
1187            L3,
1188            G3_2,
1189            S3_2,
1190        >,
1191    ) -> AsyncLockKpThenSyncKp<
1192        R,
1193        V3,
1194        Root,
1195        Value3,
1196        MutRoot,
1197        MutValue3,
1198        Self,
1199        crate::sync_kp::SyncKp<
1200            V2,
1201            Lock3,
1202            Mid3,
1203            V3,
1204            Value2,
1205            LockValue3,
1206            MidValue3,
1207            Value3,
1208            MutValue2,
1209            MutLock3,
1210            MutMid3,
1211            MutValue3,
1212            G3_1,
1213            S3_1,
1214            L3,
1215            G3_2,
1216            S3_2,
1217        >,
1218    >
1219    where
1220        V2: 'static,
1221        V3: 'static,
1222        Value2: std::borrow::Borrow<V2>,
1223        Value3: std::borrow::Borrow<V3>,
1224        MutValue2: std::borrow::BorrowMut<V2>,
1225        MutValue3: std::borrow::BorrowMut<V3>,
1226        LockValue3: std::borrow::Borrow<Lock3>,
1227        MidValue3: std::borrow::Borrow<Mid3>,
1228        MutLock3: std::borrow::BorrowMut<Lock3>,
1229        MutMid3: std::borrow::BorrowMut<Mid3>,
1230        G3_1: Fn(Value2) -> Option<LockValue3>,
1231        S3_1: Fn(MutValue2) -> Option<MutLock3>,
1232        L3: crate::sync_kp::LockAccess<Lock3, MidValue3> + crate::sync_kp::LockAccess<Lock3, MutMid3>,
1233        G3_2: Fn(MidValue3) -> Option<Value3>,
1234        S3_2: Fn(MutMid3) -> Option<MutValue3>,
1235    {
1236        let first = self;
1237        let second = lock_kp;
1238
1239        AsyncLockKpThenSyncKp {
1240            first: first,
1241            second: second,
1242            _p: std::marker::PhantomData,
1243        }
1244    }
1245}
1246
1247/// Keypath that chains a sync keypath ([crate::Kp]) with an [AsyncKeyPathLike]. Use [crate::Kp::then_async] to create; then `.get(&root).await`.
1248#[derive(Clone)]
1249pub struct KpThenAsyncKeyPath<
1250    R,
1251    V,
1252    V2,
1253    Root,
1254    Value,
1255    Value2,
1256    MutRoot,
1257    MutValue,
1258    MutValue2,
1259    First,
1260    Second,
1261> {
1262    first: First,
1263    second: Second,
1264    _p: std::marker::PhantomData<(R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2)>,
1265}
1266
1267impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
1268    KpThenAsyncKeyPath<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
1269{
1270    pub(crate) fn new(first: First, second: Second) -> Self {
1271        Self {
1272            first,
1273            second,
1274            _p: std::marker::PhantomData,
1275        }
1276    }
1277}
1278
1279impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
1280    KpThenAsyncKeyPath<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
1281where
1282    First: SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
1283    Second: AsyncKeyPathLike<Value, MutValue, Value = Value2, MutValue = MutValue2>,
1284{
1285    /// Get through sync keypath then async keypath (root is passed here).
1286    #[inline]
1287    pub async fn get(&self, root: Root) -> Option<Value2> {
1288        let v = self.first.sync_get(root)?;
1289        self.second.get(v).await
1290    }
1291    /// Get mutable through sync then async (root is passed here).
1292    #[inline]
1293    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1294        let mut_v = self.first.sync_get_mut(root)?;
1295        self.second.get_mut(mut_v).await
1296    }
1297}
1298
1299#[async_trait(?Send)]
1300impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
1301    AsyncKeyPathLike<Root, MutRoot>
1302    for KpThenAsyncKeyPath<
1303        R,
1304        V,
1305        V2,
1306        Root,
1307        Value,
1308        Value2,
1309        MutRoot,
1310        MutValue,
1311        MutValue2,
1312        First,
1313        Second,
1314    >
1315where
1316    First: SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
1317    Second: AsyncKeyPathLike<Value, MutValue, Value = Value2, MutValue = MutValue2>,
1318{
1319    type Value = Value2;
1320    type MutValue = MutValue2;
1321    async fn get(&self, root: Root) -> Option<Value2> {
1322        let v = self.first.sync_get(root)?;
1323        self.second.get(v).await
1324    }
1325    async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1326        let mut_v = self.first.sync_get_mut(root)?;
1327        self.second.get_mut(mut_v).await
1328    }
1329}
1330
1331impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
1332    KpThenAsyncKeyPath<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
1333where
1334    First: SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
1335    Second: AsyncKeyPathLike<Value, MutValue, Value = Value2, MutValue = MutValue2>,
1336{
1337    /// Chain with a [crate::Kp]. Use `.get(&root).await` later.
1338    pub fn then<V3, Value3, MutValue3, G3, S3>(
1339        self,
1340        next_kp: crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
1341    ) -> AsyncKeyPathThenKp<
1342        R,
1343        V3,
1344        Root,
1345        Value3,
1346        MutRoot,
1347        MutValue3,
1348        Self,
1349        crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
1350    >
1351    where
1352        V3: 'static,
1353        Value2: std::borrow::Borrow<V2>,
1354        MutValue2: std::borrow::BorrowMut<V2>,
1355        Value3: std::borrow::Borrow<V3>,
1356        MutValue3: std::borrow::BorrowMut<V3>,
1357        G3: Fn(Value2) -> Option<Value3> + Clone,
1358        S3: Fn(MutValue2) -> Option<MutValue3> + Clone,
1359    {
1360        let first = self;
1361        let second = next_kp;
1362
1363        AsyncKeyPathThenKp {
1364            first: first,
1365            second: second,
1366            _p: std::marker::PhantomData,
1367        }
1368    }
1369}
1370
1371/// Keypath that chains an [AsyncKeyPathLike] (async get) with a [crate::Kp] (sync step). Use `.get(&root).await` to run.
1372#[derive(Clone)]
1373pub struct AsyncKeyPathThenKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> {
1374    first: First,
1375    second: Second,
1376    _p: std::marker::PhantomData<(R, V2, Root, Value2, MutRoot, MutValue2)>,
1377}
1378
1379/// Impl when Second is a Kp whose input type is First::Value (covers both Kp<First::Value, V2, ...> and Kp<RKp, V2, First::Value, ...>).
1380impl<R, V2, Root, Value2, MutRoot, MutValue2, First, RKp, G, S>
1381    AsyncKeyPathThenKp<
1382        R,
1383        V2,
1384        Root,
1385        Value2,
1386        MutRoot,
1387        MutValue2,
1388        First,
1389        crate::Kp<RKp, V2, First::Value, Value2, First::MutValue, MutValue2, G, S>,
1390    >
1391where
1392    First: AsyncKeyPathLike<Root, MutRoot>,
1393    First::Value: std::borrow::Borrow<RKp>,
1394    First::MutValue: std::borrow::BorrowMut<RKp>,
1395    Value2: std::borrow::Borrow<V2>,
1396    MutValue2: std::borrow::BorrowMut<V2>,
1397    G: Fn(First::Value) -> Option<Value2>,
1398    S: Fn(First::MutValue) -> Option<MutValue2>,
1399{
1400    /// Get through async keypath then Kp (root is passed here).
1401    #[inline]
1402    pub async fn get(&self, root: Root) -> Option<Value2> {
1403        let value = self.first.get(root).await?;
1404        (self.second.get)(value)
1405    }
1406    /// Get mutable through async keypath then Kp (root is passed here).
1407    #[inline]
1408    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1409        let mut_value = self.first.get_mut(root).await?;
1410        (self.second.set)(mut_value)
1411    }
1412}
1413
1414#[async_trait(?Send)]
1415impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> AsyncKeyPathLike<Root, MutRoot>
1416    for ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
1417where
1418    First: AsyncKeyPathLike<Root, MutRoot>,
1419    Second: AsyncKeyPathLike<First::Value, First::MutValue, Value = Value2, MutValue = MutValue2>,
1420{
1421    type Value = Value2;
1422    type MutValue = MutValue2;
1423    async fn get(&self, root: Root) -> Option<Value2> {
1424        ComposedAsyncLockKp::get(self, root).await
1425    }
1426    async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1427        ComposedAsyncLockKp::get_mut(self, root).await
1428    }
1429}
1430
1431// =============================================================================
1432// AsyncLockKpThenSyncKp: AsyncLockKp .then_sync(SyncKp) — async then sync lock
1433// =============================================================================
1434
1435/// Keypath that goes through an async lock then a sync [crate::sync_kp::SyncKp].
1436/// Use [AsyncLockKp::then_sync] to create; then call [AsyncLockKpThenSyncKp::get] or [AsyncLockKpThenSyncKp::get_mut] with root.
1437#[derive(Clone)]
1438pub struct AsyncLockKpThenSyncKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> {
1439    first: First,
1440    second: Second,
1441    _p: std::marker::PhantomData<(R, V2, Root, Value2, MutRoot, MutValue2)>,
1442}
1443
1444impl<
1445    R,
1446    V2,
1447    Root,
1448    Value2,
1449    MutRoot,
1450    MutValue2,
1451    Lock,
1452    Mid,
1453    V,
1454    LockValue,
1455    MidValue,
1456    Value,
1457    MutLock,
1458    MutMid,
1459    MutValue,
1460    G1,
1461    S1,
1462    L,
1463    G2,
1464    S2,
1465    Lock2,
1466    Mid2,
1467    LockValue2,
1468    MidValue2,
1469    MutLock2,
1470    MutMid2,
1471    G2_1,
1472    S2_1,
1473    L2,
1474    G2_2,
1475    S2_2,
1476>
1477    AsyncLockKpThenSyncKp<
1478        R,
1479        V2,
1480        Root,
1481        Value2,
1482        MutRoot,
1483        MutValue2,
1484        AsyncLockKp<
1485            R,
1486            Lock,
1487            Mid,
1488            V,
1489            Root,
1490            LockValue,
1491            MidValue,
1492            Value,
1493            MutRoot,
1494            MutLock,
1495            MutMid,
1496            MutValue,
1497            G1,
1498            S1,
1499            L,
1500            G2,
1501            S2,
1502        >,
1503        crate::sync_kp::SyncKp<
1504            V,
1505            Lock2,
1506            Mid2,
1507            V2,
1508            Value,
1509            LockValue2,
1510            MidValue2,
1511            Value2,
1512            MutValue,
1513            MutLock2,
1514            MutMid2,
1515            MutValue2,
1516            G2_1,
1517            S2_1,
1518            L2,
1519            G2_2,
1520            S2_2,
1521        >,
1522    >
1523where
1524    Root: std::borrow::Borrow<R>,
1525    LockValue: std::borrow::Borrow<Lock>,
1526    MidValue: std::borrow::Borrow<Mid>,
1527    Value: std::borrow::Borrow<V>,
1528    MutRoot: std::borrow::BorrowMut<R>,
1529    MutLock: std::borrow::BorrowMut<Lock>,
1530    MutMid: std::borrow::BorrowMut<Mid>,
1531    MutValue: std::borrow::BorrowMut<V>,
1532    Value2: std::borrow::Borrow<V2>,
1533    MutValue2: std::borrow::BorrowMut<V2>,
1534    G1: Fn(Root) -> Option<LockValue> + Clone,
1535    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
1536    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
1537    G2: Fn(MidValue) -> Option<Value> + Clone,
1538    S2: Fn(MutMid) -> Option<MutValue> + Clone,
1539    LockValue2: std::borrow::Borrow<Lock2>,
1540    MidValue2: std::borrow::Borrow<Mid2>,
1541    MutLock2: std::borrow::BorrowMut<Lock2>,
1542    MutMid2: std::borrow::BorrowMut<Mid2>,
1543    G2_1: Fn(Value) -> Option<LockValue2>,
1544    S2_1: Fn(MutValue) -> Option<MutLock2>,
1545    L2: crate::sync_kp::LockAccess<Lock2, MidValue2> + crate::sync_kp::LockAccess<Lock2, MutMid2>,
1546    G2_2: Fn(MidValue2) -> Option<Value2>,
1547    S2_2: Fn(MutMid2) -> Option<MutValue2>,
1548    Lock: Clone,
1549{
1550    /// Get through async lock then sync lock (root is passed here).
1551    pub async fn get(&self, root: Root) -> Option<Value2> {
1552        let value = self.first.get(root).await?;
1553        self.second.get(value)
1554    }
1555
1556    /// Get mutable through async lock then sync lock (root is passed here).
1557    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1558        let mut_value = self.first.get_mut(root).await?;
1559        self.second.get_mut(mut_value)
1560    }
1561}
1562
1563// AsyncLockKpThenSyncKp when First is ComposedAsyncLockKp (so ComposedAsyncLockKp::then_sync works).
1564impl<
1565    R,
1566    V2,
1567    Root,
1568    Value2,
1569    MutRoot,
1570    MutValue2,
1571    Lock3,
1572    Mid3,
1573    LockValue3,
1574    MidValue3,
1575    MutLock3,
1576    MutMid3,
1577    G3_1,
1578    S3_1,
1579    L3,
1580    G3_2,
1581    S3_2,
1582    First,
1583    Second,
1584>
1585    AsyncLockKpThenSyncKp<
1586        R,
1587        V2,
1588        Root,
1589        Value2,
1590        MutRoot,
1591        MutValue2,
1592        ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>,
1593        crate::sync_kp::SyncKp<
1594            Value2,
1595            Lock3,
1596            Mid3,
1597            V2,
1598            Value2,
1599            LockValue3,
1600            MidValue3,
1601            Value2,
1602            MutValue2,
1603            MutLock3,
1604            MutMid3,
1605            MutValue2,
1606            G3_1,
1607            S3_1,
1608            L3,
1609            G3_2,
1610            S3_2,
1611        >,
1612    >
1613where
1614    First: AsyncKeyPathLike<Root, MutRoot>,
1615    Second: AsyncKeyPathLike<First::Value, First::MutValue, Value = Value2, MutValue = MutValue2>,
1616    Value2: std::borrow::Borrow<V2>,
1617    MutValue2: std::borrow::BorrowMut<Value2> + std::borrow::BorrowMut<V2>,
1618    LockValue3: std::borrow::Borrow<Lock3>,
1619    MidValue3: std::borrow::Borrow<Mid3>,
1620    MutLock3: std::borrow::BorrowMut<Lock3>,
1621    MutMid3: std::borrow::BorrowMut<Mid3>,
1622    G3_1: Fn(Value2) -> Option<LockValue3>,
1623    S3_1: Fn(MutValue2) -> Option<MutLock3>,
1624    L3: crate::sync_kp::LockAccess<Lock3, MidValue3> + crate::sync_kp::LockAccess<Lock3, MutMid3>,
1625    G3_2: Fn(MidValue3) -> Option<Value2>,
1626    S3_2: Fn(MutMid3) -> Option<MutValue2>,
1627{
1628    /// Get through composed async then sync lock (root is passed here).
1629    pub async fn get(&self, root: Root) -> Option<Value2> {
1630        let value = self.first.get(root).await?;
1631        self.second.get(value)
1632    }
1633    /// Get mutable through composed async then sync lock (root is passed here).
1634    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1635        let mut_value = self.first.get_mut(root).await?;
1636        self.second.get_mut(mut_value)
1637    }
1638}
1639
1640// AsyncLockKpThenSyncKp when First is AsyncLockKpThenSyncKp (nested; enables .then_sync().then_sync() chains).
1641impl<
1642    R,
1643    V2,
1644    Root,
1645    Value2,
1646    MutRoot,
1647    MutValue2,
1648    Lock3,
1649    Mid3,
1650    LockValue3,
1651    MidValue3,
1652    MutLock3,
1653    MutMid3,
1654    G3_1,
1655    S3_1,
1656    L3,
1657    G3_2,
1658    S3_2,
1659    F,
1660    S,
1661>
1662    AsyncLockKpThenSyncKp<
1663        R,
1664        V2,
1665        Root,
1666        Value2,
1667        MutRoot,
1668        MutValue2,
1669        AsyncLockKpThenSyncKp<R, V2, Root, Value2, MutRoot, MutValue2, F, S>,
1670        crate::sync_kp::SyncKp<
1671            Value2,
1672            Lock3,
1673            Mid3,
1674            V2,
1675            Value2,
1676            LockValue3,
1677            MidValue3,
1678            Value2,
1679            MutValue2,
1680            MutLock3,
1681            MutMid3,
1682            MutValue2,
1683            G3_1,
1684            S3_1,
1685            L3,
1686            G3_2,
1687            S3_2,
1688        >,
1689    >
1690where
1691    F: AsyncKeyPathLike<Root, MutRoot, Value = Value2, MutValue = MutValue2>,
1692    S: SyncKeyPathLike<Value2, Value2, MutValue2, MutValue2>,
1693    Value2: std::borrow::Borrow<V2>,
1694    MutValue2: std::borrow::BorrowMut<Value2> + std::borrow::BorrowMut<V2>,
1695    LockValue3: std::borrow::Borrow<Lock3>,
1696    MidValue3: std::borrow::Borrow<Mid3>,
1697    MutLock3: std::borrow::BorrowMut<Lock3>,
1698    MutMid3: std::borrow::BorrowMut<Mid3>,
1699    G3_1: Fn(Value2) -> Option<LockValue3>,
1700    S3_1: Fn(MutValue2) -> Option<MutLock3>,
1701    L3: crate::sync_kp::LockAccess<Lock3, MidValue3> + crate::sync_kp::LockAccess<Lock3, MutMid3>,
1702    G3_2: Fn(MidValue3) -> Option<Value2>,
1703    S3_2: Fn(MutMid3) -> Option<MutValue2>,
1704{
1705    /// Get through async then sync then sync lock (root is passed here).
1706    pub async fn get(&self, root: Root) -> Option<Value2> {
1707        let value = AsyncKeyPathLike::get(&self.first, root).await?;
1708        self.second.get(value)
1709    }
1710    /// Get mutable through async then sync then sync lock (root is passed here).
1711    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1712        let mut_value = AsyncKeyPathLike::get_mut(&self.first, root).await?;
1713        self.second.get_mut(mut_value)
1714    }
1715}
1716
1717// Blanket AsyncKeyPathLike for AsyncLockKpThenSyncKp so nested chains (then_sync().then_sync()) work.
1718#[async_trait(?Send)]
1719impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> AsyncKeyPathLike<Root, MutRoot>
1720    for AsyncLockKpThenSyncKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
1721where
1722    First: AsyncKeyPathLike<Root, MutRoot>,
1723    Second: SyncKeyPathLike<First::Value, Value2, First::MutValue, MutValue2>,
1724{
1725    type Value = Value2;
1726    type MutValue = MutValue2;
1727    async fn get(&self, root: Root) -> Option<Value2> {
1728        let value = AsyncKeyPathLike::get(&self.first, root).await?;
1729        SyncKeyPathLike::sync_get(&self.second, value)
1730    }
1731    async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1732        let mut_value = AsyncKeyPathLike::get_mut(&self.first, root).await?;
1733        SyncKeyPathLike::sync_get_mut(&self.second, mut_value)
1734    }
1735}
1736
1737// then_sync and then on AsyncLockKpThenSyncKp so chains can continue.
1738impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
1739    AsyncLockKpThenSyncKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
1740where
1741    First: AsyncKeyPathLike<Root, MutRoot>,
1742{
1743    /// Chain with an async keypath (e.g. tokio RwLock): ... -> Value2 -> async lock -> Value3.
1744    /// Use `.get(&root).await` or `.get_mut(...).await` on the returned [ComposedAsyncLockKp].
1745    pub fn then_async<
1746        Lock3,
1747        Mid3,
1748        V3,
1749        LockValue3,
1750        MidValue3,
1751        Value3,
1752        MutLock3,
1753        MutMid3,
1754        MutValue3,
1755        G3_1,
1756        S3_1,
1757        L3,
1758        G3_2,
1759        S3_2,
1760    >(
1761        self,
1762        other: AsyncLockKp<
1763            Value2,
1764            Lock3,
1765            Mid3,
1766            V3,
1767            Value2,
1768            LockValue3,
1769            MidValue3,
1770            Value3,
1771            MutValue2,
1772            MutLock3,
1773            MutMid3,
1774            MutValue3,
1775            G3_1,
1776            S3_1,
1777            L3,
1778            G3_2,
1779            S3_2,
1780        >,
1781    ) -> ComposedAsyncLockKp<
1782        Root,
1783        V3,
1784        Root,
1785        Value3,
1786        MutRoot,
1787        MutValue3,
1788        Self,
1789        AsyncLockKp<
1790            Value2,
1791            Lock3,
1792            Mid3,
1793            V3,
1794            Value2,
1795            LockValue3,
1796            MidValue3,
1797            Value3,
1798            MutValue2,
1799            MutLock3,
1800            MutMid3,
1801            MutValue3,
1802            G3_1,
1803            S3_1,
1804            L3,
1805            G3_2,
1806            S3_2,
1807        >,
1808    >
1809    where
1810        V2: 'static,
1811        V3: 'static,
1812        Value2: std::borrow::Borrow<V2>,
1813        Value3: std::borrow::Borrow<V3>,
1814        MutValue2: std::borrow::BorrowMut<V2> + std::borrow::BorrowMut<Value2>,
1815        MutValue3: std::borrow::BorrowMut<V3>,
1816        LockValue3: std::borrow::Borrow<Lock3>,
1817        MidValue3: std::borrow::Borrow<Mid3>,
1818        MutLock3: std::borrow::BorrowMut<Lock3>,
1819        MutMid3: std::borrow::BorrowMut<Mid3>,
1820        G3_1: Fn(Value2) -> Option<LockValue3> + Clone,
1821        S3_1: Fn(MutValue2) -> Option<MutLock3> + Clone,
1822        L3: AsyncLockLike<Lock3, MidValue3> + AsyncLockLike<Lock3, MutMid3> + Clone,
1823        G3_2: Fn(MidValue3) -> Option<Value3> + Clone,
1824        S3_2: Fn(MutMid3) -> Option<MutValue3> + Clone,
1825        Lock3: Clone,
1826    {
1827        let first = self;
1828        let second = other;
1829
1830        ComposedAsyncLockKp {
1831            first: first,
1832            second: second,
1833            _p: std::marker::PhantomData,
1834        }
1835    }
1836
1837    /// Chain with another sync [crate::sync_kp::SyncKp]. Use `.get(&root).await` later.
1838    pub fn then_sync<
1839        Lock3,
1840        Mid3,
1841        V3,
1842        LockValue3,
1843        MidValue3,
1844        Value3,
1845        MutLock3,
1846        MutMid3,
1847        MutValue3,
1848        G3_1,
1849        S3_1,
1850        L3,
1851        G3_2,
1852        S3_2,
1853    >(
1854        self,
1855        lock_kp: crate::sync_kp::SyncKp<
1856            Value2,
1857            Lock3,
1858            Mid3,
1859            V3,
1860            Value2,
1861            LockValue3,
1862            MidValue3,
1863            Value3,
1864            MutValue2,
1865            MutLock3,
1866            MutMid3,
1867            MutValue3,
1868            G3_1,
1869            S3_1,
1870            L3,
1871            G3_2,
1872            S3_2,
1873        >,
1874    ) -> AsyncLockKpThenSyncKp<
1875        R,
1876        V3,
1877        Root,
1878        Value3,
1879        MutRoot,
1880        MutValue3,
1881        Self,
1882        crate::sync_kp::SyncKp<
1883            Value2,
1884            Lock3,
1885            Mid3,
1886            V3,
1887            Value2,
1888            LockValue3,
1889            MidValue3,
1890            Value3,
1891            MutValue2,
1892            MutLock3,
1893            MutMid3,
1894            MutValue3,
1895            G3_1,
1896            S3_1,
1897            L3,
1898            G3_2,
1899            S3_2,
1900        >,
1901    >
1902    where
1903        V3: 'static,
1904        Value2: std::borrow::Borrow<V2>,
1905        Value3: std::borrow::Borrow<V3>,
1906        MutValue2: std::borrow::BorrowMut<Value2>,
1907        MutValue3: std::borrow::BorrowMut<V3>,
1908        LockValue3: std::borrow::Borrow<Lock3>,
1909        MidValue3: std::borrow::Borrow<Mid3>,
1910        MutLock3: std::borrow::BorrowMut<Lock3>,
1911        MutMid3: std::borrow::BorrowMut<Mid3>,
1912        G3_1: Fn(Value2) -> Option<LockValue3>,
1913        S3_1: Fn(MutValue2) -> Option<MutLock3>,
1914        L3: crate::sync_kp::LockAccess<Lock3, MidValue3> + crate::sync_kp::LockAccess<Lock3, MutMid3>,
1915        G3_2: Fn(MidValue3) -> Option<Value3>,
1916        S3_2: Fn(MutMid3) -> Option<MutValue3>,
1917    {
1918        let first = self;
1919        let second = lock_kp;
1920
1921        AsyncLockKpThenSyncKp {
1922            first: first,
1923            second: second,
1924            _p: std::marker::PhantomData,
1925        }
1926    }
1927
1928    /// Chain with a regular [crate::Kp]. Use `.get(&root).await` later.
1929    pub fn then<V3, Value3, MutValue3, G3, S3>(
1930        self,
1931        next_kp: crate::Kp<Value2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
1932    ) -> AsyncKeyPathThenKp<
1933        R,
1934        V3,
1935        Root,
1936        Value3,
1937        MutRoot,
1938        MutValue3,
1939        Self,
1940        crate::Kp<Value2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
1941    >
1942    where
1943        V3: 'static,
1944        Value2: std::borrow::Borrow<V2>,
1945        Value3: std::borrow::Borrow<V3>,
1946        MutValue2: std::borrow::BorrowMut<Value2>,
1947        MutValue3: std::borrow::BorrowMut<V3>,
1948        G3: Fn(Value2) -> Option<Value3> + Clone,
1949        S3: Fn(MutValue2) -> Option<MutValue3> + Clone,
1950    {
1951        let first = self;
1952        let second = next_kp;
1953
1954        AsyncKeyPathThenKp {
1955            first: first,
1956            second: second,
1957            _p: std::marker::PhantomData,
1958        }
1959    }
1960}
1961
1962// ============================================================================
1963// Tokio Mutex Access Implementation
1964// ============================================================================
1965
1966#[cfg(feature = "tokio")]
1967/// Async lock access implementation for std::sync::Arc<tokio::sync::Mutex<T>>
1968///
1969/// # Cloning Behavior
1970///
1971/// This struct only contains `PhantomData<T>`.
1972/// Cloning is a **zero-cost operation** - no data is copied.
1973#[derive(Clone)] // ZERO-COST: Only clones PhantomData (zero-sized type)
1974pub struct TokioMutexAccess<T> {
1975    _phantom: std::marker::PhantomData<T>,
1976}
1977
1978#[cfg(feature = "tokio")]
1979impl<T> TokioMutexAccess<T> {
1980    pub fn new() -> Self {
1981        Self {
1982            _phantom: std::marker::PhantomData,
1983        }
1984    }
1985}
1986
1987#[cfg(feature = "tokio")]
1988impl<T> Default for TokioMutexAccess<T> {
1989    fn default() -> Self {
1990        Self::new()
1991    }
1992}
1993
1994// Implementation for immutable access
1995#[cfg(feature = "tokio")]
1996#[async_trait]
1997impl<'a, T: 'static + Send + Sync> AsyncLockLike<std::sync::Arc<tokio::sync::Mutex<T>>, &'a T>
1998    for TokioMutexAccess<T>
1999{
2000    #[inline]
2001    async fn lock_read(&self, lock: &std::sync::Arc<tokio::sync::Mutex<T>>) -> Option<&'a T> {
2002        // SHALLOW CLONE: Only Arc refcount is incremented
2003        let guard = lock.lock().await;
2004        let ptr = &*guard as *const T;
2005        unsafe { Some(&*ptr) }
2006    }
2007
2008    #[inline]
2009    async fn lock_write(&self, lock: &mut std::sync::Arc<tokio::sync::Mutex<T>>) -> Option<&'a T> {
2010        let guard = lock.lock().await;
2011        let ptr = &*guard as *const T;
2012        unsafe { Some(&*ptr) }
2013    }
2014}
2015
2016// Implementation for mutable access
2017#[cfg(feature = "tokio")]
2018#[async_trait]
2019impl<'a, T: 'static + Send + Sync> AsyncLockLike<std::sync::Arc<tokio::sync::Mutex<T>>, &'a mut T>
2020    for TokioMutexAccess<T>
2021{
2022    #[inline]
2023    async fn lock_read(&self, lock: &std::sync::Arc<tokio::sync::Mutex<T>>) -> Option<&'a mut T> {
2024        // SHALLOW CLONE: Only Arc refcount is incremented
2025        let mut guard = lock.lock().await;
2026        let ptr = &mut *guard as *mut T;
2027        unsafe { Some(&mut *ptr) }
2028    }
2029
2030    #[inline]
2031    async fn lock_write(
2032        &self,
2033        lock: &mut std::sync::Arc<tokio::sync::Mutex<T>>,
2034    ) -> Option<&'a mut T> {
2035        let mut guard = lock.lock().await;
2036        let ptr = &mut *guard as *mut T;
2037        unsafe { Some(&mut *ptr) }
2038    }
2039}
2040
2041// ============================================================================
2042// Tokio RwLock Access Implementation
2043// ============================================================================
2044
2045#[cfg(feature = "tokio")]
2046/// Async lock access implementation for std::sync::Arc<tokio::sync::RwLock<T>>
2047///
2048/// # Cloning Behavior
2049///
2050/// This struct only contains `PhantomData<T>`.
2051/// Cloning is a **zero-cost operation** - no data is copied.
2052/// Manual Clone impl so `T: Clone` is not required (e.g. for `Level3` with `RwLock<i32>`).
2053pub struct TokioRwLockAccess<T> {
2054    _phantom: std::marker::PhantomData<T>,
2055}
2056
2057#[cfg(feature = "tokio")]
2058impl<T> TokioRwLockAccess<T> {
2059    pub fn new() -> Self {
2060        Self {
2061            _phantom: std::marker::PhantomData,
2062        }
2063    }
2064}
2065
2066#[cfg(feature = "tokio")]
2067impl<T> Default for TokioRwLockAccess<T> {
2068    fn default() -> Self {
2069        Self::new()
2070    }
2071}
2072
2073#[cfg(feature = "tokio")]
2074impl<T> Clone for TokioRwLockAccess<T> {
2075    fn clone(&self) -> Self {
2076        Self {
2077            _phantom: self._phantom,
2078        }
2079    }
2080}
2081
2082// Implementation for immutable access (read lock)
2083#[cfg(feature = "tokio")]
2084#[async_trait]
2085impl<'a, T: 'static + Send + Sync> AsyncLockLike<std::sync::Arc<tokio::sync::RwLock<T>>, &'a T>
2086    for TokioRwLockAccess<T>
2087{
2088    async fn lock_read(&self, lock: &std::sync::Arc<tokio::sync::RwLock<T>>) -> Option<&'a T> {
2089        // SHALLOW CLONE: Only Arc refcount is incremented
2090        let guard = lock.read().await;
2091        let ptr = &*guard as *const T;
2092        unsafe { Some(&*ptr) }
2093    }
2094
2095    async fn lock_write(&self, lock: &mut std::sync::Arc<tokio::sync::RwLock<T>>) -> Option<&'a T> {
2096        // For immutable access, use read lock
2097        let guard = lock.read().await;
2098        let ptr = &*guard as *const T;
2099        unsafe { Some(&*ptr) }
2100    }
2101}
2102
2103// Implementation for mutable access (write lock)
2104#[cfg(feature = "tokio")]
2105#[async_trait]
2106impl<'a, T: 'static + Send + Sync> AsyncLockLike<std::sync::Arc<tokio::sync::RwLock<T>>, &'a mut T>
2107    for TokioRwLockAccess<T>
2108{
2109    async fn lock_read(&self, lock: &std::sync::Arc<tokio::sync::RwLock<T>>) -> Option<&'a mut T> {
2110        // For mutable access, use write lock
2111        let mut guard = lock.write().await;
2112        let ptr = &mut *guard as *mut T;
2113        unsafe { Some(&mut *ptr) }
2114    }
2115
2116    async fn lock_write(
2117        &self,
2118        lock: &mut std::sync::Arc<tokio::sync::RwLock<T>>,
2119    ) -> Option<&'a mut T> {
2120        // SHALLOW CLONE: Only Arc refcount is incremented
2121        let mut guard = lock.write().await;
2122        let ptr = &mut *guard as *mut T;
2123        unsafe { Some(&mut *ptr) }
2124    }
2125}
2126
2127// ============================================================================
2128// Type aliases for derive macro (return concrete type to avoid lifetime issues)
2129// ============================================================================
2130//
2131// The keypath object is 'static—references are created when get() is called
2132// with a root, not when the keypath is constructed.
2133
2134#[cfg(feature = "tokio")]
2135/// Type alias for AsyncLockKp over std::sync::Arc<tokio::sync::Mutex<T>>. Use with derive macro's `_async()` methods.
2136pub type AsyncLockKpMutexFor<Root, Lock, Inner> = AsyncLockKp<
2137    Root,
2138    Lock,
2139    Inner,
2140    Inner,
2141    &'static Root,
2142    &'static Lock,
2143    &'static Inner,
2144    &'static Inner,
2145    &'static mut Root,
2146    &'static mut Lock,
2147    &'static mut Inner,
2148    &'static mut Inner,
2149    for<'b> fn(&'b Root) -> Option<&'b Lock>,
2150    for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
2151    TokioMutexAccess<Inner>,
2152    for<'b> fn(&'b Inner) -> Option<&'b Inner>,
2153    for<'b> fn(&'b mut Inner) -> Option<&'b mut Inner>,
2154>;
2155
2156#[cfg(feature = "tokio")]
2157/// Type alias for AsyncLockKp over std::sync::Arc<tokio::sync::RwLock<T>>. Use with derive macro's `_async()` methods.
2158pub type AsyncLockKpRwLockFor<Root, Lock, Inner> = AsyncLockKp<
2159    Root,
2160    Lock,
2161    Inner,
2162    Inner,
2163    &'static Root,
2164    &'static Lock,
2165    &'static Inner,
2166    &'static Inner,
2167    &'static mut Root,
2168    &'static mut Lock,
2169    &'static mut Inner,
2170    &'static mut Inner,
2171    for<'b> fn(&'b Root) -> Option<&'b Lock>,
2172    for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
2173    TokioRwLockAccess<Inner>,
2174    for<'b> fn(&'b Inner) -> Option<&'b Inner>,
2175    for<'b> fn(&'b mut Inner) -> Option<&'b mut Inner>,
2176>;
2177
2178// ============================================================================
2179// Tests
2180// ============================================================================
2181
2182#[cfg(all(test, feature = "tokio"))]
2183mod tests {
2184    use super::*;
2185    use crate::KpType;
2186
2187    #[tokio::test]
2188    async fn test_async_lock_kp_tokio_mutex_basic() {
2189        use tokio::sync::Mutex;
2190
2191        #[derive(Clone)]
2192        struct Root {
2193            data: std::sync::Arc<Mutex<String>>,
2194        }
2195
2196        let root = Root {
2197            data: std::sync::Arc::new(Mutex::new("hello".to_string())),
2198        };
2199
2200        // Create AsyncLockKp
2201        let lock_kp = {
2202            let prev: KpType<Root, std::sync::Arc<Mutex<String>>> =
2203                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
2204            let next: KpType<String, String> =
2205                Kp::new(|s: &String| Some(s), |s: &mut String| Some(s));
2206            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
2207        };
2208
2209        // Test async get
2210        let value = lock_kp.get(&root).await;
2211        assert!(value.is_some());
2212        assert_eq!(value.unwrap(), &"hello".to_string());
2213    }
2214
2215    #[tokio::test]
2216    async fn test_async_lock_kp_get_optional_or_else() {
2217        use tokio::sync::Mutex;
2218
2219        #[derive(Clone)]
2220        struct Root {
2221            data: std::sync::Arc<Mutex<i32>>,
2222        }
2223
2224        let mut root = Root {
2225            data: std::sync::Arc::new(Mutex::new(42)),
2226        };
2227
2228        let lock_kp = {
2229            let prev: KpType<Root, std::sync::Arc<Mutex<i32>>> =
2230                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
2231            let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
2232            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
2233        };
2234
2235        // get_optional
2236        assert!(lock_kp.get_optional(None).await.is_none());
2237        assert_eq!(lock_kp.get_optional(Some(&root)).await, Some(&42));
2238
2239        // get_mut_optional
2240        assert!(lock_kp.get_mut_optional(None).await.is_none());
2241        if let Some(m) = lock_kp.get_mut_optional(Some(&mut root)).await {
2242            *m = 99;
2243        }
2244        assert_eq!(lock_kp.get(&root).await, Some(&99));
2245
2246        // get_or_else
2247        assert_eq!(*lock_kp.get_or_else(None, || &0).await, 0);
2248        assert_eq!(*lock_kp.get_or_else(Some(&root), || &0).await, 99);
2249
2250        // get_mut_or_else
2251        let m = lock_kp
2252            .get_mut_or_else(Some(&mut root), || panic!("unexpected"))
2253            .await;
2254        *m = 100;
2255        assert_eq!(lock_kp.get(&root).await, Some(&100));
2256    }
2257
2258    #[tokio::test]
2259    async fn test_async_lock_kp_tokio_rwlock_basic() {
2260        use tokio::sync::RwLock;
2261
2262        #[derive(Clone)]
2263        struct Root {
2264            data: std::sync::Arc<RwLock<Vec<i32>>>,
2265        }
2266
2267        let root = Root {
2268            data: std::sync::Arc::new(RwLock::new(vec![1, 2, 3, 4, 5])),
2269        };
2270
2271        // Create AsyncLockKp with RwLock
2272        let lock_kp = {
2273            let prev: KpType<Root, std::sync::Arc<RwLock<Vec<i32>>>> =
2274                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
2275            let next: KpType<Vec<i32>, Vec<i32>> =
2276                Kp::new(|v: &Vec<i32>| Some(v), |v: &mut Vec<i32>| Some(v));
2277            AsyncLockKp::new(prev, TokioRwLockAccess::new(), next)
2278        };
2279
2280        // Test async get with RwLock (read lock)
2281        let value = lock_kp.get(&root).await;
2282        assert!(value.is_some());
2283        assert_eq!(value.unwrap().len(), 5);
2284    }
2285
2286    #[tokio::test]
2287    async fn test_async_lock_kp_concurrent_reads() {
2288        use tokio::sync::RwLock;
2289
2290        #[derive(Clone)]
2291        struct Root {
2292            data: std::sync::Arc<RwLock<i32>>,
2293        }
2294
2295        let root = Root {
2296            data: std::sync::Arc::new(RwLock::new(42)),
2297        };
2298
2299        // Create AsyncLockKp
2300        let lock_kp = {
2301            let prev: KpType<Root, std::sync::Arc<RwLock<i32>>> =
2302                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
2303            let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
2304            AsyncLockKp::new(prev, TokioRwLockAccess::new(), next)
2305        };
2306
2307        // Concurrent async reads in the same task (spawn would require 'static future;
2308        // get() returns references so we use join! instead)
2309        let lock_kp2 = {
2310            let prev: KpType<Root, std::sync::Arc<RwLock<i32>>> =
2311                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
2312            let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
2313            AsyncLockKp::new(prev, TokioRwLockAccess::new(), next)
2314        };
2315        let (a, b) = tokio::join!(lock_kp.get(&root), lock_kp2.get(&root));
2316        assert_eq!(a, Some(&42));
2317        assert_eq!(b, Some(&42));
2318
2319        // Test the original lock_kp as well
2320        let value = lock_kp.get(&root).await;
2321        assert_eq!(value, Some(&42));
2322    }
2323
2324    #[tokio::test]
2325    async fn test_async_lock_kp_panic_on_clone_proof() {
2326        use tokio::sync::Mutex;
2327
2328        /// This struct PANICS if cloned - proving no deep cloning occurs
2329        struct PanicOnClone {
2330            data: String,
2331        }
2332
2333        impl Clone for PanicOnClone {
2334            fn clone(&self) -> Self {
2335                panic!("❌ ASYNC DEEP CLONE DETECTED! PanicOnClone was cloned!");
2336            }
2337        }
2338
2339        #[derive(Clone)]
2340        struct Root {
2341            level1: std::sync::Arc<Mutex<Level1>>,
2342        }
2343
2344        struct Level1 {
2345            panic_data: PanicOnClone,
2346            value: i32,
2347        }
2348
2349        impl Clone for Level1 {
2350            fn clone(&self) -> Self {
2351                panic!("❌ Level1 was deeply cloned in async context!");
2352            }
2353        }
2354
2355        // Create structure with PanicOnClone
2356        let root = Root {
2357            level1: std::sync::Arc::new(Mutex::new(Level1 {
2358                panic_data: PanicOnClone {
2359                    data: "test".to_string(),
2360                },
2361                value: 123,
2362            })),
2363        };
2364
2365        // Create AsyncLockKp
2366        let lock_kp = {
2367            let prev: KpType<Root, std::sync::Arc<Mutex<Level1>>> = Kp::new(
2368                |r: &Root| Some(&r.level1),
2369                |r: &mut Root| Some(&mut r.level1),
2370            );
2371            let next: KpType<Level1, i32> = Kp::new(
2372                |l: &Level1| Some(&l.value),
2373                |l: &mut Level1| Some(&mut l.value),
2374            );
2375            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
2376        };
2377
2378        // CRITICAL TEST: If any deep cloning occurs, PanicOnClone will trigger
2379        let value = lock_kp.get(&root).await;
2380
2381        // ✅ SUCCESS: No panic means no deep cloning!
2382        assert_eq!(value, Some(&123));
2383    }
2384
2385    #[tokio::test]
2386    async fn test_async_lock_kp_structure() {
2387        use tokio::sync::Mutex;
2388
2389        #[derive(Clone)]
2390        struct Root {
2391            data: std::sync::Arc<Mutex<String>>,
2392        }
2393
2394        let lock_kp = {
2395            let prev: KpType<Root, std::sync::Arc<Mutex<String>>> =
2396                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
2397            let next: KpType<String, String> =
2398                Kp::new(|s: &String| Some(s), |s: &mut String| Some(s));
2399            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
2400        };
2401
2402        // Verify structure has three fields (prev, mid, next)
2403        let _ = &lock_kp.prev;
2404        let _ = &lock_kp.mid;
2405        let _ = &lock_kp.next;
2406    }
2407
2408    #[tokio::test]
2409    async fn test_async_kp_then() {
2410        use tokio::sync::Mutex;
2411
2412        #[derive(Clone)]
2413        struct Root {
2414            data: std::sync::Arc<Mutex<Inner>>,
2415        }
2416
2417        #[derive(Clone)]
2418        struct Inner {
2419            value: i32,
2420        }
2421
2422        let root = Root {
2423            data: std::sync::Arc::new(Mutex::new(Inner { value: 42 })),
2424        };
2425
2426        // Create AsyncLockKp to Inner
2427        let async_kp = {
2428            let prev: KpType<Root, std::sync::Arc<Mutex<Inner>>> =
2429                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
2430            let next: KpType<Inner, Inner> = Kp::new(|i: &Inner| Some(i), |i: &mut Inner| Some(i));
2431            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
2432        };
2433
2434        // Chain with regular Kp to get value field
2435        let value_kp: KpType<Inner, i32> = Kp::new(
2436            |i: &Inner| Some(&i.value),
2437            |i: &mut Inner| Some(&mut i.value),
2438        );
2439
2440        let chained = async_kp.then(value_kp);
2441        let result = chained.get(&root).await;
2442        assert_eq!(result, Some(&42));
2443    }
2444
2445    #[tokio::test]
2446    async fn test_async_kp_later_then() {
2447        use tokio::sync::Mutex;
2448
2449        #[derive(Clone)]
2450        struct Root {
2451            lock1: std::sync::Arc<Mutex<Container>>,
2452        }
2453
2454        #[derive(Clone)]
2455        struct Container {
2456            lock2: std::sync::Arc<Mutex<i32>>,
2457        }
2458
2459        let root = Root {
2460            lock1: std::sync::Arc::new(Mutex::new(Container {
2461                lock2: std::sync::Arc::new(Mutex::new(999)),
2462            })),
2463        };
2464
2465        // First AsyncLockKp: Root -> Container
2466        let async_kp1 = {
2467            let prev: KpType<Root, std::sync::Arc<Mutex<Container>>> =
2468                Kp::new(|r: &Root| Some(&r.lock1), |r: &mut Root| Some(&mut r.lock1));
2469            let next: KpType<Container, Container> =
2470                Kp::new(|c: &Container| Some(c), |c: &mut Container| Some(c));
2471            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
2472        };
2473
2474        // Second AsyncLockKp: Container -> i32
2475        let async_kp2 = {
2476            let prev: KpType<Container, std::sync::Arc<Mutex<i32>>> = Kp::new(
2477                |c: &Container| Some(&c.lock2),
2478                |c: &mut Container| Some(&mut c.lock2),
2479            );
2480            let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
2481            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
2482        };
2483
2484        // Chain with then_async; get with root
2485        let chained = async_kp1.then_async(async_kp2);
2486        let result = chained.get(&root).await;
2487        assert_eq!(result, Some(&999));
2488    }
2489
2490    #[tokio::test]
2491    async fn test_async_kp_then_async_three_levels() {
2492        use tokio::sync::Mutex;
2493
2494        #[derive(Clone)]
2495        struct Root {
2496            a: std::sync::Arc<Mutex<Level1>>,
2497        }
2498        #[derive(Clone)]
2499        struct Level1 {
2500            b: std::sync::Arc<Mutex<Level2>>,
2501        }
2502        #[derive(Clone)]
2503        struct Level2 {
2504            c: std::sync::Arc<Mutex<i32>>,
2505        }
2506
2507        let root = Root {
2508            a: std::sync::Arc::new(Mutex::new(Level1 {
2509                b: std::sync::Arc::new(Mutex::new(Level2 {
2510                    c: std::sync::Arc::new(Mutex::new(42)),
2511                })),
2512            })),
2513        };
2514
2515        let kp1 = {
2516            let prev: KpType<Root, std::sync::Arc<Mutex<Level1>>> =
2517                Kp::new(|r: &Root| Some(&r.a), |r: &mut Root| Some(&mut r.a));
2518            let next: KpType<Level1, Level1> =
2519                Kp::new(|l: &Level1| Some(l), |l: &mut Level1| Some(l));
2520            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
2521        };
2522        let kp2 = {
2523            let prev: KpType<Level1, std::sync::Arc<Mutex<Level2>>> =
2524                Kp::new(|l: &Level1| Some(&l.b), |l: &mut Level1| Some(&mut l.b));
2525            let next: KpType<Level2, Level2> =
2526                Kp::new(|l: &Level2| Some(l), |l: &mut Level2| Some(l));
2527            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
2528        };
2529        let kp3 = {
2530            let prev: KpType<Level2, std::sync::Arc<Mutex<i32>>> =
2531                Kp::new(|l: &Level2| Some(&l.c), |l: &mut Level2| Some(&mut l.c));
2532            let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
2533            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
2534        };
2535
2536        let chained = kp1.then_async(kp2).then_async(kp3);
2537        let result = chained.get(&root).await;
2538        assert_eq!(result, Some(&42));
2539    }
2540}