Skip to main content

rust_key_paths/
async_lock.rs

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