key_paths_core/
lib.rs

1use std::rc::Rc;
2use std::sync::{Arc, Mutex, RwLock};
3use std::cell::RefCell;
4
5#[cfg(feature = "tagged_core")]
6use tagged_core::Tagged;
7
8/// Trait for no-clone callback-based access to container types
9/// Provides methods to execute closures with references to values inside containers
10/// without requiring cloning of the values
11pub trait WithContainer<Root, Value> {
12    /// Execute a closure with a reference to the value inside an Arc
13    /// This avoids cloning by working with references directly
14    fn with_arc<F, R>(self, arc: &Arc<Root>, f: F) -> R
15    where
16        F: FnOnce(&Value) -> R;
17
18    /// Execute a closure with a reference to the value inside a Box
19    /// This avoids cloning by working with references directly
20    fn with_box<F, R>(self, boxed: &Box<Root>, f: F) -> R
21    where
22        F: FnOnce(&Value) -> R;
23
24    /// Execute a closure with a mutable reference to the value inside a Box
25    /// This avoids cloning by working with references directly
26    fn with_box_mut<F, R>(self, boxed: &mut Box<Root>, f: F) -> R
27    where
28        F: FnOnce(&mut Value) -> R;
29
30    /// Execute a closure with a reference to the value inside an Rc
31    /// This avoids cloning by working with references directly
32    fn with_rc<F, R>(self, rc: &Rc<Root>, f: F) -> R
33    where
34        F: FnOnce(&Value) -> R;
35
36    /// Execute a closure with a reference to the value inside a Result
37    /// This avoids cloning by working with references directly
38    fn with_result<F, R, E>(self, result: &Result<Root, E>, f: F) -> Option<R>
39    where
40        F: FnOnce(&Value) -> R;
41
42    /// Execute a closure with a mutable reference to the value inside a Result
43    /// This avoids cloning by working with references directly
44    fn with_result_mut<F, R, E>(self, result: &mut Result<Root, E>, f: F) -> Option<R>
45    where
46        F: FnOnce(&mut Value) -> R;
47
48    /// Execute a closure with a reference to the value inside an Option
49    /// This avoids cloning by working with references directly
50    fn with_option<F, R>(self, option: &Option<Root>, f: F) -> Option<R>
51    where
52        F: FnOnce(&Value) -> R;
53
54    /// Execute a closure with a mutable reference to the value inside an Option
55    /// This avoids cloning by working with references directly
56    fn with_option_mut<F, R>(self, option: &mut Option<Root>, f: F) -> Option<R>
57    where
58        F: FnOnce(&mut Value) -> R;
59
60    /// Execute a closure with a reference to the value inside a RefCell
61    /// This avoids cloning by working with references directly
62    fn with_refcell<F, R>(self, refcell: &RefCell<Root>, f: F) -> Option<R>
63    where
64        F: FnOnce(&Value) -> R;
65
66    /// Execute a closure with a mutable reference to the value inside a RefCell
67    /// This avoids cloning by working with references directly
68    fn with_refcell_mut<F, R>(self, refcell: &RefCell<Root>, f: F) -> Option<R>
69    where
70        F: FnOnce(&mut Value) -> R;
71
72    /// Execute a closure with a reference to the value inside a Tagged
73    /// This avoids cloning by working with references directly
74    #[cfg(feature = "tagged_core")]
75    fn with_tagged<F, R, Tag>(self, tagged: &Tagged<Root, Tag>, f: F) -> R
76    where
77        F: FnOnce(&Value) -> R;
78
79    /// Execute a closure with a reference to the value inside a Mutex
80    /// This avoids cloning by working with references while the guard is alive
81    fn with_mutex<F, R>(self, mutex: &Mutex<Root>, f: F) -> Option<R>
82    where
83        F: FnOnce(&Value) -> R;
84
85    /// Execute a closure with a mutable reference to the value inside a Mutex
86    /// This avoids cloning by working with references while the guard is alive
87    fn with_mutex_mut<F, R>(self, mutex: &mut Mutex<Root>, f: F) -> Option<R>
88    where
89        F: FnOnce(&mut Value) -> R;
90
91    /// Execute a closure with a reference to the value inside an RwLock
92    /// This avoids cloning by working with references while the guard is alive
93    fn with_rwlock<F, R>(self, rwlock: &RwLock<Root>, f: F) -> Option<R>
94    where
95        F: FnOnce(&Value) -> R;
96
97    /// Execute a closure with a mutable reference to the value inside an RwLock
98    /// This avoids cloning by working with references while the guard is alive
99    fn with_rwlock_mut<F, R>(self, rwlock: &mut RwLock<Root>, f: F) -> Option<R>
100    where
101        F: FnOnce(&mut Value) -> R;
102
103    /// Execute a closure with a reference to the value inside an Arc<RwLock<Root>>
104    /// This avoids cloning by working with references while the guard is alive
105    fn with_arc_rwlock<F, R>(self, arc_rwlock: &Arc<RwLock<Root>>, f: F) -> Option<R>
106    where
107        F: FnOnce(&Value) -> R;
108
109    /// Execute a closure with a mutable reference to the value inside an Arc<RwLock<Root>>
110    /// This avoids cloning by working with references while the guard is alive
111    fn with_arc_rwlock_mut<F, R>(self, arc_rwlock: &Arc<RwLock<Root>>, f: F) -> Option<R>
112    where
113        F: FnOnce(&mut Value) -> R;
114}
115
116#[derive(Clone)]
117/// Go to examples section to see the implementations
118///
119pub enum KeyPaths<Root, Value> {
120    Readable(Rc<dyn for<'a> Fn(&'a Root) -> &'a Value>),
121    ReadableEnum {
122        extract: Rc<dyn for<'a> Fn(&'a Root) -> Option<&'a Value>>,
123        embed: Rc<dyn Fn(Value) -> Root>,
124    },
125    FailableReadable(Rc<dyn for<'a> Fn(&'a Root) -> Option<&'a Value>>),
126
127    Writable(Rc<dyn for<'a> Fn(&'a mut Root) -> &'a mut Value>),
128    FailableWritable(Rc<dyn for<'a> Fn(&'a mut Root) -> Option<&'a mut Value>>),
129    WritableEnum {
130        extract: Rc<dyn for<'a> Fn(&'a Root) -> Option<&'a Value>>,
131        extract_mut: Rc<dyn for<'a> Fn(&'a mut Root) -> Option<&'a mut Value>>,
132        embed: Rc<dyn Fn(Value) -> Root>,
133    },
134
135
136
137    // New Owned KeyPath types (value semantics)
138    Owned(Rc<dyn Fn(Root) -> Value>),
139    FailableOwned(Rc<dyn Fn(Root) -> Option<Value>>),    
140}
141
142impl<Root, Value> KeyPaths<Root, Value> {
143    #[inline]
144    pub fn readable(get: impl for<'a> Fn(&'a Root) -> &'a Value + 'static) -> Self {
145        Self::Readable(Rc::new(get))
146    }
147
148    #[inline]
149    pub fn writable(get_mut: impl for<'a> Fn(&'a mut Root) -> &'a mut Value + 'static) -> Self {
150        Self::Writable(Rc::new(get_mut))
151    }
152
153    #[inline]
154    pub fn failable_readable(
155        get: impl for<'a> Fn(&'a Root) -> Option<&'a Value> + 'static,
156    ) -> Self {
157        Self::FailableReadable(Rc::new(get))
158    }
159
160    #[inline]
161    pub fn failable_writable(
162        get_mut: impl for<'a> Fn(&'a mut Root) -> Option<&'a mut Value> + 'static,
163    ) -> Self {
164        Self::FailableWritable(Rc::new(get_mut))
165    }
166
167    #[inline]
168    pub fn readable_enum(
169        embed: impl Fn(Value) -> Root + 'static,
170        extract: impl for<'a> Fn(&'a Root) -> Option<&'a Value> + 'static,
171    ) -> Self {
172        Self::ReadableEnum {
173            extract: Rc::new(extract),
174            embed: Rc::new(embed),
175        }
176    }
177
178    #[inline]
179    pub fn writable_enum(
180        embed: impl Fn(Value) -> Root + 'static,
181        extract: impl for<'a> Fn(&'a Root) -> Option<&'a Value> + 'static,
182        extract_mut: impl for<'a> Fn(&'a mut Root) -> Option<&'a mut Value> + 'static,
183    ) -> Self {
184        Self::WritableEnum {
185            extract: Rc::new(extract),
186            embed: Rc::new(embed),
187            extract_mut: Rc::new(extract_mut),
188        }
189    }
190
191
192    // New Owned KeyPath constructors
193    #[inline]
194    pub fn owned(get: impl Fn(Root) -> Value + 'static) -> Self {
195        Self::Owned(Rc::new(get))
196    }
197
198    #[inline]
199    pub fn failable_owned(get: impl Fn(Root) -> Option<Value> + 'static) -> Self {
200        Self::FailableOwned(Rc::new(get))
201    }
202
203    #[inline]
204    pub fn owned_writable(get: impl Fn(Root) -> Value + 'static) -> Self {
205        Self::Owned(Rc::new(get))
206    }
207    
208    #[inline]
209    pub fn failable_owned_writable(get: impl Fn(Root) -> Option<Value> + 'static) -> Self {
210        Self::FailableOwned(Rc::new(get))
211    }
212}
213
214impl<Root, Value> KeyPaths<Root, Value> {
215    /// Get an immutable reference if possible
216    #[inline]
217    pub fn get<'a>(&'a self, root: &'a Root) -> Option<&'a Value> {
218        match self {
219            KeyPaths::Readable(f) => Some(f(root)),
220            KeyPaths::Writable(_) => None, // Writable requires mut
221            KeyPaths::FailableReadable(f) => f(root),
222            KeyPaths::FailableWritable(_) => None, // needs mut
223            KeyPaths::ReadableEnum { extract, .. } => extract(root),
224            KeyPaths::WritableEnum { extract, .. } => extract(root),
225            // New owned keypath types (don't work with references)
226            KeyPaths::Owned(_) => None, // Owned keypaths don't work with references
227            KeyPaths::FailableOwned(_) => None, // Owned keypaths don't work with references
228        }
229    }
230
231    /// Get an immutable reference when Root is itself a reference (&T)
232    /// This enables using keypaths with collections of references like Vec<&T>
233    #[inline]
234    pub fn get_ref<'a, 'b>(&'a self, root: &'b &Root) -> Option<&'b Value> 
235    where
236        'a: 'b,
237    {
238        self.get(*root)
239    }
240
241    /// Get a mutable reference if possible
242    #[inline]
243    pub fn get_mut<'a>(&'a self, root: &'a mut Root) -> Option<&'a mut Value> {
244        match self {
245            KeyPaths::Readable(_) => None, // immutable only
246            KeyPaths::Writable(f) => Some(f(root)),
247            KeyPaths::FailableReadable(_) => None, // immutable only
248            KeyPaths::FailableWritable(f) => f(root),
249            KeyPaths::ReadableEnum { .. } => None, // immutable only
250            KeyPaths::WritableEnum { extract_mut, .. } => extract_mut(root),
251            // New owned keypath types (don't work with references)
252            KeyPaths::Owned(_) => None, // Owned keypaths don't work with references
253            KeyPaths::FailableOwned(_) => None, // Owned keypaths don't work with references
254        }
255    }
256
257    /// Get a mutable reference when Root is itself a mutable reference (&mut T)
258    /// This enables using writable keypaths with collections of mutable references
259    #[inline]
260    pub fn get_mut_ref<'a, 'b>(&'a self, root: &'b mut &mut Root) -> Option<&'b mut Value> 
261    where
262        'a: 'b,
263    {
264        self.get_mut(*root)
265    }
266
267    // ===== Smart Pointer / Container Adapter Methods =====
268    // These methods create new keypaths that work with wrapped types
269    // Enables using KeyPaths<T, V> with Vec<Arc<T>>, Vec<Box<T>>, etc.
270
271    /// Adapt this keypath to work with Arc<Root>
272    /// Enables using KeyPaths<T, V> with collections like Vec<Arc<T>>
273    #[inline]
274    pub fn for_arc(self) -> KeyPaths<Arc<Root>, Value>
275    where
276        Root: 'static,
277        Value: 'static,
278    {
279        match self {
280            KeyPaths::Readable(f) => KeyPaths::Readable(Rc::new(move |root: &Arc<Root>| {
281                f(&**root)
282            })),
283            KeyPaths::Writable(_) => {
284                // Writable doesn't work with Arc (no mutable access)
285                panic!("Cannot create writable keypath for Arc (Arc is immutable)")
286            }
287            KeyPaths::FailableReadable(f) => {
288                KeyPaths::FailableReadable(Rc::new(move |root: &Arc<Root>| f(&**root)))
289            }
290            KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
291                extract: Rc::new(move |root: &Arc<Root>| extract(&**root)),
292                embed: Rc::new(move |value| Arc::new(embed(value))),
293            },
294            other => panic!("Unsupported keypath variant for Arc adapter: {:?}", kind_name(&other)),
295        }
296    }
297
298    /// Adapt this keypath to work with Box<Root>
299    /// Enables using KeyPaths<T, V> with collections like Vec<Box<T>>
300    #[inline]
301    pub fn for_box(self) -> KeyPaths<Box<Root>, Value>
302    where
303        Root: 'static,
304        Value: 'static,
305    {
306        match self {
307            KeyPaths::Readable(f) => KeyPaths::Readable(Rc::new(move |root: &Box<Root>| {
308                f(&**root)
309            })),
310            KeyPaths::Writable(f) => KeyPaths::Writable(Rc::new(move |root: &mut Box<Root>| {
311                f(&mut **root)
312            })),
313            KeyPaths::FailableReadable(f) => {
314                KeyPaths::FailableReadable(Rc::new(move |root: &Box<Root>| f(&**root)))
315            }
316            KeyPaths::FailableWritable(f) => {
317                KeyPaths::FailableWritable(Rc::new(move |root: &mut Box<Root>| f(&mut **root)))
318            }
319            KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
320                extract: Rc::new(move |root: &Box<Root>| extract(&**root)),
321                embed: Rc::new(move |value| Box::new(embed(value))),
322            },
323            KeyPaths::WritableEnum { extract, extract_mut, embed } => KeyPaths::WritableEnum {
324                extract: Rc::new(move |root: &Box<Root>| extract(&**root)),
325                extract_mut: Rc::new(move |root: &mut Box<Root>| extract_mut(&mut **root)),
326                embed: Rc::new(move |value| Box::new(embed(value))),
327            },
328            other => panic!("Unsupported keypath variant for Box adapter: {:?}", kind_name(&other)),
329        }
330    }
331
332    /// Adapt this keypath to work with Rc<Root>
333    /// Enables using KeyPaths<T, V> with collections like Vec<Rc<T>>
334    #[inline]
335    pub fn for_rc(self) -> KeyPaths<Rc<Root>, Value>
336    where
337        Root: 'static,
338        Value: 'static,
339    {
340        match self {
341            KeyPaths::Readable(f) => KeyPaths::Readable(Rc::new(move |root: &Rc<Root>| {
342                f(&**root)
343            })),
344            KeyPaths::Writable(_) => {
345                // Writable doesn't work with Rc (no mutable access)
346                panic!("Cannot create writable keypath for Rc (Rc is immutable)")
347            }
348            KeyPaths::FailableReadable(f) => {
349                KeyPaths::FailableReadable(Rc::new(move |root: &Rc<Root>| f(&**root)))
350            }
351            KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
352                extract: Rc::new(move |root: &Rc<Root>| extract(&**root)),
353                embed: Rc::new(move |value| Rc::new(embed(value))),
354            },
355            other => panic!("Unsupported keypath variant for Rc adapter: {:?}", kind_name(&other)),
356        }
357    }
358
359    /// Adapt this keypath to work with Result<Root, E>
360    /// Enables using KeyPaths<T, V> with Result types
361    /// Note: This creates a FailableReadable keypath since Result can be Err
362    #[inline]
363    pub fn for_result<E>(self) -> KeyPaths<Result<Root, E>, Value>
364    where
365        Root: 'static,
366        Value: 'static,
367        E: 'static,
368    {
369        match self {
370            KeyPaths::Readable(f) => KeyPaths::FailableReadable(Rc::new(move |root: &Result<Root, E>| {
371                root.as_ref().ok().map(|r| f(r))
372            })),
373            KeyPaths::Writable(f) => KeyPaths::FailableWritable(Rc::new(move |root: &mut Result<Root, E>| {
374                root.as_mut().ok().map(|r| f(r))
375            })),
376            KeyPaths::FailableReadable(f) => {
377                KeyPaths::FailableReadable(Rc::new(move |root: &Result<Root, E>| {
378                    root.as_ref().ok().and_then(|r| f(r))
379                }))
380            }
381            KeyPaths::FailableWritable(f) => {
382                KeyPaths::FailableWritable(Rc::new(move |root: &mut Result<Root, E>| {
383                    root.as_mut().ok().and_then(|r| f(r))
384                }))
385            }
386            KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
387                extract: Rc::new(move |root: &Result<Root, E>| {
388                    root.as_ref().ok().and_then(|r| extract(r))
389                }),
390                embed: Rc::new(move |value| Ok(embed(value))),
391            },
392            KeyPaths::WritableEnum { extract, extract_mut, embed } => KeyPaths::WritableEnum {
393                extract: Rc::new(move |root: &Result<Root, E>| {
394                    root.as_ref().ok().and_then(|r| extract(r))
395                }),
396                extract_mut: Rc::new(move |root: &mut Result<Root, E>| {
397                    root.as_mut().ok().and_then(|r| extract_mut(r))
398                }),
399                embed: Rc::new(move |value| Ok(embed(value))),
400            },
401            other => panic!("Unsupported keypath variant for Result adapter: {:?}", kind_name(&other)),
402        }
403    }
404
405    /// Adapt this keypath to work with Option<Root>
406    /// Enables using KeyPaths<T, V> with Option types
407    /// Note: This creates a FailableReadable/FailableWritable keypath since Option can be None
408    #[inline]
409    pub fn for_option(self) -> KeyPaths<Option<Root>, Value>
410    where
411        Root: 'static,
412        Value: 'static,
413    {
414        match self {
415            KeyPaths::Readable(f) => KeyPaths::FailableReadable(Rc::new(move |root: &Option<Root>| {
416                root.as_ref().map(|r| f(r))
417            })),
418            KeyPaths::Writable(f) => KeyPaths::FailableWritable(Rc::new(move |root: &mut Option<Root>| {
419                root.as_mut().map(|r| f(r))
420            })),
421            KeyPaths::FailableReadable(f) => {
422                KeyPaths::FailableReadable(Rc::new(move |root: &Option<Root>| {
423                    root.as_ref().and_then(|r| f(r))
424                }))
425            }
426            KeyPaths::FailableWritable(f) => {
427                KeyPaths::FailableWritable(Rc::new(move |root: &mut Option<Root>| {
428                    root.as_mut().and_then(|r| f(r))
429                }))
430            }
431            KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
432                extract: Rc::new(move |root: &Option<Root>| {
433                    root.as_ref().and_then(|r| extract(r))
434                }),
435                embed: Rc::new(move |value| Some(embed(value))),
436            },
437            KeyPaths::WritableEnum { extract, extract_mut, embed } => KeyPaths::WritableEnum {
438                extract: Rc::new(move |root: &Option<Root>| {
439                    root.as_ref().and_then(|r| extract(r))
440                }),
441                extract_mut: Rc::new(move |root: &mut Option<Root>| {
442                    root.as_mut().and_then(|r| extract_mut(r))
443                }),
444                embed: Rc::new(move |value| Some(embed(value))),
445            },
446            other => panic!("Unsupported keypath variant for Option adapter: {:?}", kind_name(&other)),
447        }
448    }
449
450    /// Adapt this keypath to work with Arc<RwLock<Root>>
451    /// Enables using KeyPaths<T, V> with Arc<RwLock<T>> containers
452    /// Note: This creates a FailableOwned keypath since RwLock access can fail and we need to clone values
453    #[inline]
454    pub fn for_arc_rwlock(self) -> KeyPaths<Arc<RwLock<Root>>, Value>
455    where
456        Root: 'static,
457        Value: Clone + 'static,
458    {
459        match self {
460            KeyPaths::Readable(f) => KeyPaths::FailableOwned(Rc::new(move |root: Arc<RwLock<Root>>| {
461                let guard = root.read().ok()?;
462                Some(f(&*guard).clone())
463            })),
464            KeyPaths::Writable(_) => {
465                // Writable doesn't work with Arc<RwLock> (Arc is immutable, need write guard)
466                panic!("Cannot create writable keypath for Arc<RwLock> (use with_arc_rwlock_mut instead)")
467            }
468            KeyPaths::FailableReadable(f) => {
469                KeyPaths::FailableOwned(Rc::new(move |root: Arc<RwLock<Root>>| {
470                    let guard = root.read().ok()?;
471                    f(&*guard).map(|v| v.clone())
472                }))
473            }
474            KeyPaths::ReadableEnum { extract, embed: _ } => KeyPaths::FailableOwned(Rc::new(move |root: Arc<RwLock<Root>>| {
475                let guard = root.read().ok()?;
476                extract(&*guard).map(|v| v.clone())
477            })),
478            other => panic!("Unsupported keypath variant for Arc<RwLock> adapter: {:?}", kind_name(&other)),
479        }
480    }
481
482    /// Adapt this keypath to work with Arc<Mutex<Root>>
483    /// Enables using KeyPaths<T, V> with Arc<Mutex<T>> containers
484    /// Note: This creates a FailableOwned keypath since Mutex access can fail and we need to clone values
485    #[inline]
486    pub fn for_arc_mutex(self) -> KeyPaths<Arc<Mutex<Root>>, Value>
487    where
488        Root: 'static,
489        Value: Clone + 'static,
490    {
491        match self {
492            KeyPaths::Readable(f) => KeyPaths::FailableOwned(Rc::new(move |root: Arc<Mutex<Root>>| {
493                let guard = root.lock().ok()?;
494                Some(f(&*guard).clone())
495            })),
496            KeyPaths::Writable(_) => {
497                // Writable doesn't work with Arc<Mutex> (Arc is immutable, need write guard)
498                panic!("Cannot create writable keypath for Arc<Mutex> (use with_arc_mutex_mut instead)")
499            }
500            KeyPaths::FailableReadable(f) => {
501                KeyPaths::FailableOwned(Rc::new(move |root: Arc<Mutex<Root>>| {
502                    let guard = root.lock().ok()?;
503                    f(&*guard).map(|v| v.clone())
504                }))
505            }
506            KeyPaths::ReadableEnum { extract, embed: _ } => KeyPaths::FailableOwned(Rc::new(move |root: Arc<Mutex<Root>>| {
507                let guard = root.lock().ok()?;
508                extract(&*guard).map(|v| v.clone())
509            })),
510            other => panic!("Unsupported keypath variant for Arc<Mutex> adapter: {:?}", kind_name(&other)),
511        }
512    }
513
514    /// Adapt this keypath to work with Arc<parking_lot::Mutex<Root>>
515    /// Enables using KeyPaths<T, V> with Arc<parking_lot::Mutex<T>> containers
516    /// Note: This creates a FailableOwned keypath since Mutex access can fail and we need to clone values
517    /// Requires the "parking_lot" feature to be enabled
518    #[cfg(feature = "parking_lot")]
519    #[inline]
520    pub fn for_arc_parking_mutex(self) -> KeyPaths<Arc<parking_lot::Mutex<Root>>, Value>
521    where
522        Root: 'static,
523        Value: Clone + 'static,
524    {
525        match self {
526            KeyPaths::Readable(f) => KeyPaths::FailableOwned(Rc::new(move |root: Arc<parking_lot::Mutex<Root>>| {
527                let guard = root.lock();
528                Some(f(&*guard).clone())
529            })),
530            KeyPaths::Writable(_) => {
531                // Writable doesn't work with Arc<parking_lot::Mutex> (Arc is immutable, need write guard)
532                panic!("Cannot create writable keypath for Arc<parking_lot::Mutex> (use with_arc_parking_mutex_mut instead)")
533            }
534            KeyPaths::FailableReadable(f) => {
535                KeyPaths::FailableOwned(Rc::new(move |root: Arc<parking_lot::Mutex<Root>>| {
536                    let guard = root.lock();
537                    f(&*guard).map(|v| v.clone())
538                }))
539            }
540            KeyPaths::ReadableEnum { extract, embed: _ } => KeyPaths::FailableOwned(Rc::new(move |root: Arc<parking_lot::Mutex<Root>>| {
541                let guard = root.lock();
542                extract(&*guard).map(|v| v.clone())
543            })),
544            other => panic!("Unsupported keypath variant for Arc<parking_lot::Mutex> adapter: {:?}", kind_name(&other)),
545        }
546    }
547
548    /// Adapt this keypath to work with Arc<parking_lot::RwLock<Root>>
549    /// Enables using KeyPaths<T, V> with Arc<parking_lot::RwLock<T>> containers
550    /// Note: This creates a FailableOwned keypath since RwLock access can fail and we need to clone values
551    /// Requires the "parking_lot" feature to be enabled
552    #[cfg(feature = "parking_lot")]
553    #[inline]
554    pub fn for_arc_parking_rwlock(self) -> KeyPaths<Arc<parking_lot::RwLock<Root>>, Value>
555    where
556        Root: 'static,
557        Value: Clone + 'static,
558    {
559        match self {
560            KeyPaths::Readable(f) => KeyPaths::FailableOwned(Rc::new(move |root: Arc<parking_lot::RwLock<Root>>| {
561                let guard = root.read();
562                Some(f(&*guard).clone())
563            })),
564            KeyPaths::Writable(_) => {
565                // Writable doesn't work with Arc<parking_lot::RwLock> (Arc is immutable, need write guard)
566                panic!("Cannot create writable keypath for Arc<parking_lot::RwLock> (use with_arc_parking_rwlock_mut instead)")
567            }
568            KeyPaths::FailableReadable(f) => {
569                KeyPaths::FailableOwned(Rc::new(move |root: Arc<parking_lot::RwLock<Root>>| {
570                    let guard = root.read();
571                    f(&*guard).map(|v| v.clone())
572                }))
573            }
574            KeyPaths::ReadableEnum { extract, embed: _ } => KeyPaths::FailableOwned(Rc::new(move |root: Arc<parking_lot::RwLock<Root>>| {
575                let guard = root.read();
576                extract(&*guard).map(|v| v.clone())
577            })),
578            other => panic!("Unsupported keypath variant for Arc<parking_lot::RwLock> adapter: {:?}", kind_name(&other)),
579        }
580    }
581
582    /// Adapt a keypath to work with Tagged<Tag, Root>
583    /// Returns a new KeyPaths instance that can work with Tagged values
584    /// Note: Tagged<T, Tag> where T is the actual value and Tag is a zero-sized phantom type
585    /// Tagged only implements Deref, not DerefMut, so writable keypaths are not supported
586    #[cfg(feature = "tagged_core")]
587    #[inline]
588    pub fn for_tagged<Tag>(self) -> KeyPaths<Tagged<Root, Tag>, Value>
589    where
590        Root: Clone + 'static,
591        Value: 'static,
592        Tag: 'static,
593    {
594        match self {
595            KeyPaths::Readable(f) => KeyPaths::Readable(Rc::new(move |root: &Tagged<Root, Tag>| {
596                f(&**root)
597            })),
598            KeyPaths::Writable(_) => {
599                panic!("Tagged does not support writable keypaths (Tagged only implements Deref, not DerefMut)")
600            }
601            KeyPaths::FailableReadable(f) => KeyPaths::FailableReadable(Rc::new(move |root: &Tagged<Root, Tag>| {
602                f(&**root)
603            })),
604            KeyPaths::FailableWritable(_) => {
605                panic!("Tagged does not support writable keypaths (Tagged only implements Deref, not DerefMut)")
606            }
607            KeyPaths::Owned(f) => KeyPaths::Owned(Rc::new(move |root: Tagged<Root, Tag>| {
608                // Tagged consumes itself and returns the inner value by cloning
609                f((*root).clone())
610            })),
611            KeyPaths::FailableOwned(f) => KeyPaths::FailableOwned(Rc::new(move |root: Tagged<Root, Tag>| {
612                f((*root).clone())
613            })),
614            KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
615                extract: Rc::new(move |root: &Tagged<Root, Tag>| {
616                    extract(&**root)
617                }),
618                embed: Rc::new(move |value: Value| {
619                    Tagged::new(embed(value))
620                }),
621            },
622            KeyPaths::WritableEnum { .. } => {
623                panic!("Tagged does not support writable keypaths (Tagged only implements Deref, not DerefMut)")
624            }
625        }
626    }
627
628    // ===== WithContainer Trait Implementation =====
629    // All with_* methods are now implemented via the WithContainer trait
630
631    pub fn embed(&self, value: Value) -> Option<Root>
632    where
633        Value: Clone,
634    {
635        match self {
636            KeyPaths::ReadableEnum { embed, .. } => Some(embed(value)),
637            _ => None,
638        }
639    }
640
641    pub fn embed_mut(&self, value: Value) -> Option<Root>
642    where
643        Value: Clone,
644    {
645        match self {
646            KeyPaths::WritableEnum { embed, .. } => Some(embed(value)),
647            _ => None,
648        }
649    }
650
651
652    // ===== Owned KeyPath Accessor Methods =====
653
654    /// Get an owned value (primary method for owned keypaths)
655    #[inline]
656    pub fn get_owned(self, root: Root) -> Value {
657        match self {
658            KeyPaths::Owned(f) => f(root),
659            _ => panic!("get_owned only works with owned keypaths"),
660        }
661    }
662
663    /// Get an owned value with failable access
664    #[inline]
665    pub fn get_failable_owned(self, root: Root) -> Option<Value> {
666        match self {
667            KeyPaths::FailableOwned(f) => f(root),
668            _ => panic!("get_failable_owned only works with failable owned keypaths"),
669        }
670    }
671
672    /// Iter over immutable references if `Value: IntoIterator`
673    pub fn iter<'a, T>(&'a self, root: &'a Root) -> Option<<&'a Value as IntoIterator>::IntoIter>
674    where
675        &'a Value: IntoIterator<Item = &'a T>,
676        T: 'a,
677    {
678        self.get(root).map(|v| v.into_iter())
679    }
680
681    /// Iter over mutable references if `&mut Value: IntoIterator`
682    pub fn iter_mut<'a, T>(
683        &'a self,
684        root: &'a mut Root,
685    ) -> Option<<&'a mut Value as IntoIterator>::IntoIter>
686    where
687        &'a mut Value: IntoIterator<Item = &'a mut T>,
688        T: 'a,
689    {
690        self.get_mut(root).map(|v| v.into_iter())
691    }
692
693    /// Consume root and iterate if `Value: IntoIterator`
694    #[inline]
695    pub fn into_iter<T>(self, root: Root) -> Option<<Value as IntoIterator>::IntoIter>
696    where
697        Value: IntoIterator<Item = T> + Clone,
698    {
699        match self {
700            KeyPaths::Readable(f) => Some(f(&root).clone().into_iter()), // requires Clone
701            KeyPaths::Writable(_) => None,
702            KeyPaths::FailableReadable(f) => f(&root).map(|v| v.clone().into_iter()),
703            KeyPaths::FailableWritable(_) => None,
704            KeyPaths::ReadableEnum { extract, .. } => extract(&root).map(|v| v.clone().into_iter()),
705            KeyPaths::WritableEnum { extract, .. } => extract(&root).map(|v| v.clone().into_iter()),
706            // New owned keypath types
707            KeyPaths::Owned(f) => Some(f(root).into_iter()),
708            KeyPaths::FailableOwned(f) => f(root).map(|v| v.into_iter()),
709        }
710    }
711}
712
713// ===== WithContainer Trait Implementation =====
714impl<Root, Value> WithContainer<Root, Value> for KeyPaths<Root, Value> {
715    /// Execute a closure with a reference to the value inside an Arc
716    /// This avoids cloning by working with references directly
717    #[inline]
718    fn with_arc<F, R>(self, arc: &Arc<Root>, f: F) -> R
719    where
720        F: FnOnce(&Value) -> R,
721    {
722        match self {
723            KeyPaths::Readable(get) => f(get(&**arc)),
724            KeyPaths::FailableReadable(get) => {
725                if let Some(value) = get(&**arc) {
726                    f(value)
727                } else {
728                    panic!("FailableReadable keypath returned None for Arc")
729                }
730            }
731            _ => panic!("with_arc only works with readable keypaths"),
732        }
733    }
734
735    /// Execute a closure with a reference to the value inside a Box
736    /// This avoids cloning by working with references directly
737    #[inline]
738    fn with_box<F, R>(self, boxed: &Box<Root>, f: F) -> R
739    where
740        F: FnOnce(&Value) -> R,
741    {
742        match self {
743            KeyPaths::Readable(get) => f(get(&**boxed)),
744            KeyPaths::FailableReadable(get) => {
745                if let Some(value) = get(&**boxed) {
746                    f(value)
747                } else {
748                    panic!("FailableReadable keypath returned None for Box")
749                }
750            }
751            _ => panic!("with_box only works with readable keypaths"),
752        }
753    }
754
755    /// Execute a closure with a mutable reference to the value inside a Box
756    /// This avoids cloning by working with references directly
757    #[inline]
758    fn with_box_mut<F, R>(self, boxed: &mut Box<Root>, f: F) -> R
759    where
760        F: FnOnce(&mut Value) -> R,
761    {
762        match self {
763            KeyPaths::Writable(get) => f(get(&mut **boxed)),
764            KeyPaths::FailableWritable(get) => {
765                if let Some(value) = get(&mut **boxed) {
766                    f(value)
767                } else {
768                    panic!("FailableWritable keypath returned None for Box")
769                }
770            }
771            _ => panic!("with_box_mut only works with writable keypaths"),
772        }
773    }
774
775    /// Execute a closure with a reference to the value inside an Rc
776    /// This avoids cloning by working with references directly
777    #[inline]
778    fn with_rc<F, R>(self, rc: &Rc<Root>, f: F) -> R
779    where
780        F: FnOnce(&Value) -> R,
781    {
782        match self {
783            KeyPaths::Readable(get) => f(get(&**rc)),
784            KeyPaths::FailableReadable(get) => {
785                if let Some(value) = get(&**rc) {
786                    f(value)
787                } else {
788                    panic!("FailableReadable keypath returned None for Rc")
789                }
790            }
791            _ => panic!("with_rc only works with readable keypaths"),
792        }
793    }
794
795    /// Execute a closure with a reference to the value inside a Result
796    /// This avoids cloning by working with references directly
797    #[inline]
798    fn with_result<F, R, E>(self, result: &Result<Root, E>, f: F) -> Option<R>
799    where
800        F: FnOnce(&Value) -> R,
801    {
802        match self {
803            KeyPaths::Readable(get) => {
804                result.as_ref().ok().map(|root| f(get(root)))
805            }
806            KeyPaths::FailableReadable(get) => {
807                result.as_ref().ok().and_then(|root| get(root).map(|v| f(v)))
808            }
809            _ => panic!("with_result only works with readable keypaths"),
810        }
811    }
812
813    /// Execute a closure with a mutable reference to the value inside a Result
814    /// This avoids cloning by working with references directly
815    #[inline]
816    fn with_result_mut<F, R, E>(self, result: &mut Result<Root, E>, f: F) -> Option<R>
817    where
818        F: FnOnce(&mut Value) -> R,
819    {
820        match self {
821            KeyPaths::Writable(get) => {
822                result.as_mut().ok().map(|root| f(get(root)))
823            }
824            KeyPaths::FailableWritable(get) => {
825                result.as_mut().ok().and_then(|root| get(root).map(|v| f(v)))
826            }
827            _ => panic!("with_result_mut only works with writable keypaths"),
828        }
829    }
830
831    /// Execute a closure with a reference to the value inside an Option
832    /// This avoids cloning by working with references directly
833    #[inline]
834    fn with_option<F, R>(self, option: &Option<Root>, f: F) -> Option<R>
835    where
836        F: FnOnce(&Value) -> R,
837    {
838        match self {
839            KeyPaths::Readable(get) => {
840                option.as_ref().map(|root| f(get(root)))
841            }
842            KeyPaths::FailableReadable(get) => {
843                option.as_ref().and_then(|root| get(root).map(|v| f(v)))
844            }
845            _ => panic!("with_option only works with readable keypaths"),
846        }
847    }
848
849    /// Execute a closure with a mutable reference to the value inside an Option
850    /// This avoids cloning by working with references directly
851    #[inline]
852    fn with_option_mut<F, R>(self, option: &mut Option<Root>, f: F) -> Option<R>
853    where
854        F: FnOnce(&mut Value) -> R,
855    {
856        match self {
857            KeyPaths::Writable(get) => {
858                option.as_mut().map(|root| f(get(root)))
859            }
860            KeyPaths::FailableWritable(get) => {
861                option.as_mut().and_then(|root| get(root).map(|v| f(v)))
862            }
863            _ => panic!("with_option_mut only works with writable keypaths"),
864        }
865    }
866
867    /// Execute a closure with a reference to the value inside a RefCell
868    /// This avoids cloning by working with references directly
869    #[inline]
870    fn with_refcell<F, R>(self, refcell: &RefCell<Root>, f: F) -> Option<R>
871    where
872        F: FnOnce(&Value) -> R,
873    {
874        match self {
875            KeyPaths::Readable(get) => {
876                refcell.try_borrow().ok().map(|borrow| f(get(&*borrow)))
877            }
878            KeyPaths::FailableReadable(get) => {
879                refcell.try_borrow().ok().and_then(|borrow| get(&*borrow).map(|v| f(v)))
880            }
881            _ => panic!("with_refcell only works with readable keypaths"),
882        }
883    }
884
885    /// Execute a closure with a mutable reference to the value inside a RefCell
886    /// This avoids cloning by working with references directly
887    #[inline]
888    fn with_refcell_mut<F, R>(self, refcell: &RefCell<Root>, f: F) -> Option<R>
889    where
890        F: FnOnce(&mut Value) -> R,
891    {
892        match self {
893            KeyPaths::Writable(get) => {
894                refcell.try_borrow_mut().ok().map(|mut borrow| f(get(&mut *borrow)))
895            }
896            KeyPaths::FailableWritable(get) => {
897                refcell.try_borrow_mut().ok().and_then(|mut borrow| get(&mut *borrow).map(|v| f(v)))
898            }
899            _ => panic!("with_refcell_mut only works with writable keypaths"),
900        }
901    }
902
903    /// Execute a closure with a reference to the value inside a Tagged
904    /// This avoids cloning by working with references directly
905    #[cfg(feature = "tagged_core")]
906    #[inline]
907    fn with_tagged<F, R, Tag>(self, tagged: &Tagged<Root, Tag>, f: F) -> R
908    where
909        F: FnOnce(&Value) -> R,
910    {
911        match self {
912            KeyPaths::Readable(get) => f(get(&**tagged)),
913            KeyPaths::FailableReadable(get) => {
914                get(&**tagged).map_or_else(|| panic!("Tagged value is None"), f)
915            }
916            KeyPaths::ReadableEnum { extract, .. } => {
917                extract(&**tagged).map_or_else(|| panic!("Tagged value is None"), f)
918            }
919            _ => panic!("with_tagged only works with readable keypaths"),
920        }
921    }
922
923    /// Execute a closure with a reference to the value inside a Mutex
924    /// This avoids cloning by working with references while the guard is alive
925    #[inline]
926    fn with_mutex<F, R>(self, mutex: &Mutex<Root>, f: F) -> Option<R>
927    where
928        F: FnOnce(&Value) -> R,
929    {
930        match self {
931            KeyPaths::Readable(get) => {
932                mutex.try_lock().ok().map(|guard| f(get(&*guard)))
933            }
934            KeyPaths::FailableReadable(get) => {
935                mutex.try_lock().ok().and_then(|guard| get(&*guard).map(|v| f(v)))
936            }
937            _ => panic!("with_mutex only works with readable keypaths"),
938        }
939    }
940
941    /// Execute a closure with a mutable reference to the value inside a Mutex
942    /// This avoids cloning by working with references while the guard is alive
943    #[inline]
944    fn with_mutex_mut<F, R>(self, mutex: &mut Mutex<Root>, f: F) -> Option<R>
945    where
946        F: FnOnce(&mut Value) -> R,
947    {
948        match self {
949            KeyPaths::Writable(get) => {
950                mutex.try_lock().ok().map(|mut guard| f(get(&mut *guard)))
951            }
952            KeyPaths::FailableWritable(get) => {
953                mutex.try_lock().ok().and_then(|mut guard| get(&mut *guard).map(|v| f(v)))
954            }
955            _ => panic!("with_mutex_mut only works with writable keypaths"),
956        }
957    }
958
959    /// Execute a closure with a reference to the value inside an RwLock
960    /// This avoids cloning by working with references while the guard is alive
961    #[inline]
962    fn with_rwlock<F, R>(self, rwlock: &RwLock<Root>, f: F) -> Option<R>
963    where
964        F: FnOnce(&Value) -> R,
965    {
966        match self {
967            KeyPaths::Readable(get) => {
968                rwlock.try_read().ok().map(|guard| f(get(&*guard)))
969            }
970            KeyPaths::FailableReadable(get) => {
971                rwlock.try_read().ok().and_then(|guard| get(&*guard).map(|v| f(v)))
972            }
973            _ => panic!("with_rwlock only works with readable keypaths"),
974        }
975    }
976
977    /// Execute a closure with a mutable reference to the value inside an RwLock
978    /// This avoids cloning by working with references while the guard is alive
979    #[inline]
980    fn with_rwlock_mut<F, R>(self, rwlock: &mut RwLock<Root>, f: F) -> Option<R>
981    where
982        F: FnOnce(&mut Value) -> R,
983    {
984        match self {
985            KeyPaths::Writable(get) => {
986                rwlock.try_write().ok().map(|mut guard| f(get(&mut *guard)))
987            }
988            KeyPaths::FailableWritable(get) => {
989                rwlock.try_write().ok().and_then(|mut guard| get(&mut *guard).map(|v| f(v)))
990            }
991            _ => panic!("with_rwlock_mut only works with writable keypaths"),
992        }
993    }
994
995    /// Execute a closure with a reference to the value inside an Arc<RwLock<Root>>
996    /// This avoids cloning by working with references while the guard is alive
997    fn with_arc_rwlock<F, R>(self, arc_rwlock: &Arc<RwLock<Root>>, f: F) -> Option<R>
998    where
999        F: FnOnce(&Value) -> R,
1000    {
1001        match self {
1002            KeyPaths::Readable(get) => {
1003                arc_rwlock.try_read().ok().map(|guard| f(get(&*guard)))
1004            }
1005            KeyPaths::FailableReadable(get) => {
1006                arc_rwlock.try_read().ok().and_then(|guard| get(&*guard).map(|v| f(v)))
1007            }
1008            _ => panic!("with_arc_rwlock only works with readable keypaths"),
1009        }
1010    }
1011
1012    /// Execute a closure with a mutable reference to the value inside an Arc<RwLock<Root>>
1013    /// This avoids cloning by working with references while the guard is alive
1014    fn with_arc_rwlock_mut<F, R>(self, arc_rwlock: &Arc<RwLock<Root>>, f: F) -> Option<R>
1015    where
1016        F: FnOnce(&mut Value) -> R,
1017    {
1018        match self {
1019            KeyPaths::Writable(get) => {
1020                arc_rwlock.try_write().ok().map(|mut guard| f(get(&mut *guard)))
1021            }
1022            KeyPaths::FailableWritable(get) => {
1023                arc_rwlock.try_write().ok().and_then(|mut guard| get(&mut *guard).map(|v| f(v)))
1024            }
1025            _ => panic!("with_arc_rwlock_mut only works with writable keypaths"),
1026        }
1027    }
1028}
1029
1030impl<Root, Mid> KeyPaths<Root, Mid>
1031where
1032    Root: 'static,
1033    Mid: 'static,
1034{
1035    /// Alias for `compose` for ergonomic chaining.
1036    #[inline]
1037    pub fn then<Value>(self, mid: KeyPaths<Mid, Value>) -> KeyPaths<Root, Value>
1038    where
1039        Value: 'static,
1040    {
1041        self.compose(mid)
1042    }
1043
1044    pub fn compose<Value>(self, mid: KeyPaths<Mid, Value>) -> KeyPaths<Root, Value>
1045    where
1046        Value: 'static,
1047    {
1048        use KeyPaths::*;
1049
1050        match (self, mid) {
1051            (Readable(f1), Readable(f2)) => Readable(Rc::new(move |r| f2(f1(r)))),
1052
1053            (Writable(f1), Writable(f2)) => Writable(Rc::new(move |r| f2(f1(r)))),
1054
1055            (FailableReadable(f1), Readable(f2)) => {
1056                FailableReadable(Rc::new(move |r| f1(r).map(|m| f2(m))))
1057            }
1058
1059            (Readable(f1), FailableReadable(f2)) => FailableReadable(Rc::new(move |r| f2(f1(r)))),
1060
1061            (FailableReadable(f1), FailableReadable(f2)) => {
1062                FailableReadable(Rc::new(move |r| f1(r).and_then(|m| f2(m))))
1063            }
1064
1065            (FailableWritable(f1), Writable(f2)) => {
1066                FailableWritable(Rc::new(move |r| f1(r).map(|m| f2(m))))
1067            }
1068
1069            (Writable(f1), FailableWritable(f2)) => FailableWritable(Rc::new(move |r| f2(f1(r)))),
1070
1071            (FailableWritable(f1), FailableWritable(f2)) => {
1072                FailableWritable(Rc::new(move |r| f1(r).and_then(|m| f2(m))))
1073            }
1074            (FailableReadable(f1), ReadableEnum { extract, .. }) => {
1075                FailableReadable(Rc::new(move |r| f1(r).and_then(|m| extract(m))))
1076            }
1077            // (ReadableEnum { extract, .. }, FailableReadable(f2)) => {
1078            //     FailableReadable(Rc::new(move |r| extract(r).map(|m| f2(m).unwrap())))
1079            // }
1080            (ReadableEnum { extract, .. }, Readable(f2)) => {
1081                FailableReadable(Rc::new(move |r| extract(r).map(|m| f2(m))))
1082            }
1083
1084            (ReadableEnum { extract, .. }, FailableReadable(f2)) => {
1085                FailableReadable(Rc::new(move |r| extract(r).and_then(|m| f2(m))))
1086            }
1087
1088            (WritableEnum { extract, .. }, Readable(f2)) => {
1089                FailableReadable(Rc::new(move |r| extract(r).map(|m| f2(m))))
1090            }
1091
1092            (WritableEnum { extract, .. }, FailableReadable(f2)) => {
1093                FailableReadable(Rc::new(move |r| extract(r).and_then(|m| f2(m))))
1094            }
1095
1096            (WritableEnum { extract_mut, .. }, Writable(f2)) => {
1097                FailableWritable(Rc::new(move |r| extract_mut(r).map(|m| f2(m))))
1098            }
1099
1100            (
1101                FailableWritable(f_root_mid),
1102                WritableEnum {
1103                    extract_mut: exm_mid_val,
1104                    ..
1105                },
1106            ) => {
1107                FailableWritable(Rc::new(move |r: &mut Root| {
1108                    // First, apply the function that operates on Root.
1109                    // This will give us `Option<&mut Mid>`.
1110                    let intermediate_mid_ref = f_root_mid(r);
1111
1112                    // Then, apply the function that operates on Mid.
1113                    // This will give us `Option<&mut Value>`.
1114                    intermediate_mid_ref.and_then(|intermediate_mid| exm_mid_val(intermediate_mid))
1115                }))
1116            }
1117
1118            (WritableEnum { extract_mut, .. }, FailableWritable(f2)) => {
1119                FailableWritable(Rc::new(move |r| extract_mut(r).and_then(|m| f2(m))))
1120            }
1121
1122            // New: Writable then WritableEnum => FailableWritable
1123            (Writable(f1), WritableEnum { extract_mut, .. }) => {
1124                FailableWritable(Rc::new(move |r: &mut Root| {
1125                    let mid: &mut Mid = f1(r);
1126                    extract_mut(mid)
1127                }))
1128            }
1129
1130            (
1131                ReadableEnum {
1132                    extract: ex1,
1133                    embed: em1,
1134                },
1135                ReadableEnum {
1136                    extract: ex2,
1137                    embed: em2,
1138                },
1139            ) => ReadableEnum {
1140                extract: Rc::new(move |r| ex1(r).and_then(|m| ex2(m))),
1141                embed: Rc::new(move |v| em1(em2(v))),
1142            },
1143
1144            (
1145                WritableEnum {
1146                    extract: ex1,
1147                    extract_mut: _,
1148                    embed: em1,
1149                },
1150                ReadableEnum {
1151                    extract: ex2,
1152                    embed: em2,
1153                },
1154            ) => ReadableEnum {
1155                extract: Rc::new(move |r| ex1(r).and_then(|m| ex2(m))),
1156                embed: Rc::new(move |v| em1(em2(v))),
1157            },
1158
1159            (
1160                WritableEnum {
1161                    extract: ex1,
1162                    extract_mut: exm1,
1163                    embed: em1,
1164                },
1165                WritableEnum {
1166                    extract: ex2,
1167                    extract_mut: exm2,
1168                    embed: em2,
1169                },
1170            ) => WritableEnum {
1171                extract: Rc::new(move |r| ex1(r).and_then(|m| ex2(m))),
1172                extract_mut: Rc::new(move |r| exm1(r).and_then(|m| exm2(m))),
1173                embed: Rc::new(move |v| em1(em2(v))),
1174            },
1175
1176
1177            // New owned keypath compositions
1178            (Owned(f1), Owned(f2)) => {
1179                Owned(Rc::new(move |r| f2(f1(r))))
1180            }
1181            (FailableOwned(f1), Owned(f2)) => {
1182                FailableOwned(Rc::new(move |r| f1(r).map(|m| f2(m))))
1183            }
1184            (Owned(f1), FailableOwned(f2)) => {
1185                FailableOwned(Rc::new(move |r| f2(f1(r))))
1186            }
1187            (FailableOwned(f1), FailableOwned(f2)) => {
1188                FailableOwned(Rc::new(move |r| f1(r).and_then(|m| f2(m))))
1189            }
1190
1191            // Cross-composition between owned and regular keypaths
1192            // Note: These compositions require Clone bounds which may not always be available
1193            // For now, we'll skip these complex compositions
1194
1195            (a, b) => panic!(
1196                "Unsupported composition: {:?} then {:?}",
1197                kind_name(&a),
1198                kind_name(&b)
1199            ),
1200        }
1201    }
1202
1203    /// Get the kind name of this keypath
1204    #[inline]
1205    pub fn kind_name(&self) -> &'static str {
1206        kind_name(self)
1207    }
1208}
1209
1210fn kind_name<Root, Value>(k: &KeyPaths<Root, Value>) -> &'static str {
1211    use KeyPaths::*;
1212    match k {
1213        Readable(_) => "Readable",
1214        Writable(_) => "Writable",
1215        FailableReadable(_) => "FailableReadable",
1216        FailableWritable(_) => "FailableWritable",
1217        ReadableEnum { .. } => "ReadableEnum",
1218        WritableEnum { .. } => "WritableEnum",
1219        // New owned keypath types
1220        Owned(_) => "Owned",
1221        FailableOwned(_) => "FailableOwned",
1222    }
1223}
1224
1225// ===== Helper functions for creating reusable getter functions =====
1226// Note: These helper functions have lifetime constraints that make them
1227// difficult to implement in Rust's current type system. The keypath
1228// instances themselves can be used directly for access.
1229
1230// ===== Global compose function =====
1231
1232/// Global compose function that combines two compatible key paths
1233pub fn compose<Root, Mid, Value>(
1234    kp1: KeyPaths<Root, Mid>,
1235    kp2: KeyPaths<Mid, Value>,
1236) -> KeyPaths<Root, Value>
1237where
1238    Root: 'static,
1239    Mid: 'static,
1240    Value: 'static,
1241{
1242    kp1.compose(kp2)
1243}
1244
1245// ===== Helper macros for enum case keypaths =====
1246
1247#[macro_export]
1248macro_rules! readable_enum_macro {
1249    // Unit variant: Enum::Variant
1250    ($enum:path, $variant:ident) => {{
1251        $crate::KeyPaths::readable_enum(
1252            |_| <$enum>::$variant,
1253            |e: &$enum| match e {
1254                <$enum>::$variant => Some(&()),
1255                _ => None,
1256            },
1257        )
1258    }};
1259    // Single-field tuple variant: Enum::Variant(Inner)
1260    ($enum:path, $variant:ident($inner:ty)) => {{
1261        $crate::KeyPaths::readable_enum(
1262            |v: $inner| <$enum>::$variant(v),
1263            |e: &$enum| match e {
1264                <$enum>::$variant(v) => Some(v),
1265                _ => None,
1266            },
1267        )
1268    }};
1269}
1270
1271#[macro_export]
1272macro_rules! writable_enum_macro {
1273    // Unit variant: Enum::Variant (creates prism to and from ())
1274    ($enum:path, $variant:ident) => {{
1275        $crate::KeyPaths::writable_enum(
1276            |_| <$enum>::$variant,
1277            |e: &$enum| match e {
1278                <$enum>::$variant => Some(&()),
1279                _ => None,
1280            },
1281            |e: &mut $enum| match e {
1282                <$enum>::$variant => Some(&mut ()),
1283                _ => None,
1284            },
1285        )
1286    }};
1287    // Single-field tuple variant: Enum::Variant(Inner)
1288    ($enum:path, $variant:ident($inner:ty)) => {{
1289        $crate::KeyPaths::writable_enum(
1290            |v: $inner| <$enum>::$variant(v),
1291            |e: &$enum| match e {
1292                <$enum>::$variant(v) => Some(v),
1293                _ => None,
1294            },
1295            |e: &mut $enum| match e {
1296                <$enum>::$variant(v) => Some(v),
1297                _ => None,
1298            },
1299        )
1300    }};
1301}