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