key_paths_core/
lib.rs

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