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//!
11//! Example: `root_lock.then_lock(parking_kp).then_async(async_kp).then_lock(std_lock_kp)`
12//!
13//! # SHALLOW CLONING GUARANTEE
14//!
15//! **IMPORTANT**: All cloning operations in this module are SHALLOW (reference-counted) clones:
16//!
17//! 1. **`AsyncLockKp` derives `Clone`**: Clones function pointers and PhantomData only
18//!    - `prev` and `next` fields contain function pointers (cheap to copy)
19//!    - `mid` field is typically just `PhantomData<T>` (zero-sized, zero-cost)
20//!    - No heap allocations or deep data copies
21//!
22//! 2. **`Lock: Clone` bound** (e.g., `Arc<tokio::sync::Mutex<T>>`):
23//!    - For `Arc<T>`: Only increments the atomic reference count (one atomic operation)
24//!    - The actual data `T` inside is **NEVER** cloned
25//!    - This is the whole point of Arc - shared ownership without copying data
26//!
27//! 3. **`L: Clone` bound** (e.g., `TokioMutexAccess<T>`):
28//!    - Only clones `PhantomData<T>` which is zero-sized
29//!    - Compiled away completely - zero runtime cost
30
31use crate::Kp;
32use async_trait::async_trait;
33use std::sync::Arc;
34
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//   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    fn sync_get(&self, root: Root) -> Option<Value>;
69    fn sync_get_mut(&self, root: MutRoot) -> Option<MutValue>;
70}
71
72impl<R, V, Root, Value, MutRoot, MutValue, G, S> SyncKeyPathLike<Root, Value, MutRoot, MutValue>
73    for crate::Kp<R, V, Root, Value, MutRoot, MutValue, G, S>
74where
75    Root: std::borrow::Borrow<R>,
76    Value: std::borrow::Borrow<V>,
77    MutRoot: std::borrow::BorrowMut<R>,
78    MutValue: std::borrow::BorrowMut<V>,
79    G: Fn(Root) -> Option<Value>,
80    S: Fn(MutRoot) -> Option<MutValue>,
81{
82    fn sync_get(&self, root: Root) -> Option<Value> {
83        self.get(root)
84    }
85    fn sync_get_mut(&self, root: MutRoot) -> Option<MutValue> {
86        self.get_mut(root)
87    }
88}
89
90impl<
91        R,
92        Lock,
93        Mid,
94        V,
95        Root,
96        LockValue,
97        MidValue,
98        Value,
99        MutRoot,
100        MutLock,
101        MutMid,
102        MutValue,
103        G1,
104        S1,
105        L,
106        G2,
107        S2,
108    >
109    SyncKeyPathLike<Root, Value, MutRoot, MutValue> for crate::lock::LockKp<
110        R,
111        Lock,
112        Mid,
113        V,
114        Root,
115        LockValue,
116        MidValue,
117        Value,
118        MutRoot,
119        MutLock,
120        MutMid,
121        MutValue,
122        G1,
123        S1,
124        L,
125        G2,
126        S2,
127    >
128where
129    Root: std::borrow::Borrow<R>,
130    LockValue: std::borrow::Borrow<Lock>,
131    MidValue: std::borrow::Borrow<Mid>,
132    Value: std::borrow::Borrow<V>,
133    MutRoot: std::borrow::BorrowMut<R>,
134    MutLock: std::borrow::BorrowMut<Lock>,
135    MutMid: std::borrow::BorrowMut<Mid>,
136    MutValue: std::borrow::BorrowMut<V>,
137    G1: Fn(Root) -> Option<LockValue>,
138    S1: Fn(MutRoot) -> Option<MutLock>,
139    L: crate::lock::LockAccess<Lock, MidValue> + crate::lock::LockAccess<Lock, MutMid>,
140    G2: Fn(MidValue) -> Option<Value>,
141    S2: Fn(MutMid) -> Option<MutValue>,
142    V: Clone,
143{
144    #[inline]
145    fn sync_get(&self, root: Root) -> Option<Value> {
146        self.get(root)
147    }
148    #[inline]
149    fn sync_get_mut(&self, root: MutRoot) -> Option<MutValue> {
150        self.get_mut(root)
151    }
152}
153
154/// Trait for async keypaths (both [AsyncLockKp] and [ComposedAsyncLockKp]) so composition can be any depth.
155///
156/// # Why MutRoot? (RwLock/Mutex interior mutability)
157///
158/// RwLock and Mutex provide **interior mutability**—their `lock()` / `write()` methods take `&self`,
159/// so you can mutate through an immutable reference. For **async lock keypaths**, the mutation
160/// happens inside the lock; you do *not* need a mutable root. `MutRoot` exists for composition
161/// with sync keypaths (e.g. [Kp]) that may require `&mut` along the path. When the path goes
162/// entirely through locks (RwLock/Mutex), `Root` and `MutRoot` are typically the same type
163/// (e.g. `&Root` for both).
164#[async_trait(?Send)]
165pub trait AsyncKeyPathLike<Root, MutRoot> {
166    /// Value type at the end of the keypath.
167    type Value;
168    /// Mutable value type at the end of the keypath.
169    type MutValue;
170    /// Get the value at the end of the keypath.
171    async fn get(&self, root: Root) -> Option<Self::Value>;
172    /// Get mutable access to the value at the end of the keypath.
173    async fn get_mut(&self, root: MutRoot) -> Option<Self::MutValue>;
174}
175
176/// An async keypath that handles async locked values (e.g., Arc<tokio::sync::Mutex<T>>)
177///
178/// Structure:
179/// - `prev`: Keypath from Root to Lock container (e.g., Arc<tokio::sync::Mutex<Mid>>)
180/// - `mid`: Async lock access handler that goes from Lock to Inner value
181/// - `next`: Keypath from Inner value to final Value
182///
183/// # Type Parameters
184/// - `R`: Root type (base)
185/// - `Lock`: Lock container type (e.g., Arc<tokio::sync::Mutex<Mid>>)
186/// - `Mid`: The type inside the lock
187/// - `V`: Final value type
188/// - Rest are the same generic parameters as Kp
189///
190/// # Cloning Behavior
191///
192/// **IMPORTANT**: All `Clone` operations in this struct are SHALLOW clones:
193///
194/// - `AsyncLockKp` itself derives `Clone` - this clones the three field references/closures
195/// - `prev` and `next` fields are `Kp` structs containing function pointers (cheap to clone)
196/// - `mid` field implements `AsyncLockLike` trait - typically just `PhantomData` (zero-cost clone)
197/// - When `Lock: Clone` (e.g., `Arc<tokio::sync::Mutex<T>>`), cloning is just incrementing reference count
198/// - NO deep data cloning occurs - all clones are pointer/reference increments
199#[derive(Clone)] // SHALLOW: Clones function pointers and PhantomData only
200pub struct AsyncLockKp<
201    R,
202    Lock,
203    Mid,
204    V,
205    Root,
206    LockValue,
207    MidValue,
208    Value,
209    MutRoot,
210    MutLock,
211    MutMid,
212    MutValue,
213    G1,
214    S1,
215    L,
216    G2,
217    S2,
218> where
219    Root: std::borrow::Borrow<R>,
220    LockValue: std::borrow::Borrow<Lock>,
221    MidValue: std::borrow::Borrow<Mid>,
222    Value: std::borrow::Borrow<V>,
223    MutRoot: std::borrow::BorrowMut<R>,
224    MutLock: std::borrow::BorrowMut<Lock>,
225    MutMid: std::borrow::BorrowMut<Mid>,
226    MutValue: std::borrow::BorrowMut<V>,
227    G1: Fn(Root) -> Option<LockValue> + Clone,
228    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
229    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
230    G2: Fn(MidValue) -> Option<Value> + Clone,
231    S2: Fn(MutMid) -> Option<MutValue> + Clone,
232{
233    /// Keypath from Root to Lock container
234    pub prev: Kp<R, Lock, Root, LockValue, MutRoot, MutLock, G1, S1>,
235
236    /// Async lock access handler (converts Lock -> Inner)
237    pub mid: L,
238
239    /// Keypath from Inner to final Value
240    pub next: Kp<Mid, V, MidValue, Value, MutMid, MutValue, G2, S2>,
241}
242
243impl<
244    R,
245    Lock,
246    Mid,
247    V,
248    Root,
249    LockValue,
250    MidValue,
251    Value,
252    MutRoot,
253    MutLock,
254    MutMid,
255    MutValue,
256    G1,
257    S1,
258    L,
259    G2,
260    S2,
261>
262    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    >
281where
282    Root: std::borrow::Borrow<R>,
283    LockValue: std::borrow::Borrow<Lock>,
284    MidValue: std::borrow::Borrow<Mid>,
285    Value: std::borrow::Borrow<V>,
286    MutRoot: std::borrow::BorrowMut<R>,
287    MutLock: std::borrow::BorrowMut<Lock>,
288    MutMid: std::borrow::BorrowMut<Mid>,
289    MutValue: std::borrow::BorrowMut<V>,
290    G1: Fn(Root) -> Option<LockValue> + Clone,
291    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
292    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
293    G2: Fn(MidValue) -> Option<Value> + Clone,
294    S2: Fn(MutMid) -> Option<MutValue> + Clone,
295{
296    /// Create a new AsyncLockKp with prev, mid, and next components
297    pub fn new(
298        prev: Kp<R, Lock, Root, LockValue, MutRoot, MutLock, G1, S1>,
299        mid: L,
300        next: Kp<Mid, V, MidValue, Value, MutMid, MutValue, G2, S2>,
301    ) -> Self {
302        Self { prev, mid, next }
303    }
304
305    /// Get the value through the lock
306    ///
307    /// This will:
308    /// 1. Use `prev` to get to the Lock
309    /// 2. Use `mid` to asynchronously lock and get the Inner value
310    /// 3. Use `next` to get to the final Value
311    ///
312    /// # SHALLOW CLONING NOTE
313    ///
314    /// When `lock` is cloned (e.g., `Arc<tokio::sync::Mutex<T>>`):
315    /// - Only the Arc reference count is incremented (one atomic operation)
316    /// - The actual data `T` inside the Mutex is **NEVER** cloned
317    /// - This is safe and efficient - the whole point of Arc
318    #[inline]
319    pub async fn get(&self, root: Root) -> Option<Value>
320    where
321        Lock: Clone,
322    {
323        // SHALLOW CLONE: For Arc<Mutex<T>>, only increments Arc refcount
324        // The actual data T is NOT cloned
325        let lock_value = (self.prev.get)(root)?;
326        let lock: &Lock = lock_value.borrow();
327        let lock_clone = lock.clone(); // SHALLOW: Arc refcount++
328
329        // Async lock and get the mid value
330        let mid_value = self.mid.lock_read(&lock_clone).await?;
331
332        // Navigate from mid to final value
333        (self.next.get)(mid_value)
334    }
335
336    /// Get mutable access to the value through the lock
337    #[inline]
338    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue>
339    where
340        Lock: Clone,
341    {
342        // SHALLOW CLONE: For Arc<Mutex<T>>, only increments Arc refcount
343        let mut lock_value = (self.prev.set)(root)?;
344        let lock: &mut Lock = lock_value.borrow_mut();
345        let mut lock_clone = lock.clone(); // SHALLOW: Arc refcount++
346
347        // Async lock and get the mid value
348        let mid_value = self.mid.lock_write(&mut lock_clone).await?;
349
350        // Navigate from mid to final value
351        (self.next.set)(mid_value)
352    }
353
354    /// Set the value through the lock using an updater function.
355    ///
356    /// Uses interior mutability—no mutable root required. RwLock/Mutex allow mutation through
357    /// `&self` (lock().write() etc.), so `root` can be `&Root`.
358    ///
359    /// Internally uses: `prev.get` → `mid.lock_read`/`lock_write` → `next.set` (the setter path).
360    pub async fn set<F>(&self, root: Root, updater: F) -> Result<(), String>
361    where
362        Lock: Clone,
363        F: FnOnce(&mut V),
364    {
365        // SHALLOW CLONE: For Arc<Mutex<T>>, only increments Arc refcount
366        let lock_value = (self.prev.get)(root).ok_or("Failed to get lock from root")?;
367        let lock: &Lock = lock_value.borrow();
368        let lock_clone = lock.clone(); // SHALLOW: Arc refcount++
369
370        // Async lock and get the mid value
371        let mut mid_value = self
372            .mid
373            .lock_read(&lock_clone)
374            .await
375            .ok_or("Failed to lock")?;
376
377        // Get the final value
378        let mut mut_value = (self.next.set)(mid_value).ok_or("Failed to navigate to value")?;
379        let v: &mut V = mut_value.borrow_mut();
380
381        // Apply the updater
382        updater(v);
383
384        Ok(())
385    }
386
387    // ========================================================================
388    // Interoperability: then (Kp), then_lock (sync LockKp), then_async (async keypath)
389    // ========================================================================
390
391    /// Chain this AsyncLockKp with a regular [crate::Kp] (no root at call site).
392    /// Returns an AsyncLockKp that goes one step further; use [AsyncLockKp::get] or [AsyncLockKp::get_mut] with root later.
393    ///
394    /// # Example
395    /// ```
396    /// // Root -> Arc<tokio::Mutex<Inner>> -> Inner -> field
397    /// let async_kp = AsyncLockKp::new(root_to_lock, TokioMutexAccess::new(), lock_to_inner);
398    /// let field_kp = Kp::new(|inner: &Inner| Some(&inner.field), |inner: &mut Inner| Some(&mut inner.field));
399    /// let chained = async_kp.then(field_kp);
400    /// let result = chained.get(&root).await;
401    /// ```
402    pub fn then<V2, Value2, MutValue2, G3, S3>(
403        self,
404        next_kp: crate::Kp<V, V2, Value, Value2, MutValue, MutValue2, G3, S3>,
405    ) -> AsyncLockKp<
406        R,
407        Lock,
408        Mid,
409        V2,
410        Root,
411        LockValue,
412        MidValue,
413        Value2,
414        MutRoot,
415        MutLock,
416        MutMid,
417        MutValue2,
418        G1,
419        S1,
420        L,
421        impl Fn(MidValue) -> Option<Value2> + Clone,
422        impl Fn(MutMid) -> Option<MutValue2> + Clone,
423    >
424    where
425        V: 'static,
426        V2: 'static,
427        Value: std::borrow::Borrow<V>,
428        Value2: std::borrow::Borrow<V2>,
429        MutValue: std::borrow::BorrowMut<V>,
430        MutValue2: std::borrow::BorrowMut<V2>,
431        G3: Fn(Value) -> Option<Value2> + Clone,
432        S3: Fn(MutValue) -> Option<MutValue2> + Clone,
433    {
434        let next_get = self.next.get;
435        let next_set = self.next.set;
436        let chained_kp = crate::Kp::new(
437            move |mid_value: MidValue| next_get(mid_value).and_then(|v| (next_kp.get)(v)),
438            move |mid_value: MutMid| next_set(mid_value).and_then(|v| (next_kp.set)(v)),
439        );
440        AsyncLockKp::new(self.prev, self.mid, chained_kp)
441    }
442
443    /// Chain this AsyncLockKp with a sync [crate::lock::LockKp] (no root at call site).
444    /// Returns a keypath that first goes through the async lock, then through the sync lock; use `.get(&root).await` later.
445    pub fn then_lock<
446        Lock2,
447        Mid2,
448        V2,
449        LockValue2,
450        MidValue2,
451        Value2,
452        MutLock2,
453        MutMid2,
454        MutValue2,
455        G2_1,
456        S2_1,
457        L2,
458        G2_2,
459        S2_2,
460    >(
461        self,
462        lock_kp: crate::lock::LockKp<
463            V,
464            Lock2,
465            Mid2,
466            V2,
467            Value,
468            LockValue2,
469            MidValue2,
470            Value2,
471            MutValue,
472            MutLock2,
473            MutMid2,
474            MutValue2,
475            G2_1,
476            S2_1,
477            L2,
478            G2_2,
479            S2_2,
480        >,
481    ) -> AsyncLockKpThenLockKp<
482        R,
483        V2,
484        Root,
485        Value2,
486        MutRoot,
487        MutValue2,
488        Self,
489        crate::lock::LockKp<
490            V,
491            Lock2,
492            Mid2,
493            V2,
494            Value,
495            LockValue2,
496            MidValue2,
497            Value2,
498            MutValue,
499            MutLock2,
500            MutMid2,
501            MutValue2,
502            G2_1,
503            S2_1,
504            L2,
505            G2_2,
506            S2_2,
507        >,
508    >
509    where
510        V: 'static,
511        V2: 'static,
512        Value: std::borrow::Borrow<V>,
513        Value2: std::borrow::Borrow<V2>,
514        MutValue: std::borrow::BorrowMut<V>,
515        MutValue2: std::borrow::BorrowMut<V2>,
516        LockValue2: std::borrow::Borrow<Lock2>,
517        MidValue2: std::borrow::Borrow<Mid2>,
518        MutLock2: std::borrow::BorrowMut<Lock2>,
519        MutMid2: std::borrow::BorrowMut<Mid2>,
520        G2_1: Fn(Value) -> Option<LockValue2>,
521        S2_1: Fn(MutValue) -> Option<MutLock2>,
522        L2: crate::lock::LockAccess<Lock2, MidValue2> + crate::lock::LockAccess<Lock2, MutMid2>,
523        G2_2: Fn(MidValue2) -> Option<Value2>,
524        S2_2: Fn(MutMid2) -> Option<MutValue2>,
525    {
526        AsyncLockKpThenLockKp {
527            first: self,
528            second: lock_kp,
529            _p: std::marker::PhantomData,
530        }
531    }
532
533    /// Chain with another async keypath (like [crate::lock::LockKp::then_lock] for sync locks).
534    ///
535    /// Chain with another async keypath (e.g. tokio RwLock). Use [ComposedAsyncLockKp::get] or
536    /// [ComposedAsyncLockKp::get_mut] with root later.
537    ///
538    /// Root -> AsyncLock1 -> Container -> AsyncLock2 -> Value
539    ///
540    /// # Example
541    /// ```
542    /// // Root -> Arc<tokio::Mutex<Container>> -> Container -> Arc<tokio::Mutex<Value>> -> Value
543    /// let async_kp1 = AsyncLockKp::new(...); // Root -> Container
544    /// let async_kp2 = AsyncLockKp::new(...); // Container -> Value
545    /// let chained = async_kp1.then_async(async_kp2);
546    /// let result = chained.get(&root).await;
547    /// ```
548    pub fn then_async<
549        Lock2,
550        Mid2,
551        V2,
552        LockValue2,
553        MidValue2,
554        Value2,
555        MutLock2,
556        MutMid2,
557        MutValue2,
558        G2_1,
559        S2_1,
560        L2,
561        G2_2,
562        S2_2,
563    >(
564        self,
565        other: AsyncLockKp<
566            V,
567            Lock2,
568            Mid2,
569            V2,
570            Value,
571            LockValue2,
572            MidValue2,
573            Value2,
574            MutValue,
575            MutLock2,
576            MutMid2,
577            MutValue2,
578            G2_1,
579            S2_1,
580            L2,
581            G2_2,
582            S2_2,
583        >,
584    ) -> ComposedAsyncLockKp<
585        R,
586        V2,
587        Root,
588        Value2,
589        MutRoot,
590        MutValue2,
591        Self,
592        AsyncLockKp<
593            V,
594            Lock2,
595            Mid2,
596            V2,
597            Value,
598            LockValue2,
599            MidValue2,
600            Value2,
601            MutValue,
602            MutLock2,
603            MutMid2,
604            MutValue2,
605            G2_1,
606            S2_1,
607            L2,
608            G2_2,
609            S2_2,
610        >,
611    >
612    where
613        Lock: Clone,
614        Lock2: Clone,
615        V: 'static,
616        V2: 'static,
617        Value: std::borrow::Borrow<V>,
618        LockValue2: std::borrow::Borrow<Lock2>,
619        MidValue2: std::borrow::Borrow<Mid2>,
620        Value2: std::borrow::Borrow<V2>,
621        MutValue: std::borrow::BorrowMut<V>,
622        MutLock2: std::borrow::BorrowMut<Lock2>,
623        MutMid2: std::borrow::BorrowMut<Mid2>,
624        MutValue2: std::borrow::BorrowMut<V2>,
625        G2_1: Fn(Value) -> Option<LockValue2> + Clone,
626        S2_1: Fn(MutValue) -> Option<MutLock2> + Clone,
627        L2: AsyncLockLike<Lock2, MidValue2> + AsyncLockLike<Lock2, MutMid2> + Clone,
628        G2_2: Fn(MidValue2) -> Option<Value2> + Clone,
629        S2_2: Fn(MutMid2) -> Option<MutValue2> + Clone,
630    {
631        ComposedAsyncLockKp {
632            first: self,
633            second: other,
634            _p: std::marker::PhantomData,
635        }
636    }
637}
638
639// Implement AsyncKeyPathLike for AsyncLockKp so it can be used in composition at any depth.
640#[async_trait(?Send)]
641impl<
642    R,
643    Lock,
644    Mid,
645    V,
646    Root,
647    LockValue,
648    MidValue,
649    Value,
650    MutRoot,
651    MutLock,
652    MutMid,
653    MutValue,
654    G1,
655    S1,
656    L,
657    G2,
658    S2,
659> AsyncKeyPathLike<Root, MutRoot>
660    for AsyncLockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>
661where
662    Root: std::borrow::Borrow<R>,
663    LockValue: std::borrow::Borrow<Lock>,
664    MidValue: std::borrow::Borrow<Mid>,
665    Value: std::borrow::Borrow<V>,
666    MutRoot: std::borrow::BorrowMut<R>,
667    MutLock: std::borrow::BorrowMut<Lock>,
668    MutMid: std::borrow::BorrowMut<Mid>,
669    MutValue: std::borrow::BorrowMut<V>,
670    G1: Fn(Root) -> Option<LockValue> + Clone,
671    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
672    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
673    G2: Fn(MidValue) -> Option<Value> + Clone,
674    S2: Fn(MutMid) -> Option<MutValue> + Clone,
675    Lock: Clone,
676{
677    type Value = Value;
678    type MutValue = MutValue;
679    async fn get(&self, root: Root) -> Option<Value> {
680        AsyncLockKp::get(self, root).await
681    }
682    async fn get_mut(&self, root: MutRoot) -> Option<MutValue> {
683        AsyncLockKp::get_mut(self, root).await
684    }
685}
686
687/// Chained async lock keypath: two or more async keypaths (Root -> V -> V2 -> ...). Root is passed at get/get_mut time.
688///
689/// Use [AsyncLockKp::then_async] to create (or [ComposedAsyncLockKp::then_async] for more levels). Then call [ComposedAsyncLockKp::get] or
690/// [ComposedAsyncLockKp::get_mut] with root when you need the value.
691///
692/// Chain any depth: `kp1.then_async(kp2).then_async(kp3).then_async(kp4)...` then `.get(&root).await`.
693#[derive(Clone)]
694pub struct ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> {
695    pub(crate) first: First,
696    pub(crate) second: Second,
697    _p: std::marker::PhantomData<(R, V2, Root, Value2, MutRoot, MutValue2)>,
698}
699
700impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
701    ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
702where
703    First: AsyncKeyPathLike<Root, MutRoot>,
704    Second: AsyncKeyPathLike<First::Value, First::MutValue, Value = Value2, MutValue = MutValue2>,
705{
706    /// Get through all chained async locks (root is passed here).
707    pub async fn get(&self, root: Root) -> Option<Value2> {
708        let value = self.first.get(root).await?;
709        self.second.get(value).await
710    }
711
712    /// Get mutable through all composed locks (root is passed here).
713    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
714        let mut_value = self.first.get_mut(root).await?;
715        self.second.get_mut(mut_value).await
716    }
717
718    /// Chain with another async keypath: `a.then_async(b).then_async(c).get(&root).await`.
719    pub fn then_async<
720        Lock3,
721        Mid3,
722        V3,
723        LockValue3,
724        MidValue3,
725        Value3,
726        MutLock3,
727        MutMid3,
728        MutValue3,
729        G3_1,
730        S3_1,
731        L3,
732        G3_2,
733        S3_2,
734    >(
735        self,
736        other: AsyncLockKp<
737            V2,
738            Lock3,
739            Mid3,
740            V3,
741            Value2,
742            LockValue3,
743            MidValue3,
744            Value3,
745            MutValue2,
746            MutLock3,
747            MutMid3,
748            MutValue3,
749            G3_1,
750            S3_1,
751            L3,
752            G3_2,
753            S3_2,
754        >,
755    ) -> ComposedAsyncLockKp<
756        R,
757        V3,
758        Root,
759        Value3,
760        MutRoot,
761        MutValue3,
762        Self,
763        AsyncLockKp<
764            V2,
765            Lock3,
766            Mid3,
767            V3,
768            Value2,
769            LockValue3,
770            MidValue3,
771            Value3,
772            MutValue2,
773            MutLock3,
774            MutMid3,
775            MutValue3,
776            G3_1,
777            S3_1,
778            L3,
779            G3_2,
780            S3_2,
781        >,
782    >
783    where
784        V2: 'static,
785        V3: 'static,
786        Value2: std::borrow::Borrow<V2>,
787        Value3: std::borrow::Borrow<V3>,
788        MutValue2: std::borrow::BorrowMut<V2>,
789        MutValue3: std::borrow::BorrowMut<V3>,
790        LockValue3: std::borrow::Borrow<Lock3>,
791        MidValue3: std::borrow::Borrow<Mid3>,
792        MutLock3: std::borrow::BorrowMut<Lock3>,
793        MutMid3: std::borrow::BorrowMut<Mid3>,
794        G3_1: Fn(Value2) -> Option<LockValue3> + Clone,
795        S3_1: Fn(MutValue2) -> Option<MutLock3> + Clone,
796        L3: AsyncLockLike<Lock3, MidValue3> + AsyncLockLike<Lock3, MutMid3> + Clone,
797        G3_2: Fn(MidValue3) -> Option<Value3> + Clone,
798        S3_2: Fn(MutMid3) -> Option<MutValue3> + Clone,
799        Lock3: Clone,
800    {
801        ComposedAsyncLockKp {
802            first: self,
803            second: other,
804            _p: std::marker::PhantomData,
805        }
806    }
807
808    /// Chain with a regular [crate::Kp] (no root at call site). Use `.get(&root).await` later.
809    pub fn then<V3, Value3, MutValue3, G3, S3>(
810        self,
811        next_kp: crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
812    ) -> AsyncKeyPathThenKp<R, V3, Root, Value3, MutRoot, MutValue3, Self, crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>>
813    where
814        V2: 'static,
815        V3: 'static,
816        Value2: std::borrow::Borrow<V2>,
817        Value3: std::borrow::Borrow<V3>,
818        MutValue2: std::borrow::BorrowMut<V2>,
819        MutValue3: std::borrow::BorrowMut<V3>,
820        G3: Fn(Value2) -> Option<Value3> + Clone,
821        S3: Fn(MutValue2) -> Option<MutValue3> + Clone,
822    {
823        AsyncKeyPathThenKp {
824            first: self,
825            second: next_kp,
826            _p: std::marker::PhantomData,
827        }
828    }
829
830    /// Chain with a sync [crate::lock::LockKp] (no root at call site). Use `.get(&root).await` later.
831    pub fn then_lock<
832        Lock3,
833        Mid3,
834        V3,
835        LockValue3,
836        MidValue3,
837        Value3,
838        MutLock3,
839        MutMid3,
840        MutValue3,
841        G3_1,
842        S3_1,
843        L3,
844        G3_2,
845        S3_2,
846    >(
847        self,
848        lock_kp: crate::lock::LockKp<V2, Lock3, Mid3, V3, Value2, LockValue3, MidValue3, Value3, MutValue2, MutLock3, MutMid3, MutValue3, G3_1, S3_1, L3, G3_2, S3_2>,
849    ) -> AsyncLockKpThenLockKp<R, V3, Root, Value3, MutRoot, MutValue3, Self, crate::lock::LockKp<V2, Lock3, Mid3, V3, Value2, LockValue3, MidValue3, Value3, MutValue2, MutLock3, MutMid3, MutValue3, G3_1, S3_1, L3, G3_2, S3_2>>
850    where
851        V2: 'static,
852        V3: 'static,
853        Value2: std::borrow::Borrow<V2>,
854        Value3: std::borrow::Borrow<V3>,
855        MutValue2: std::borrow::BorrowMut<V2>,
856        MutValue3: std::borrow::BorrowMut<V3>,
857        LockValue3: std::borrow::Borrow<Lock3>,
858        MidValue3: std::borrow::Borrow<Mid3>,
859        MutLock3: std::borrow::BorrowMut<Lock3>,
860        MutMid3: std::borrow::BorrowMut<Mid3>,
861        G3_1: Fn(Value2) -> Option<LockValue3>,
862        S3_1: Fn(MutValue2) -> Option<MutLock3>,
863        L3: crate::lock::LockAccess<Lock3, MidValue3> + crate::lock::LockAccess<Lock3, MutMid3>,
864        G3_2: Fn(MidValue3) -> Option<Value3>,
865        S3_2: Fn(MutMid3) -> Option<MutValue3>,
866    {
867        AsyncLockKpThenLockKp {
868            first: self,
869            second: lock_kp,
870            _p: std::marker::PhantomData,
871        }
872    }
873}
874
875/// Keypath that chains a sync keypath ([crate::Kp]) with an [AsyncKeyPathLike]. Use [crate::Kp::then_async] to create; then `.get(&root).await`.
876#[derive(Clone)]
877pub struct KpThenAsyncKeyPath<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second> {
878    pub(crate) first: First,
879    pub(crate) second: Second,
880    pub(crate) _p: std::marker::PhantomData<(R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2)>,
881}
882
883impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
884    KpThenAsyncKeyPath<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
885where
886    First: SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
887    Second: AsyncKeyPathLike<Value, MutValue, Value = Value2, MutValue = MutValue2>,
888{
889    /// Get through sync keypath then async keypath (root is passed here).
890    #[inline]
891    pub async fn get(&self, root: Root) -> Option<Value2> {
892        let v = self.first.sync_get(root)?;
893        self.second.get(v).await
894    }
895    /// Get mutable through sync then async (root is passed here).
896    #[inline]
897    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
898        let mut_v = self.first.sync_get_mut(root)?;
899        self.second.get_mut(mut_v).await
900    }
901}
902
903#[async_trait(?Send)]
904impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
905    AsyncKeyPathLike<Root, MutRoot> for KpThenAsyncKeyPath<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
906where
907    First: SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
908    Second: AsyncKeyPathLike<Value, MutValue, Value = Value2, MutValue = MutValue2>,
909{
910    type Value = Value2;
911    type MutValue = MutValue2;
912    async fn get(&self, root: Root) -> Option<Value2> {
913        let v = self.first.sync_get(root)?;
914        self.second.get(v).await
915    }
916    async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
917        let mut_v = self.first.sync_get_mut(root)?;
918        self.second.get_mut(mut_v).await
919    }
920}
921
922impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
923    KpThenAsyncKeyPath<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
924where
925    First: SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
926    Second: AsyncKeyPathLike<Value, MutValue, Value = Value2, MutValue = MutValue2>,
927{
928    /// Chain with a [crate::Kp]. Use `.get(&root).await` later.
929    pub fn then<V3, Value3, MutValue3, G3, S3>(
930        self,
931        next_kp: crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
932    ) -> AsyncKeyPathThenKp<R, V3, Root, Value3, MutRoot, MutValue3, Self, crate::Kp<V2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>>
933    where
934        V3: 'static,
935        Value2: std::borrow::Borrow<V2>,
936        MutValue2: std::borrow::BorrowMut<V2>,
937        Value3: std::borrow::Borrow<V3>,
938        MutValue3: std::borrow::BorrowMut<V3>,
939        G3: Fn(Value2) -> Option<Value3> + Clone,
940        S3: Fn(MutValue2) -> Option<MutValue3> + Clone,
941    {
942        AsyncKeyPathThenKp {
943            first: self,
944            second: next_kp,
945            _p: std::marker::PhantomData,
946        }
947    }
948}
949
950/// Keypath that chains an [AsyncKeyPathLike] (async get) with a [crate::Kp] (sync step). Use `.get(&root).await` to run.
951#[derive(Clone)]
952pub struct AsyncKeyPathThenKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> {
953    pub(crate) first: First,
954    pub(crate) second: Second,
955    _p: std::marker::PhantomData<(R, V2, Root, Value2, MutRoot, MutValue2)>,
956}
957
958/// Impl when Second is a Kp whose input type is First::Value (covers both Kp<First::Value, V2, ...> and Kp<RKp, V2, First::Value, ...>).
959impl<R, V2, Root, Value2, MutRoot, MutValue2, First, RKp, G, S>
960    AsyncKeyPathThenKp<R, V2, Root, Value2, MutRoot, MutValue2, First, crate::Kp<RKp, V2, First::Value, Value2, First::MutValue, MutValue2, G, S>>
961where
962    First: AsyncKeyPathLike<Root, MutRoot>,
963    First::Value: std::borrow::Borrow<RKp>,
964    First::MutValue: std::borrow::BorrowMut<RKp>,
965    Value2: std::borrow::Borrow<V2>,
966    MutValue2: std::borrow::BorrowMut<V2>,
967    G: Fn(First::Value) -> Option<Value2>,
968    S: Fn(First::MutValue) -> Option<MutValue2>,
969{
970    /// Get through async keypath then Kp (root is passed here).
971    #[inline]
972    pub async fn get(&self, root: Root) -> Option<Value2> {
973        let value = self.first.get(root).await?;
974        (self.second.get)(value)
975    }
976    /// Get mutable through async keypath then Kp (root is passed here).
977    #[inline]
978    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
979        let mut_value = self.first.get_mut(root).await?;
980        (self.second.set)(mut_value)
981    }
982}
983
984#[async_trait(?Send)]
985impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
986    AsyncKeyPathLike<Root, MutRoot> for ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
987where
988    First: AsyncKeyPathLike<Root, MutRoot>,
989    Second: AsyncKeyPathLike<First::Value, First::MutValue, Value = Value2, MutValue = MutValue2>,
990{
991    type Value = Value2;
992    type MutValue = MutValue2;
993    async fn get(&self, root: Root) -> Option<Value2> {
994        ComposedAsyncLockKp::get(self, root).await
995    }
996    async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
997        ComposedAsyncLockKp::get_mut(self, root).await
998    }
999}
1000
1001// =============================================================================
1002// AsyncLockKpThenLockKp: AsyncLockKp .then_lock(LockKp) — async then sync lock
1003// =============================================================================
1004
1005/// Keypath that goes through an async lock then a sync [crate::lock::LockKp].
1006/// Use [AsyncLockKp::then_lock] to create; then call [AsyncLockKpThenLockKp::get] or [AsyncLockKpThenLockKp::get_mut] with root.
1007#[derive(Clone)]
1008pub struct AsyncLockKpThenLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> {
1009    pub(crate) first: First,
1010    pub(crate) second: Second,
1011    _p: std::marker::PhantomData<(R, V2, Root, Value2, MutRoot, MutValue2)>,
1012}
1013
1014impl<
1015        R,
1016        V2,
1017        Root,
1018        Value2,
1019        MutRoot,
1020        MutValue2,
1021        Lock,
1022        Mid,
1023        V,
1024        LockValue,
1025        MidValue,
1026        Value,
1027        MutLock,
1028        MutMid,
1029        MutValue,
1030        G1,
1031        S1,
1032        L,
1033        G2,
1034        S2,
1035        Lock2,
1036        Mid2,
1037        LockValue2,
1038        MidValue2,
1039        MutLock2,
1040        MutMid2,
1041        G2_1,
1042        S2_1,
1043        L2,
1044        G2_2,
1045        S2_2,
1046    >
1047    AsyncLockKpThenLockKp<
1048        R,
1049        V2,
1050        Root,
1051        Value2,
1052        MutRoot,
1053        MutValue2,
1054        AsyncLockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>,
1055        crate::lock::LockKp<V, Lock2, Mid2, V2, Value, LockValue2, MidValue2, Value2, MutValue, MutLock2, MutMid2, MutValue2, G2_1, S2_1, L2, G2_2, S2_2>,
1056    >
1057where
1058    Root: std::borrow::Borrow<R>,
1059    LockValue: std::borrow::Borrow<Lock>,
1060    MidValue: std::borrow::Borrow<Mid>,
1061    Value: std::borrow::Borrow<V>,
1062    MutRoot: std::borrow::BorrowMut<R>,
1063    MutLock: std::borrow::BorrowMut<Lock>,
1064    MutMid: std::borrow::BorrowMut<Mid>,
1065    MutValue: std::borrow::BorrowMut<V>,
1066    Value2: std::borrow::Borrow<V2>,
1067    MutValue2: std::borrow::BorrowMut<V2>,
1068    G1: Fn(Root) -> Option<LockValue> + Clone,
1069    S1: Fn(MutRoot) -> Option<MutLock> + Clone,
1070    L: AsyncLockLike<Lock, MidValue> + AsyncLockLike<Lock, MutMid> + Clone,
1071    G2: Fn(MidValue) -> Option<Value> + Clone,
1072    S2: Fn(MutMid) -> Option<MutValue> + Clone,
1073    LockValue2: std::borrow::Borrow<Lock2>,
1074    MidValue2: std::borrow::Borrow<Mid2>,
1075    MutLock2: std::borrow::BorrowMut<Lock2>,
1076    MutMid2: std::borrow::BorrowMut<Mid2>,
1077    G2_1: Fn(Value) -> Option<LockValue2>,
1078    S2_1: Fn(MutValue) -> Option<MutLock2>,
1079    L2: crate::lock::LockAccess<Lock2, MidValue2> + crate::lock::LockAccess<Lock2, MutMid2>,
1080    G2_2: Fn(MidValue2) -> Option<Value2>,
1081    S2_2: Fn(MutMid2) -> Option<MutValue2>,
1082    Lock: Clone,
1083    V: Clone,
1084    V2: Clone,
1085{
1086    /// Get through async lock then sync lock (root is passed here).
1087    pub async fn get(&self, root: Root) -> Option<Value2> {
1088        let value = self.first.get(root).await?;
1089        self.second.get(value)
1090    }
1091
1092    /// Get mutable through async lock then sync lock (root is passed here).
1093    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1094        let mut_value = self.first.get_mut(root).await?;
1095        self.second.get_mut(mut_value)
1096    }
1097}
1098
1099// AsyncLockKpThenLockKp when First is ComposedAsyncLockKp (so ComposedAsyncLockKp::then_lock works).
1100impl<
1101        R,
1102        V2,
1103        Root,
1104        Value2,
1105        MutRoot,
1106        MutValue2,
1107        Lock3,
1108        Mid3,
1109        LockValue3,
1110        MidValue3,
1111        MutLock3,
1112        MutMid3,
1113        G3_1,
1114        S3_1,
1115        L3,
1116        G3_2,
1117        S3_2,
1118        First,
1119        Second,
1120    >
1121    AsyncLockKpThenLockKp<
1122        R,
1123        V2,
1124        Root,
1125        Value2,
1126        MutRoot,
1127        MutValue2,
1128        ComposedAsyncLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>,
1129        crate::lock::LockKp<Value2, Lock3, Mid3, V2, Value2, LockValue3, MidValue3, Value2, MutValue2, MutLock3, MutMid3, MutValue2, G3_1, S3_1, L3, G3_2, S3_2>,
1130    >
1131where
1132    First: AsyncKeyPathLike<Root, MutRoot>,
1133    Second: AsyncKeyPathLike<First::Value, First::MutValue, Value = Value2, MutValue = MutValue2>,
1134    Value2: std::borrow::Borrow<V2>,
1135    MutValue2: std::borrow::BorrowMut<Value2> + std::borrow::BorrowMut<V2>,
1136    LockValue3: std::borrow::Borrow<Lock3>,
1137    MidValue3: std::borrow::Borrow<Mid3>,
1138    MutLock3: std::borrow::BorrowMut<Lock3>,
1139    MutMid3: std::borrow::BorrowMut<Mid3>,
1140    G3_1: Fn(Value2) -> Option<LockValue3>,
1141    S3_1: Fn(MutValue2) -> Option<MutLock3>,
1142    L3: crate::lock::LockAccess<Lock3, MidValue3> + crate::lock::LockAccess<Lock3, MutMid3>,
1143    G3_2: Fn(MidValue3) -> Option<Value2>,
1144    S3_2: Fn(MutMid3) -> Option<MutValue2>,
1145    Value2: Clone,
1146    V2: Clone,
1147{
1148    /// Get through composed async then sync lock (root is passed here).
1149    pub async fn get(&self, root: Root) -> Option<Value2> {
1150        let value = self.first.get(root).await?;
1151        self.second.get(value)
1152    }
1153    /// Get mutable through composed async then sync lock (root is passed here).
1154    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1155        let mut_value = self.first.get_mut(root).await?;
1156        self.second.get_mut(mut_value)
1157    }
1158}
1159
1160// AsyncLockKpThenLockKp when First is AsyncLockKpThenLockKp (nested; enables .then_lock().then_lock() chains).
1161impl<
1162        R,
1163        V2,
1164        Root,
1165        Value2,
1166        MutRoot,
1167        MutValue2,
1168        Lock3,
1169        Mid3,
1170        LockValue3,
1171        MidValue3,
1172        MutLock3,
1173        MutMid3,
1174        G3_1,
1175        S3_1,
1176        L3,
1177        G3_2,
1178        S3_2,
1179        F,
1180        S,
1181    >
1182    AsyncLockKpThenLockKp<
1183        R,
1184        V2,
1185        Root,
1186        Value2,
1187        MutRoot,
1188        MutValue2,
1189        AsyncLockKpThenLockKp<R, V2, Root, Value2, MutRoot, MutValue2, F, S>,
1190        crate::lock::LockKp<Value2, Lock3, Mid3, V2, Value2, LockValue3, MidValue3, Value2, MutValue2, MutLock3, MutMid3, MutValue2, G3_1, S3_1, L3, G3_2, S3_2>,
1191    >
1192where
1193    F: AsyncKeyPathLike<Root, MutRoot, Value = Value2, MutValue = MutValue2>,
1194    S: SyncKeyPathLike<Value2, Value2, MutValue2, MutValue2>,
1195    Value2: std::borrow::Borrow<V2>,
1196    MutValue2: std::borrow::BorrowMut<Value2> + std::borrow::BorrowMut<V2>,
1197    LockValue3: std::borrow::Borrow<Lock3>,
1198    MidValue3: std::borrow::Borrow<Mid3>,
1199    MutLock3: std::borrow::BorrowMut<Lock3>,
1200    MutMid3: std::borrow::BorrowMut<Mid3>,
1201    G3_1: Fn(Value2) -> Option<LockValue3>,
1202    S3_1: Fn(MutValue2) -> Option<MutLock3>,
1203    L3: crate::lock::LockAccess<Lock3, MidValue3> + crate::lock::LockAccess<Lock3, MutMid3>,
1204    G3_2: Fn(MidValue3) -> Option<Value2>,
1205    S3_2: Fn(MutMid3) -> Option<MutValue2>,
1206    Value2: Clone,
1207    V2: Clone,
1208{
1209    /// Get through async then sync then sync lock (root is passed here).
1210    pub async fn get(&self, root: Root) -> Option<Value2> {
1211        let value = AsyncKeyPathLike::get(&self.first, root).await?;
1212        self.second.get(value)
1213    }
1214    /// Get mutable through async then sync then sync lock (root is passed here).
1215    pub async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1216        let mut_value = AsyncKeyPathLike::get_mut(&self.first, root).await?;
1217        self.second.get_mut(mut_value)
1218    }
1219}
1220
1221// Blanket AsyncKeyPathLike for AsyncLockKpThenLockKp so nested chains (then_lock().then_lock()) work.
1222#[async_trait(?Send)]
1223impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> AsyncKeyPathLike<Root, MutRoot>
1224    for AsyncLockKpThenLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
1225where
1226    First: AsyncKeyPathLike<Root, MutRoot>,
1227    Second: SyncKeyPathLike<First::Value, Value2, First::MutValue, MutValue2>,
1228{
1229    type Value = Value2;
1230    type MutValue = MutValue2;
1231    async fn get(&self, root: Root) -> Option<Value2> {
1232        let value = AsyncKeyPathLike::get(&self.first, root).await?;
1233        SyncKeyPathLike::sync_get(&self.second, value)
1234    }
1235    async fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
1236        let mut_value = AsyncKeyPathLike::get_mut(&self.first, root).await?;
1237        SyncKeyPathLike::sync_get_mut(&self.second, mut_value)
1238    }
1239}
1240
1241// then_lock and then on AsyncLockKpThenLockKp so chains can continue.
1242impl<R, V2, Root, Value2, MutRoot, MutValue2, First, Second> AsyncLockKpThenLockKp<R, V2, Root, Value2, MutRoot, MutValue2, First, Second>
1243where
1244    First: AsyncKeyPathLike<Root, MutRoot>,
1245{
1246    /// Chain with an async keypath (e.g. tokio RwLock): ... -> Value2 -> async lock -> Value3.
1247    /// Use `.get(&root).await` or `.get_mut(...).await` on the returned [ComposedAsyncLockKp].
1248    pub fn then_async<
1249        Lock3,
1250        Mid3,
1251        V3,
1252        LockValue3,
1253        MidValue3,
1254        Value3,
1255        MutLock3,
1256        MutMid3,
1257        MutValue3,
1258        G3_1,
1259        S3_1,
1260        L3,
1261        G3_2,
1262        S3_2,
1263    >(
1264        self,
1265        other: AsyncLockKp<
1266            Value2,
1267            Lock3,
1268            Mid3,
1269            V3,
1270            Value2,
1271            LockValue3,
1272            MidValue3,
1273            Value3,
1274            MutValue2,
1275            MutLock3,
1276            MutMid3,
1277            MutValue3,
1278            G3_1,
1279            S3_1,
1280            L3,
1281            G3_2,
1282            S3_2,
1283        >,
1284    ) -> ComposedAsyncLockKp<
1285        Root,
1286        V3,
1287        Root,
1288        Value3,
1289        MutRoot,
1290        MutValue3,
1291        Self,
1292        AsyncLockKp<
1293            Value2,
1294            Lock3,
1295            Mid3,
1296            V3,
1297            Value2,
1298            LockValue3,
1299            MidValue3,
1300            Value3,
1301            MutValue2,
1302            MutLock3,
1303            MutMid3,
1304            MutValue3,
1305            G3_1,
1306            S3_1,
1307            L3,
1308            G3_2,
1309            S3_2,
1310        >,
1311    >
1312    where
1313        V2: 'static,
1314        V3: 'static,
1315        Value2: std::borrow::Borrow<V2>,
1316        Value3: std::borrow::Borrow<V3>,
1317        MutValue2: std::borrow::BorrowMut<V2> + std::borrow::BorrowMut<Value2>,
1318        MutValue3: std::borrow::BorrowMut<V3>,
1319        LockValue3: std::borrow::Borrow<Lock3>,
1320        MidValue3: std::borrow::Borrow<Mid3>,
1321        MutLock3: std::borrow::BorrowMut<Lock3>,
1322        MutMid3: std::borrow::BorrowMut<Mid3>,
1323        G3_1: Fn(Value2) -> Option<LockValue3> + Clone,
1324        S3_1: Fn(MutValue2) -> Option<MutLock3> + Clone,
1325        L3: AsyncLockLike<Lock3, MidValue3> + AsyncLockLike<Lock3, MutMid3> + Clone,
1326        G3_2: Fn(MidValue3) -> Option<Value3> + Clone,
1327        S3_2: Fn(MutMid3) -> Option<MutValue3> + Clone,
1328        Lock3: Clone,
1329    {
1330        ComposedAsyncLockKp {
1331            first: self,
1332            second: other,
1333            _p: std::marker::PhantomData,
1334        }
1335    }
1336
1337    /// Chain with another sync [crate::lock::LockKp]. Use `.get(&root).await` later.
1338    pub fn then_lock<
1339        Lock3,
1340        Mid3,
1341        V3,
1342        LockValue3,
1343        MidValue3,
1344        Value3,
1345        MutLock3,
1346        MutMid3,
1347        MutValue3,
1348        G3_1,
1349        S3_1,
1350        L3,
1351        G3_2,
1352        S3_2,
1353    >(
1354        self,
1355        lock_kp: crate::lock::LockKp<Value2, Lock3, Mid3, V3, Value2, LockValue3, MidValue3, Value3, MutValue2, MutLock3, MutMid3, MutValue3, G3_1, S3_1, L3, G3_2, S3_2>,
1356    ) -> AsyncLockKpThenLockKp<R, V3, Root, Value3, MutRoot, MutValue3, Self, crate::lock::LockKp<Value2, Lock3, Mid3, V3, Value2, LockValue3, MidValue3, Value3, MutValue2, MutLock3, MutMid3, MutValue3, G3_1, S3_1, L3, G3_2, S3_2>>
1357    where
1358        V3: 'static,
1359        Value2: std::borrow::Borrow<V2>,
1360        Value3: std::borrow::Borrow<V3>,
1361        MutValue2: std::borrow::BorrowMut<Value2>,
1362        MutValue3: std::borrow::BorrowMut<V3>,
1363        LockValue3: std::borrow::Borrow<Lock3>,
1364        MidValue3: std::borrow::Borrow<Mid3>,
1365        MutLock3: std::borrow::BorrowMut<Lock3>,
1366        MutMid3: std::borrow::BorrowMut<Mid3>,
1367        G3_1: Fn(Value2) -> Option<LockValue3>,
1368        S3_1: Fn(MutValue2) -> Option<MutLock3>,
1369        L3: crate::lock::LockAccess<Lock3, MidValue3> + crate::lock::LockAccess<Lock3, MutMid3>,
1370        G3_2: Fn(MidValue3) -> Option<Value3>,
1371        S3_2: Fn(MutMid3) -> Option<MutValue3>,
1372    {
1373        AsyncLockKpThenLockKp {
1374            first: self,
1375            second: lock_kp,
1376            _p: std::marker::PhantomData,
1377        }
1378    }
1379
1380    /// Chain with a regular [crate::Kp]. Use `.get(&root).await` later.
1381    pub fn then<V3, Value3, MutValue3, G3, S3>(
1382        self,
1383        next_kp: crate::Kp<Value2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>,
1384    ) -> AsyncKeyPathThenKp<R, V3, Root, Value3, MutRoot, MutValue3, Self, crate::Kp<Value2, V3, Value2, Value3, MutValue2, MutValue3, G3, S3>>
1385    where
1386        V3: 'static,
1387        Value2: std::borrow::Borrow<V2>,
1388        Value3: std::borrow::Borrow<V3>,
1389        MutValue2: std::borrow::BorrowMut<Value2>,
1390        MutValue3: std::borrow::BorrowMut<V3>,
1391        G3: Fn(Value2) -> Option<Value3> + Clone,
1392        S3: Fn(MutValue2) -> Option<MutValue3> + Clone,
1393    {
1394        AsyncKeyPathThenKp {
1395            first: self,
1396            second: next_kp,
1397            _p: std::marker::PhantomData,
1398        }
1399    }
1400}
1401
1402// ============================================================================
1403// Tokio Mutex Access Implementation
1404// ============================================================================
1405
1406#[cfg(feature = "tokio")]
1407/// Async lock access implementation for Arc<tokio::sync::Mutex<T>>
1408///
1409/// # Cloning Behavior
1410///
1411/// This struct only contains `PhantomData<T>`.
1412/// Cloning is a **zero-cost operation** - no data is copied.
1413#[derive(Clone)] // ZERO-COST: Only clones PhantomData (zero-sized type)
1414pub struct TokioMutexAccess<T> {
1415    _phantom: std::marker::PhantomData<T>,
1416}
1417
1418#[cfg(feature = "tokio")]
1419impl<T> TokioMutexAccess<T> {
1420    pub fn new() -> Self {
1421        Self {
1422            _phantom: std::marker::PhantomData,
1423        }
1424    }
1425}
1426
1427#[cfg(feature = "tokio")]
1428impl<T> Default for TokioMutexAccess<T> {
1429    fn default() -> Self {
1430        Self::new()
1431    }
1432}
1433
1434// Implementation for immutable access
1435#[cfg(feature = "tokio")]
1436#[async_trait]
1437impl<'a, T: 'static + Send + Sync> AsyncLockLike<Arc<tokio::sync::Mutex<T>>, &'a T>
1438    for TokioMutexAccess<T>
1439{
1440    #[inline]
1441    async fn lock_read(&self, lock: &Arc<tokio::sync::Mutex<T>>) -> Option<&'a T> {
1442        // SHALLOW CLONE: Only Arc refcount is incremented
1443        let guard = lock.lock().await;
1444        let ptr = &*guard as *const T;
1445        unsafe { Some(&*ptr) }
1446    }
1447
1448    #[inline]
1449    async fn lock_write(&self, lock: &mut Arc<tokio::sync::Mutex<T>>) -> Option<&'a T> {
1450        let guard = lock.lock().await;
1451        let ptr = &*guard as *const T;
1452        unsafe { Some(&*ptr) }
1453    }
1454}
1455
1456// Implementation for mutable access
1457#[cfg(feature = "tokio")]
1458#[async_trait]
1459impl<'a, T: 'static + Send + Sync> AsyncLockLike<Arc<tokio::sync::Mutex<T>>, &'a mut T>
1460    for TokioMutexAccess<T>
1461{
1462    #[inline]
1463    async fn lock_read(&self, lock: &Arc<tokio::sync::Mutex<T>>) -> Option<&'a mut T> {
1464        // SHALLOW CLONE: Only Arc refcount is incremented
1465        let mut guard = lock.lock().await;
1466        let ptr = &mut *guard as *mut T;
1467        unsafe { Some(&mut *ptr) }
1468    }
1469
1470    #[inline]
1471    async fn lock_write(&self, lock: &mut Arc<tokio::sync::Mutex<T>>) -> Option<&'a mut T> {
1472        let mut guard = lock.lock().await;
1473        let ptr = &mut *guard as *mut T;
1474        unsafe { Some(&mut *ptr) }
1475    }
1476}
1477
1478// ============================================================================
1479// Tokio RwLock Access Implementation
1480// ============================================================================
1481
1482#[cfg(feature = "tokio")]
1483/// Async lock access implementation for Arc<tokio::sync::RwLock<T>>
1484///
1485/// # Cloning Behavior
1486///
1487/// This struct only contains `PhantomData<T>`.
1488/// Cloning is a **zero-cost operation** - no data is copied.
1489/// Manual Clone impl so `T: Clone` is not required (e.g. for `Level3` with `RwLock<i32>`).
1490pub struct TokioRwLockAccess<T> {
1491    _phantom: std::marker::PhantomData<T>,
1492}
1493
1494#[cfg(feature = "tokio")]
1495impl<T> TokioRwLockAccess<T> {
1496    pub fn new() -> Self {
1497        Self {
1498            _phantom: std::marker::PhantomData,
1499        }
1500    }
1501}
1502
1503#[cfg(feature = "tokio")]
1504impl<T> Default for TokioRwLockAccess<T> {
1505    fn default() -> Self {
1506        Self::new()
1507    }
1508}
1509
1510#[cfg(feature = "tokio")]
1511impl<T> Clone for TokioRwLockAccess<T> {
1512    fn clone(&self) -> Self {
1513        Self {
1514            _phantom: self._phantom,
1515        }
1516    }
1517}
1518
1519// Implementation for immutable access (read lock)
1520#[cfg(feature = "tokio")]
1521#[async_trait]
1522impl<'a, T: 'static + Send + Sync> AsyncLockLike<Arc<tokio::sync::RwLock<T>>, &'a T>
1523    for TokioRwLockAccess<T>
1524{
1525    async fn lock_read(&self, lock: &Arc<tokio::sync::RwLock<T>>) -> Option<&'a T> {
1526        // SHALLOW CLONE: Only Arc refcount is incremented
1527        let guard = lock.read().await;
1528        let ptr = &*guard as *const T;
1529        unsafe { Some(&*ptr) }
1530    }
1531
1532    async fn lock_write(&self, lock: &mut Arc<tokio::sync::RwLock<T>>) -> Option<&'a T> {
1533        // For immutable access, use read lock
1534        let guard = lock.read().await;
1535        let ptr = &*guard as *const T;
1536        unsafe { Some(&*ptr) }
1537    }
1538}
1539
1540// Implementation for mutable access (write lock)
1541#[cfg(feature = "tokio")]
1542#[async_trait]
1543impl<'a, T: 'static + Send + Sync> AsyncLockLike<Arc<tokio::sync::RwLock<T>>, &'a mut T>
1544    for TokioRwLockAccess<T>
1545{
1546    async fn lock_read(&self, lock: &Arc<tokio::sync::RwLock<T>>) -> Option<&'a mut T> {
1547        // For mutable access, use write lock
1548        let mut guard = lock.write().await;
1549        let ptr = &mut *guard as *mut T;
1550        unsafe { Some(&mut *ptr) }
1551    }
1552
1553    async fn lock_write(&self, lock: &mut Arc<tokio::sync::RwLock<T>>) -> Option<&'a mut T> {
1554        // SHALLOW CLONE: Only Arc refcount is incremented
1555        let mut guard = lock.write().await;
1556        let ptr = &mut *guard as *mut T;
1557        unsafe { Some(&mut *ptr) }
1558    }
1559}
1560
1561// ============================================================================
1562// Tests
1563// ============================================================================
1564
1565#[cfg(all(test, feature = "tokio"))]
1566mod tests {
1567    use super::*;
1568    use crate::KpType;
1569
1570    #[tokio::test]
1571    async fn test_async_lock_kp_tokio_mutex_basic() {
1572        use tokio::sync::Mutex;
1573
1574        #[derive(Clone)]
1575        struct Root {
1576            data: Arc<Mutex<String>>,
1577        }
1578
1579        let root = Root {
1580            data: Arc::new(Mutex::new("hello".to_string())),
1581        };
1582
1583        // Create AsyncLockKp
1584        let lock_kp = {
1585            let prev: KpType<Root, Arc<Mutex<String>>> =
1586                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
1587            let next: KpType<String, String> =
1588                Kp::new(|s: &String| Some(s), |s: &mut String| Some(s));
1589            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1590        };
1591
1592        // Test async get
1593        let value = lock_kp.get(&root).await;
1594        assert!(value.is_some());
1595        assert_eq!(value.unwrap(), &"hello".to_string());
1596    }
1597
1598    #[tokio::test]
1599    async fn test_async_lock_kp_tokio_rwlock_basic() {
1600        use tokio::sync::RwLock;
1601
1602        #[derive(Clone)]
1603        struct Root {
1604            data: Arc<RwLock<Vec<i32>>>,
1605        }
1606
1607        let root = Root {
1608            data: Arc::new(RwLock::new(vec![1, 2, 3, 4, 5])),
1609        };
1610
1611        // Create AsyncLockKp with RwLock
1612        let lock_kp = {
1613            let prev: KpType<Root, Arc<RwLock<Vec<i32>>>> =
1614                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
1615            let next: KpType<Vec<i32>, Vec<i32>> =
1616                Kp::new(|v: &Vec<i32>| Some(v), |v: &mut Vec<i32>| Some(v));
1617            AsyncLockKp::new(prev, TokioRwLockAccess::new(), next)
1618        };
1619
1620        // Test async get with RwLock (read lock)
1621        let value = lock_kp.get(&root).await;
1622        assert!(value.is_some());
1623        assert_eq!(value.unwrap().len(), 5);
1624    }
1625
1626    #[tokio::test]
1627    async fn test_async_lock_kp_concurrent_reads() {
1628        use tokio::sync::RwLock;
1629
1630        #[derive(Clone)]
1631        struct Root {
1632            data: Arc<RwLock<i32>>,
1633        }
1634
1635        let root = Root {
1636            data: Arc::new(RwLock::new(42)),
1637        };
1638
1639        // Create AsyncLockKp
1640        let lock_kp = {
1641            let prev: KpType<Root, Arc<RwLock<i32>>> =
1642                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
1643            let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
1644            AsyncLockKp::new(prev, TokioRwLockAccess::new(), next)
1645        };
1646
1647        // Spawn multiple concurrent async reads
1648        let mut handles = vec![];
1649        for _ in 0..10 {
1650            let root_clone = root.clone();
1651
1652            // Re-create lock_kp for each task since we can't clone it easily
1653            let lock_kp_for_task = {
1654                let prev: KpType<Root, Arc<RwLock<i32>>> =
1655                    Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
1656                let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
1657                AsyncLockKp::new(prev, TokioRwLockAccess::new(), next)
1658            };
1659
1660            let handle = tokio::spawn(async move { lock_kp_for_task.get(&root_clone).await });
1661            handles.push(handle);
1662        }
1663
1664        // All reads should succeed
1665        for handle in handles {
1666            let result = handle.await.unwrap();
1667            assert_eq!(result, Some(&42));
1668        }
1669
1670        // Test the original lock_kp as well
1671        let value = lock_kp.get(&root).await;
1672        assert_eq!(value, Some(&42));
1673    }
1674
1675    #[tokio::test]
1676    async fn test_async_lock_kp_panic_on_clone_proof() {
1677        use tokio::sync::Mutex;
1678
1679        /// This struct PANICS if cloned - proving no deep cloning occurs
1680        struct PanicOnClone {
1681            data: String,
1682        }
1683
1684        impl Clone for PanicOnClone {
1685            fn clone(&self) -> Self {
1686                panic!("❌ ASYNC DEEP CLONE DETECTED! PanicOnClone was cloned!");
1687            }
1688        }
1689
1690        #[derive(Clone)]
1691        struct Root {
1692            level1: Arc<Mutex<Level1>>,
1693        }
1694
1695        struct Level1 {
1696            panic_data: PanicOnClone,
1697            value: i32,
1698        }
1699
1700        impl Clone for Level1 {
1701            fn clone(&self) -> Self {
1702                panic!("❌ Level1 was deeply cloned in async context!");
1703            }
1704        }
1705
1706        // Create structure with PanicOnClone
1707        let root = Root {
1708            level1: Arc::new(Mutex::new(Level1 {
1709                panic_data: PanicOnClone {
1710                    data: "test".to_string(),
1711                },
1712                value: 123,
1713            })),
1714        };
1715
1716        // Create AsyncLockKp
1717        let lock_kp = {
1718            let prev: KpType<Root, Arc<Mutex<Level1>>> = Kp::new(
1719                |r: &Root| Some(&r.level1),
1720                |r: &mut Root| Some(&mut r.level1),
1721            );
1722            let next: KpType<Level1, i32> = Kp::new(
1723                |l: &Level1| Some(&l.value),
1724                |l: &mut Level1| Some(&mut l.value),
1725            );
1726            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1727        };
1728
1729        // CRITICAL TEST: If any deep cloning occurs, PanicOnClone will trigger
1730        let value = lock_kp.get(&root).await;
1731
1732        // ✅ SUCCESS: No panic means no deep cloning!
1733        assert_eq!(value, Some(&123));
1734    }
1735
1736    #[tokio::test]
1737    async fn test_async_lock_kp_structure() {
1738        use tokio::sync::Mutex;
1739
1740        #[derive(Clone)]
1741        struct Root {
1742            data: Arc<Mutex<String>>,
1743        }
1744
1745        let lock_kp = {
1746            let prev: KpType<Root, Arc<Mutex<String>>> =
1747                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
1748            let next: KpType<String, String> =
1749                Kp::new(|s: &String| Some(s), |s: &mut String| Some(s));
1750            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1751        };
1752
1753        // Verify structure has three fields (prev, mid, next)
1754        let _ = &lock_kp.prev;
1755        let _ = &lock_kp.mid;
1756        let _ = &lock_kp.next;
1757    }
1758
1759    #[tokio::test]
1760    async fn test_async_kp_then() {
1761        use tokio::sync::Mutex;
1762
1763        #[derive(Clone)]
1764        struct Root {
1765            data: Arc<Mutex<Inner>>,
1766        }
1767
1768        #[derive(Clone)]
1769        struct Inner {
1770            value: i32,
1771        }
1772
1773        let root = Root {
1774            data: Arc::new(Mutex::new(Inner { value: 42 })),
1775        };
1776
1777        // Create AsyncLockKp to Inner
1778        let async_kp = {
1779            let prev: KpType<Root, Arc<Mutex<Inner>>> =
1780                Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
1781            let next: KpType<Inner, Inner> = Kp::new(|i: &Inner| Some(i), |i: &mut Inner| Some(i));
1782            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1783        };
1784
1785        // Chain with regular Kp to get value field
1786        let value_kp: KpType<Inner, i32> = Kp::new(
1787            |i: &Inner| Some(&i.value),
1788            |i: &mut Inner| Some(&mut i.value),
1789        );
1790
1791        let chained = async_kp.then(value_kp);
1792        let result = chained.get(&root).await;
1793        assert_eq!(result, Some(&42));
1794    }
1795
1796    #[tokio::test]
1797    async fn test_async_kp_later_then() {
1798        use tokio::sync::Mutex;
1799
1800        #[derive(Clone)]
1801        struct Root {
1802            lock1: Arc<Mutex<Container>>,
1803        }
1804
1805        #[derive(Clone)]
1806        struct Container {
1807            lock2: Arc<Mutex<i32>>,
1808        }
1809
1810        let root = Root {
1811            lock1: Arc::new(Mutex::new(Container {
1812                lock2: Arc::new(Mutex::new(999)),
1813            })),
1814        };
1815
1816        // First AsyncLockKp: Root -> Container
1817        let async_kp1 = {
1818            let prev: KpType<Root, Arc<Mutex<Container>>> =
1819                Kp::new(|r: &Root| Some(&r.lock1), |r: &mut Root| Some(&mut r.lock1));
1820            let next: KpType<Container, Container> =
1821                Kp::new(|c: &Container| Some(c), |c: &mut Container| Some(c));
1822            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1823        };
1824
1825        // Second AsyncLockKp: Container -> i32
1826        let async_kp2 = {
1827            let prev: KpType<Container, Arc<Mutex<i32>>> = Kp::new(
1828                |c: &Container| Some(&c.lock2),
1829                |c: &mut Container| Some(&mut c.lock2),
1830            );
1831            let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
1832            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1833        };
1834
1835        // Chain with then_async; get with root
1836        let chained = async_kp1.then_async(async_kp2);
1837        let result = chained.get(&root).await;
1838        assert_eq!(result, Some(&999));
1839    }
1840
1841    #[tokio::test]
1842    async fn test_async_kp_then_async_three_levels() {
1843        use tokio::sync::Mutex;
1844
1845        #[derive(Clone)]
1846        struct Root {
1847            a: Arc<Mutex<Level1>>,
1848        }
1849        #[derive(Clone)]
1850        struct Level1 {
1851            b: Arc<Mutex<Level2>>,
1852        }
1853        #[derive(Clone)]
1854        struct Level2 {
1855            c: Arc<Mutex<i32>>,
1856        }
1857
1858        let root = Root {
1859            a: Arc::new(Mutex::new(Level1 {
1860                b: Arc::new(Mutex::new(Level2 {
1861                    c: Arc::new(Mutex::new(42)),
1862                })),
1863            })),
1864        };
1865
1866        let kp1 = {
1867            let prev: KpType<Root, Arc<Mutex<Level1>>> =
1868                Kp::new(|r: &Root| Some(&r.a), |r: &mut Root| Some(&mut r.a));
1869            let next: KpType<Level1, Level1> =
1870                Kp::new(|l: &Level1| Some(l), |l: &mut Level1| Some(l));
1871            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1872        };
1873        let kp2 = {
1874            let prev: KpType<Level1, Arc<Mutex<Level2>>> =
1875                Kp::new(|l: &Level1| Some(&l.b), |l: &mut Level1| Some(&mut l.b));
1876            let next: KpType<Level2, Level2> =
1877                Kp::new(|l: &Level2| Some(l), |l: &mut Level2| Some(l));
1878            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1879        };
1880        let kp3 = {
1881            let prev: KpType<Level2, Arc<Mutex<i32>>> =
1882                Kp::new(|l: &Level2| Some(&l.c), |l: &mut Level2| Some(&mut l.c));
1883            let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
1884            AsyncLockKp::new(prev, TokioMutexAccess::new(), next)
1885        };
1886
1887        let chained = kp1.then_async(kp2).then_async(kp3);
1888        let result = chained.get(&root).await;
1889        assert_eq!(result, Some(&42));
1890    }
1891}