Skip to main content

rust_key_paths/
async_lock.rs

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