Skip to main content

rust_key_paths/
async_lock.rs

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