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