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