key_paths_derive/
lib.rs

1use proc_macro::TokenStream;
2use quote::{format_ident, quote};
3use syn::{Data, DeriveInput, Fields, Type, parse_macro_input};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6enum WrapperKind {
7    None,
8    Option,
9    Box,
10    Rc,
11    Arc,
12    Vec,
13    HashMap,
14    BTreeMap,
15    HashSet,
16    BTreeSet,
17    VecDeque,
18    LinkedList,
19    BinaryHeap,
20    // Nested container support
21    OptionBox,
22    OptionRc,
23    OptionArc,
24    BoxOption,
25    RcOption,
26    ArcOption,
27    VecOption,
28    OptionVec,
29    HashMapOption,
30    OptionHashMap,
31}
32
33#[proc_macro_derive(Keypaths)]
34pub fn derive_keypaths(input: TokenStream) -> TokenStream {
35    let input = parse_macro_input!(input as DeriveInput);
36    let name = input.ident;
37
38    let methods = match input.data {
39        Data::Struct(data_struct) => match data_struct.fields {
40            Fields::Named(fields_named) => {
41                let mut tokens = proc_macro2::TokenStream::new();
42                for field in fields_named.named.iter() {
43                    let field_ident = field.ident.as_ref().unwrap();
44                    let ty = &field.ty;
45
46                    let r_fn = format_ident!("{}_r", field_ident);
47                    let w_fn = format_ident!("{}_w", field_ident);
48                    let fr_fn = format_ident!("{}_fr", field_ident);
49                    let fw_fn = format_ident!("{}_fw", field_ident);
50                    let fr_at_fn = format_ident!("{}_fr_at", field_ident);
51                    let fw_at_fn = format_ident!("{}_fw_at", field_ident);
52                    // Owned keypath method names
53                    let o_fn = format_ident!("{}_o", field_ident);
54                    let fo_fn = format_ident!("{}_fo", field_ident);
55
56                    let (kind, inner_ty) = extract_wrapper_inner_type(ty);
57
58                    match (kind, inner_ty) {
59                        (WrapperKind::Option, Some(inner_ty)) => {
60                            tokens.extend(quote! {
61                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
62                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
63                                }
64                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
65                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
66                                }
67                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
68                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref())
69                                }
70                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
71                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.as_mut())
72                                }
73                                // Owned keypath methods
74                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
75                                    key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
76                                }
77                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
78                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident)
79                                }
80                            });
81                        }
82                        (WrapperKind::Vec, Some(inner_ty)) => {
83                            tokens.extend(quote! {
84                                pub fn #fr_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
85                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(index))
86                                }
87                                pub fn #fw_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
88                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(index))
89                                }
90                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
91                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
92                                }
93                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
94                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
95                                }
96                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
97                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.first())
98                                }
99                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
100                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.first_mut())
101                                }
102                                // Owned keypath methods
103                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
104                                    key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
105                                }
106                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
107                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_iter().next())
108                                }
109                            });
110                        }
111                        (WrapperKind::HashMap, Some(inner_ty)) => {
112                            tokens.extend(quote! {
113                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
114                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
115                                }
116                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
117                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
118                                }
119                                pub fn #fr_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
120                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key))
121                                }
122                                pub fn #fw_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
123                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key))
124                                }
125                                pub fn #fr_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
126                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key))
127                                }
128                                pub fn #fw_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
129                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key))
130                                }
131                                // Owned keypath methods
132                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
133                                    key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
134                                }
135                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
136                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_values().next())
137                                }
138                            });
139                        }
140                        (WrapperKind::Box, Some(inner_ty)) => {
141                            tokens.extend(quote! {
142                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
143                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
144                                }
145                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
146                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut *s.#field_ident)
147                                }
148                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
149                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#field_ident))
150                                }
151                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
152                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut *s.#field_ident))
153                                }
154                                // Owned keypath methods
155                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
156                                    key_paths_core::KeyPaths::owned(|s: #name| *s.#field_ident)
157                                }
158                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
159                                    key_paths_core::KeyPaths::failable_owned(|s: #name| Some(*s.#field_ident))
160                                }
161                            });
162                        }
163                        (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
164                            tokens.extend(quote! {
165                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
166                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
167                                }
168                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
169                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#field_ident))
170                                }
171                                // Owned keypath methods
172                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
173                                    key_paths_core::KeyPaths::owned(|s: #name| (*s.#field_ident).clone())
174                                }
175                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
176                                    key_paths_core::KeyPaths::failable_owned(|s: #name| Some((*s.#field_ident).clone()))
177                                }
178                            });
179                        }
180                        (WrapperKind::BTreeMap, Some(inner_ty)) => {
181                            tokens.extend(quote! {
182                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
183                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
184                                }
185                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
186                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
187                                }
188                                // Owned keypath methods
189                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
190                                    key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
191                                }
192                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
193                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_values().next())
194                                }
195                                // Note: Key-based access methods for BTreeMap require the exact key type
196                                // For now, we'll skip generating these methods to avoid generic constraint issues
197                            });
198                        }
199                        (WrapperKind::HashSet, Some(inner_ty)) => {
200                            tokens.extend(quote! {
201                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
202                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
203                                }
204                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
205                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
206                                }
207                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
208                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.iter().next())
209                                }
210                                // Owned keypath methods
211                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
212                                    key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
213                                }
214                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
215                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_iter().next())
216                                }
217                            });
218                        }
219                        (WrapperKind::BTreeSet, Some(inner_ty)) => {
220                            tokens.extend(quote! {
221                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
222                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
223                                }
224                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
225                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
226                                }
227                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
228                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.iter().next())
229                                }
230                                // Owned keypath methods
231                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
232                                    key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
233                                }
234                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
235                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_iter().next())
236                                }
237                            });
238                        }
239                        (WrapperKind::VecDeque, Some(inner_ty)) => {
240                            tokens.extend(quote! {
241                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
242                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
243                                }
244                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
245                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
246                                }
247                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
248                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.front())
249                                }
250                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
251                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.front_mut())
252                                }
253                                pub fn #fr_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
254                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(index))
255                                }
256                                pub fn #fw_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
257                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(index))
258                                }
259                                // Owned keypath methods
260                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
261                                    key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
262                                }
263                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
264                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_iter().next())
265                                }
266                            });
267                        }
268                        (WrapperKind::LinkedList, Some(inner_ty)) => {
269                            tokens.extend(quote! {
270                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
271                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
272                                }
273                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
274                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
275                                }
276                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
277                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.front())
278                                }
279                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
280                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.front_mut())
281                                }
282                                // Owned keypath methods
283                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
284                                    key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
285                                }
286                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
287                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_iter().next())
288                                }
289                            });
290                        }
291                        (WrapperKind::BinaryHeap, Some(inner_ty)) => {
292                            tokens.extend(quote! {
293                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
294                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
295                                }
296                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
297                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
298                                }
299                                // Owned keypath methods
300                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
301                                    key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
302                                }
303                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
304                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#field_ident.into_iter().next())
305                                }
306                                // Note: BinaryHeap peek() returns &T, but we need &inner_ty
307                                // For now, we'll skip failable methods for BinaryHeap to avoid type issues
308                            });
309                        }
310                        // Nested container combinations - COMMENTED OUT FOR NOW
311                        // TODO: Fix type mismatch issues in nested combinations
312                        /*
313                        (WrapperKind::OptionBox, Some(inner_ty)) => {
314                            tokens.extend(quote! {
315                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
316                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
317                                }
318                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
319                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
320                                }
321                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
322                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref().map(|b| &**b))
323                                }
324                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
325                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.as_mut().map(|b| &mut **b))
326                                }
327                            });
328                        }
329                        (WrapperKind::OptionRc, Some(inner_ty)) => {
330                            tokens.extend(quote! {
331                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
332                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
333                                }
334                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
335                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref().map(|r| &**r))
336                                }
337                            });
338                        }
339                        (WrapperKind::OptionArc, Some(inner_ty)) => {
340                            tokens.extend(quote! {
341                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
342                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
343                                }
344                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
345                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref().map(|a| &**a))
346                                }
347                            });
348                        }
349                        (WrapperKind::BoxOption, Some(inner_ty)) => {
350                            tokens.extend(quote! {
351                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
352                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
353                                }
354                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
355                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut *s.#field_ident)
356                                }
357                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
358                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| (*s.#field_ident).as_ref())
359                                }
360                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
361                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| (*s.#field_ident).as_mut())
362                                }
363                            });
364                        }
365                        (WrapperKind::RcOption, Some(inner_ty)) => {
366                            tokens.extend(quote! {
367                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
368                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
369                                }
370                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
371                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| (*s.#field_ident).as_ref())
372                                }
373                            });
374                        }
375                        (WrapperKind::ArcOption, Some(inner_ty)) => {
376                            tokens.extend(quote! {
377                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
378                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
379                                }
380                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
381                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| (*s.#field_ident).as_ref())
382                                }
383                            });
384                        }
385                        (WrapperKind::VecOption, Some(inner_ty)) => {
386                            tokens.extend(quote! {
387                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
388                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
389                                }
390                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
391                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
392                                }
393                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
394                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.first().and_then(|opt| opt.as_ref()))
395                                }
396                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
397                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.first_mut().and_then(|opt| opt.as_mut()))
398                                }
399                                pub fn #fr_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
400                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(index).and_then(|opt| opt.as_ref()))
401                                }
402                                pub fn #fw_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
403                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(index).and_then(|opt| opt.as_mut()))
404                                }
405                            });
406                        }
407                        (WrapperKind::OptionVec, Some(inner_ty)) => {
408                            tokens.extend(quote! {
409                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
410                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
411                                }
412                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
413                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
414                                }
415                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
416                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref().and_then(|v| v.first()))
417                                }
418                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
419                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.as_mut().and_then(|v| v.first_mut()))
420                                }
421                                pub fn #fr_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
422                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.as_ref().and_then(|v| v.get(index)))
423                                }
424                                pub fn #fw_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
425                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.as_mut().and_then(|v| v.get_mut(index)))
426                                }
427                            });
428                        }
429                        (WrapperKind::HashMapOption, Some(inner_ty)) => {
430                            tokens.extend(quote! {
431                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
432                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
433                                }
434                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
435                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
436                                }
437                                pub fn #fr_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
438                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key).and_then(|opt| opt.as_ref()))
439                                }
440                                pub fn #fw_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
441                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key).and_then(|opt| opt.as_mut()))
442                                }
443                                pub fn #fr_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
444                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key).and_then(|opt| opt.as_ref()))
445                                }
446                                pub fn #fw_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
447                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key).and_then(|opt| opt.as_mut()))
448                                }
449                            });
450                        }
451                        (WrapperKind::OptionHashMap, Some(inner_ty)) => {
452                            tokens.extend(quote! {
453                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
454                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
455                                }
456                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
457                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
458                                }
459                                pub fn #fr_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
460                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.as_ref().and_then(|m| m.get(&key)))
461                                }
462                                pub fn #fw_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
463                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.as_mut().and_then(|m| m.get_mut(&key)))
464                                }
465                                pub fn #fr_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
466                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.as_ref().and_then(|m| m.get(&key)))
467                                }
468                                pub fn #fw_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
469                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.as_mut().and_then(|m| m.get_mut(&key)))
470                                }
471                            });
472                        }
473                        */
474                        (WrapperKind::None, None) => {
475                            tokens.extend(quote! {
476                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
477                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
478                                }
479                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
480                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
481                                }
482                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #ty> {
483                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&s.#field_ident))
484                                }
485                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #ty> {
486                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut s.#field_ident))
487                                }
488                                // Owned keypath methods
489                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
490                                    key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
491                                }
492                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #ty> {
493                                    key_paths_core::KeyPaths::failable_owned(|s: #name| Some(s.#field_ident))
494                                }
495                            });
496                        }
497                        _ => {
498                            tokens.extend(quote! {
499                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
500                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
501                                }
502                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
503                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
504                                }
505                                // Owned keypath methods
506                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
507                                    key_paths_core::KeyPaths::owned(|s: #name| s.#field_ident)
508                                }
509                            });
510                        }
511                    }
512                }
513                tokens
514            }
515            Fields::Unnamed(unnamed) => {
516                let mut tokens = proc_macro2::TokenStream::new();
517                for (idx, field) in unnamed.unnamed.iter().enumerate() {
518                    let idx_lit = syn::Index::from(idx);
519                    let ty = &field.ty;
520
521                    let r_fn = format_ident!("f{}_r", idx);
522                    let w_fn = format_ident!("f{}_w", idx);
523                    let fr_fn = format_ident!("f{}_fr", idx);
524                    let fw_fn = format_ident!("f{}_fw", idx);
525                    let fr_at_fn = format_ident!("f{}_fr_at", idx);
526                    let fw_at_fn = format_ident!("f{}_fw_at", idx);
527                    // Owned keypath method names
528                    let o_fn = format_ident!("f{}_o", idx);
529                    let fo_fn = format_ident!("f{}_fo", idx);
530
531                    let (kind, inner_ty) = extract_wrapper_inner_type(ty);
532
533                    match (kind, inner_ty) {
534                        (WrapperKind::Option, Some(inner_ty)) => {
535                            tokens.extend(quote! {
536                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
537                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
538                                }
539                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
540                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
541                                }
542                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
543                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref())
544                                }
545                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
546                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.as_mut())
547                                }
548                                // Owned keypath methods
549                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
550                                    key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
551                                }
552                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
553                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit)
554                                }
555                            });
556                        }
557                        (WrapperKind::Vec, Some(inner_ty)) => {
558                            tokens.extend(quote! {
559                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
560                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
561                                }
562                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
563                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
564                                }
565                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
566                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.first())
567                                }
568                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
569                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.first_mut())
570                                }
571                                pub fn #fr_at_fn(index: &'static usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
572                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.get(*index))
573                                }
574                                pub fn #fw_at_fn(index: &'static usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
575                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.get_mut(*index))
576                                }
577                                // Owned keypath methods
578                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
579                                    key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
580                                }
581                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
582                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_iter().next())
583                                }
584                            });
585                        }
586                        (WrapperKind::HashMap, Some(inner_ty)) => {
587                            tokens.extend(quote! {
588                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
589                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
590                                }
591                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
592                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
593                                }
594                                pub fn #fr_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
595                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key))
596                                }
597                                pub fn #fw_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
598                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key))
599                                }
600                                pub fn #fr_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
601                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key))
602                                }
603                                pub fn #fw_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
604                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key))
605                                }
606                                // Owned keypath methods
607                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
608                                    key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
609                                }
610                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
611                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_values().next())
612                                }
613                            });
614                        }
615                        (WrapperKind::Box, Some(inner_ty)) => {
616                            tokens.extend(quote! {
617                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
618                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
619                                }
620                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
621                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut *s.#idx_lit)
622                                }
623                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
624                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#idx_lit))
625                                }
626                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
627                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut *s.#idx_lit))
628                                }
629                                // Owned keypath methods
630                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
631                                    key_paths_core::KeyPaths::owned(|s: #name| *s.#idx_lit)
632                                }
633                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
634                                    key_paths_core::KeyPaths::failable_owned(|s: #name| Some(*s.#idx_lit))
635                                }
636                            });
637                        }
638                        (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
639                            tokens.extend(quote! {
640                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
641                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
642                                }
643                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
644                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#idx_lit))
645                                }
646                                // Owned keypath methods
647                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
648                                    key_paths_core::KeyPaths::owned(|s: #name| (*s.#idx_lit).clone())
649                                }
650                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
651                                    key_paths_core::KeyPaths::failable_owned(|s: #name| Some((*s.#idx_lit).clone()))
652                                }
653                            });
654                        }
655                        (WrapperKind::BTreeMap, Some(inner_ty)) => {
656                            tokens.extend(quote! {
657                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
658                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
659                                }
660                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
661                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
662                                }
663                                // Owned keypath methods
664                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
665                                    key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
666                                }
667                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
668                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_values().next())
669                                }
670                                // Note: Key-based access methods for BTreeMap require the exact key type
671                                // For now, we'll skip generating these methods to avoid generic constraint issues
672                            });
673                        }
674                        (WrapperKind::HashSet, Some(inner_ty)) => {
675                            tokens.extend(quote! {
676                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
677                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
678                                }
679                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
680                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
681                                }
682                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
683                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.iter().next())
684                                }
685                                // Owned keypath methods
686                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
687                                    key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
688                                }
689                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
690                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_iter().next())
691                                }
692                            });
693                        }
694                        (WrapperKind::BTreeSet, Some(inner_ty)) => {
695                            tokens.extend(quote! {
696                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
697                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
698                                }
699                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
700                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
701                                }
702                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
703                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.iter().next())
704                                }
705                                // Owned keypath methods
706                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
707                                    key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
708                                }
709                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
710                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_iter().next())
711                                }
712                            });
713                        }
714                        (WrapperKind::VecDeque, Some(inner_ty)) => {
715                            tokens.extend(quote! {
716                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
717                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
718                                }
719                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
720                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
721                                }
722                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
723                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.front())
724                                }
725                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
726                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.front_mut())
727                                }
728                                // Owned keypath methods
729                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
730                                    key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
731                                }
732                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
733                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_iter().next())
734                                }
735                            });
736                        }
737                        (WrapperKind::LinkedList, Some(inner_ty)) => {
738                            tokens.extend(quote! {
739                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
740                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
741                                }
742                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
743                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
744                                }
745                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
746                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.front())
747                                }
748                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
749                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.front_mut())
750                                }
751                                // Owned keypath methods
752                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
753                                    key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
754                                }
755                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
756                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_iter().next())
757                                }
758                            });
759                        }
760                        (WrapperKind::BinaryHeap, Some(inner_ty)) => {
761                            tokens.extend(quote! {
762                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
763                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
764                                }
765                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
766                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
767                                }
768                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
769                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.peek())
770                                }
771                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
772                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.peek_mut().map(|v| &mut **v))
773                                }
774                                // Owned keypath methods
775                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
776                                    key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
777                                }
778                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
779                                    key_paths_core::KeyPaths::failable_owned(|s: #name| s.#idx_lit.into_iter().next())
780                                }
781                            });
782                        }
783                        // Nested container combinations for tuple structs - COMMENTED OUT FOR NOW
784                        /*
785                        (WrapperKind::OptionBox, Some(inner_ty)) => {
786                            tokens.extend(quote! {
787                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
788                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
789                                }
790                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
791                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
792                                }
793                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
794                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref().map(|b| &**b))
795                                }
796                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
797                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.as_mut().map(|b| &mut **b))
798                                }
799                            });
800                        }
801                        (WrapperKind::OptionRc, Some(inner_ty)) => {
802                            tokens.extend(quote! {
803                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
804                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
805                                }
806                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
807                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref().map(|r| &**r))
808                                }
809                            });
810                        }
811                        (WrapperKind::OptionArc, Some(inner_ty)) => {
812                            tokens.extend(quote! {
813                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
814                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
815                                }
816                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
817                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref().map(|a| &**a))
818                                }
819                            });
820                        }
821                        (WrapperKind::BoxOption, Some(inner_ty)) => {
822                            tokens.extend(quote! {
823                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
824                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
825                                }
826                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
827                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut *s.#idx_lit)
828                                }
829                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
830                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| (*s.#idx_lit).as_ref())
831                                }
832                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
833                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| (*s.#idx_lit).as_mut())
834                                }
835                            });
836                        }
837                        (WrapperKind::RcOption, Some(inner_ty)) => {
838                            tokens.extend(quote! {
839                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
840                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
841                                }
842                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
843                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| (*s.#idx_lit).as_ref())
844                                }
845                            });
846                        }
847                        (WrapperKind::ArcOption, Some(inner_ty)) => {
848                            tokens.extend(quote! {
849                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
850                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
851                                }
852                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
853                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| (*s.#idx_lit).as_ref())
854                                }
855                            });
856                        }
857                        (WrapperKind::VecOption, Some(inner_ty)) => {
858                            tokens.extend(quote! {
859                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
860                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
861                                }
862                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
863                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
864                                }
865                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
866                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.first().and_then(|opt| opt.as_ref()))
867                                }
868                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
869                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.first_mut().and_then(|opt| opt.as_mut()))
870                                }
871                            });
872                        }
873                        (WrapperKind::OptionVec, Some(inner_ty)) => {
874                            tokens.extend(quote! {
875                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
876                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
877                                }
878                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
879                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
880                                }
881                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
882                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref().and_then(|v| v.first()))
883                                }
884                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
885                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.as_mut().and_then(|v| v.first_mut()))
886                                }
887                            });
888                        }
889                        (WrapperKind::HashMapOption, Some(inner_ty)) => {
890                            tokens.extend(quote! {
891                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
892                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
893                                }
894                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
895                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
896                                }
897                                pub fn #fr_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
898                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key).and_then(|opt| opt.as_ref()))
899                                }
900                                pub fn #fw_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
901                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key).and_then(|opt| opt.as_mut()))
902                                }
903                            });
904                        }
905                        (WrapperKind::OptionHashMap, Some(inner_ty)) => {
906                            tokens.extend(quote! {
907                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
908                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
909                                }
910                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
911                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
912                                }
913                                pub fn #fr_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
914                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.as_ref().and_then(|m| m.get(&key)))
915                                }
916                                pub fn #fw_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
917                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.as_mut().and_then(|m| m.get_mut(&key)))
918                                }
919                            });
920                        }
921                        */
922                        (WrapperKind::None, None) => {
923                            tokens.extend(quote! {
924                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
925                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
926                                }
927                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
928                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
929                                }
930                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #ty> {
931                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&s.#idx_lit))
932                                }
933                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #ty> {
934                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut s.#idx_lit))
935                                }
936                                // Owned keypath methods
937                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
938                                    key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
939                                }
940                                pub fn #fo_fn() -> key_paths_core::KeyPaths<#name, #ty> {
941                                    key_paths_core::KeyPaths::failable_owned(|s: #name| Some(s.#idx_lit))
942                                }
943                            });
944                        }
945                        _ => {
946                            tokens.extend(quote! {
947                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
948                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
949                                }
950                                // Owned keypath methods
951                                pub fn #o_fn() -> key_paths_core::KeyPaths<#name, #ty> {
952                                    key_paths_core::KeyPaths::owned(|s: #name| s.#idx_lit)
953                                }
954                            });
955                        }
956                    }
957                }
958                tokens
959            }
960            _ => quote! {
961                compile_error!("Keypaths derive supports only structs with named or unnamed fields");
962            },
963        },
964        Data::Enum(data_enum) => {
965            let mut tokens = proc_macro2::TokenStream::new();
966            for variant in data_enum.variants.iter() {
967                let v_ident = &variant.ident;
968                let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
969                let r_fn = format_ident!("{}_case_r", snake);
970                let w_fn = format_ident!("{}_case_w", snake);
971                let _fr_fn = format_ident!("{}_case_fr", snake);
972                let _fw_fn = format_ident!("{}_case_fw", snake);
973                let fr_at_fn = format_ident!("{}_case_fr_at", snake);
974                let fw_at_fn = format_ident!("{}_case_fw_at", snake);
975
976                match &variant.fields {
977                    Fields::Unit => {
978                        tokens.extend(quote! {
979                            pub fn #r_fn() -> key_paths_core::KeyPaths<#name, ()> {
980                                static UNIT: () = ();
981                                key_paths_core::KeyPaths::readable_enum(
982                                    |_| #name::#v_ident,
983                                    |e: &#name| match e { #name::#v_ident => Some(&UNIT), _ => None }
984                                )
985                            }
986                        });
987                    }
988                    Fields::Unnamed(unnamed) if unnamed.unnamed.len() == 1 => {
989                        let field_ty = &unnamed.unnamed.first().unwrap().ty;
990                        let (kind, inner_ty_opt) = extract_wrapper_inner_type(field_ty);
991
992                        match (kind, inner_ty_opt) {
993                            (WrapperKind::Option, Some(inner_ty)) => {
994                                tokens.extend(quote! {
995                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
996                                        key_paths_core::KeyPaths::readable_enum(
997                                            #name::#v_ident,
998                                            |e: &#name| match e { #name::#v_ident(v) => v.as_ref(), _ => None }
999                                        )
1000                                    }
1001                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1002                                        key_paths_core::KeyPaths::writable_enum(
1003                                            #name::#v_ident,
1004                                            |e: &#name| match e { #name::#v_ident(v) => v.as_ref(), _ => None },
1005                                            |e: &mut #name| match e { #name::#v_ident(v) => v.as_mut(), _ => None },
1006                                        )
1007                                    }
1008                                });
1009                            }
1010                            (WrapperKind::Vec, Some(inner_ty)) => {
1011                                tokens.extend(quote! {
1012                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1013                                        key_paths_core::KeyPaths::readable_enum(
1014                                            #name::#v_ident,
1015                                            |e: &#name| match e { #name::#v_ident(v) => v.first(), _ => None }
1016                                        )
1017                                    }
1018                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1019                                        key_paths_core::KeyPaths::writable_enum(
1020                                            #name::#v_ident,
1021                                            |e: &#name| match e { #name::#v_ident(v) => v.first(), _ => None },
1022                                            |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut(), _ => None },
1023                                        )
1024                                    }
1025                                    pub fn #fr_at_fn(index: &'static usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1026                                        key_paths_core::KeyPaths::readable_enum(
1027                                            #name::#v_ident,
1028                                            |e: &#name| match e { #name::#v_ident(v) => v.get(*index), _ => None }
1029                                        )
1030                                    }
1031                                    pub fn #fw_at_fn(index: &'static usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1032                                        key_paths_core::KeyPaths::writable_enum(
1033                                            #name::#v_ident,
1034                                            |e: &#name| match e { #name::#v_ident(v) => v.get(*index), _ => None },
1035                                            |e: &mut #name| match e { #name::#v_ident(v) => v.get_mut(*index), _ => None },
1036                                        )
1037                                    }
1038                                });
1039                            }
1040                        (WrapperKind::HashMap, Some(inner_ty)) => {
1041                            tokens.extend(quote! {
1042                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1043                                        key_paths_core::KeyPaths::readable_enum(
1044                                            #name::#v_ident,
1045                                            |e: &#name| match e { #name::#v_ident(v) => v.first().map(|(_, v)| v), _ => None }
1046                                        )
1047                                    }
1048                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1049                                        key_paths_core::KeyPaths::writable_enum(
1050                                            #name::#v_ident,
1051                                            |e: &#name| match e { #name::#v_ident(v) => v.first().map(|(_, v)| v), _ => None },
1052                                            |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut().map(|(_, v)| v), _ => None },
1053                                        )
1054                                    }
1055                                    pub fn #fr_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: &'static K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1056                                        key_paths_core::KeyPaths::readable_enum(
1057                                            #name::#v_ident,
1058                                            |e: &#name| match e { #name::#v_ident(v) => v.get(key), _ => None }
1059                                        )
1060                                    }
1061                                    pub fn #fw_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: &'static K) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1062                                        key_paths_core::KeyPaths::writable_enum(
1063                                            #name::#v_ident,
1064                                            |e: &#name| match e { #name::#v_ident(v) => v.get(key), _ => None },
1065                                            |e: &mut #name| match e { #name::#v_ident(v) => v.get_mut(key), _ => None },
1066                                        )
1067                                    }
1068                                });
1069                            }
1070                            (WrapperKind::Box, Some(inner_ty)) => {
1071                                tokens.extend(quote! {
1072                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1073                                        key_paths_core::KeyPaths::readable_enum(
1074                                            #name::#v_ident,
1075                                            |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
1076                                        )
1077                                    }
1078                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1079                                        key_paths_core::KeyPaths::writable_enum(
1080                                            #name::#v_ident,
1081                                            |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None },
1082                                            |e: &mut #name| match e { #name::#v_ident(v) => Some(&mut *v), _ => None },
1083                                        )
1084                                    }
1085                                });
1086                            }
1087                            (WrapperKind::Rc, Some(inner_ty))
1088                            | (WrapperKind::Arc, Some(inner_ty)) => {
1089                                tokens.extend(quote! {
1090                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1091                                        key_paths_core::KeyPaths::readable_enum(
1092                                            #name::#v_ident,
1093                                            |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
1094                                        )
1095                                    }
1096                                });
1097                            }
1098                            (WrapperKind::BTreeMap, Some(inner_ty)) => {
1099                                tokens.extend(quote! {
1100                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1101                                        key_paths_core::KeyPaths::readable_enum(
1102                                            #name::#v_ident,
1103                                            |e: &#name| match e { #name::#v_ident(v) => v.first().map(|(_, v)| v), _ => None }
1104                                        )
1105                                    }
1106                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1107                                        key_paths_core::KeyPaths::writable_enum(
1108                                            #name::#v_ident,
1109                                            |e: &#name| match e { #name::#v_ident(v) => v.first().map(|(_, v)| v), _ => None },
1110                                            |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut().map(|(_, v)| v), _ => None },
1111                                        )
1112                                    }
1113                                });
1114                            }
1115                            (WrapperKind::HashSet, Some(inner_ty)) => {
1116                                tokens.extend(quote! {
1117                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1118                                        key_paths_core::KeyPaths::readable_enum(
1119                                            #name::#v_ident,
1120                                            |e: &#name| match e { #name::#v_ident(v) => v.iter().next(), _ => None }
1121                                        )
1122                                    }
1123                                });
1124                            }
1125                            (WrapperKind::BTreeSet, Some(inner_ty)) => {
1126                                tokens.extend(quote! {
1127                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1128                                        key_paths_core::KeyPaths::readable_enum(
1129                                            #name::#v_ident,
1130                                            |e: &#name| match e { #name::#v_ident(v) => v.iter().next(), _ => None }
1131                                        )
1132                                    }
1133                                });
1134                            }
1135                            (WrapperKind::VecDeque, Some(inner_ty)) => {
1136                                tokens.extend(quote! {
1137                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1138                                        key_paths_core::KeyPaths::readable_enum(
1139                                            #name::#v_ident,
1140                                            |e: &#name| match e { #name::#v_ident(v) => v.front(), _ => None }
1141                                        )
1142                                    }
1143                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1144                                        key_paths_core::KeyPaths::writable_enum(
1145                                            #name::#v_ident,
1146                                            |e: &#name| match e { #name::#v_ident(v) => v.front(), _ => None },
1147                                            |e: &mut #name| match e { #name::#v_ident(v) => v.front_mut(), _ => None },
1148                                        )
1149                                    }
1150                                });
1151                            }
1152                            (WrapperKind::LinkedList, Some(inner_ty)) => {
1153                                tokens.extend(quote! {
1154                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1155                                        key_paths_core::KeyPaths::readable_enum(
1156                                            #name::#v_ident,
1157                                            |e: &#name| match e { #name::#v_ident(v) => v.front(), _ => None }
1158                                        )
1159                                    }
1160                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1161                                        key_paths_core::KeyPaths::writable_enum(
1162                                            #name::#v_ident,
1163                                            |e: &#name| match e { #name::#v_ident(v) => v.front(), _ => None },
1164                                            |e: &mut #name| match e { #name::#v_ident(v) => v.front_mut(), _ => None },
1165                                        )
1166                                    }
1167                                });
1168                            }
1169                            (WrapperKind::BinaryHeap, Some(inner_ty)) => {
1170                                tokens.extend(quote! {
1171                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1172                                        key_paths_core::KeyPaths::readable_enum(
1173                                            #name::#v_ident,
1174                                            |e: &#name| match e { #name::#v_ident(v) => v.peek(), _ => None }
1175                                        )
1176                                    }
1177                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1178                                        key_paths_core::KeyPaths::writable_enum(
1179                                            #name::#v_ident,
1180                                            |e: &#name| match e { #name::#v_ident(v) => v.peek(), _ => None },
1181                                            |e: &mut #name| match e { #name::#v_ident(v) => v.peek_mut().map(|v| &mut **v), _ => None },
1182                                        )
1183                                    }
1184                                });
1185                            }
1186                            // Nested container combinations for enums - COMMENTED OUT FOR NOW
1187                            /*
1188                            (WrapperKind::OptionBox, Some(inner_ty)) => {
1189                                tokens.extend(quote! {
1190                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1191                                        key_paths_core::KeyPaths::readable_enum(
1192                                            #name::#v_ident,
1193                                            |e: &#name| match e { #name::#v_ident(v) => v.as_ref().map(|b| &**b), _ => None }
1194                                        )
1195                                    }
1196                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1197                                        key_paths_core::KeyPaths::writable_enum(
1198                                            #name::#v_ident,
1199                                            |e: &#name| match e { #name::#v_ident(v) => v.as_ref().map(|b| &**b), _ => None },
1200                                            |e: &mut #name| match e { #name::#v_ident(v) => v.as_mut().map(|b| &mut **b), _ => None },
1201                                        )
1202                                    }
1203                                });
1204                            }
1205                            (WrapperKind::OptionRc, Some(inner_ty)) => {
1206                                tokens.extend(quote! {
1207                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1208                                        key_paths_core::KeyPaths::readable_enum(
1209                                            #name::#v_ident,
1210                                            |e: &#name| match e { #name::#v_ident(v) => v.as_ref().map(|r| &**r), _ => None }
1211                                        )
1212                                    }
1213                                });
1214                            }
1215                            (WrapperKind::OptionArc, Some(inner_ty)) => {
1216                                tokens.extend(quote! {
1217                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1218                                        key_paths_core::KeyPaths::readable_enum(
1219                                            #name::#v_ident,
1220                                            |e: &#name| match e { #name::#v_ident(v) => v.as_ref().map(|a| &**a), _ => None }
1221                                        )
1222                                    }
1223                                });
1224                            }
1225                            (WrapperKind::BoxOption, Some(inner_ty)) => {
1226                                tokens.extend(quote! {
1227                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #field_ty> {
1228                                        key_paths_core::KeyPaths::readable_enum(
1229                                            #name::#v_ident,
1230                                            |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
1231                                        )
1232                                    }
1233                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #field_ty> {
1234                                        key_paths_core::KeyPaths::writable_enum(
1235                                            #name::#v_ident,
1236                                            |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None },
1237                                            |e: &mut #name| match e { #name::#v_ident(v) => Some(&mut *v), _ => None },
1238                                        )
1239                                    }
1240                                    pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1241                                        key_paths_core::KeyPaths::readable_enum(
1242                                            #name::#v_ident,
1243                                            |e: &#name| match e { #name::#v_ident(v) => (*v).as_ref(), _ => None }
1244                                        )
1245                                    }
1246                                    pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1247                                        key_paths_core::KeyPaths::writable_enum(
1248                                            #name::#v_ident,
1249                                            |e: &#name| match e { #name::#v_ident(v) => (*v).as_ref(), _ => None },
1250                                            |e: &mut #name| match e { #name::#v_ident(v) => (*v).as_mut(), _ => None },
1251                                        )
1252                                    }
1253                                });
1254                            }
1255                            (WrapperKind::RcOption, Some(inner_ty)) => {
1256                                tokens.extend(quote! {
1257                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #field_ty> {
1258                                        key_paths_core::KeyPaths::readable_enum(
1259                                            #name::#v_ident,
1260                                            |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
1261                                        )
1262                                    }
1263                                    pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1264                                        key_paths_core::KeyPaths::readable_enum(
1265                                            #name::#v_ident,
1266                                            |e: &#name| match e { #name::#v_ident(v) => (*v).as_ref(), _ => None }
1267                                        )
1268                                    }
1269                                });
1270                            }
1271                            (WrapperKind::ArcOption, Some(inner_ty)) => {
1272                                tokens.extend(quote! {
1273                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #field_ty> {
1274                                        key_paths_core::KeyPaths::readable_enum(
1275                                            #name::#v_ident,
1276                                            |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
1277                                        )
1278                                    }
1279                                    pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1280                                        key_paths_core::KeyPaths::readable_enum(
1281                                            #name::#v_ident,
1282                                            |e: &#name| match e { #name::#v_ident(v) => (*v).as_ref(), _ => None }
1283                                        )
1284                                    }
1285                                });
1286                            }
1287                            (WrapperKind::VecOption, Some(inner_ty)) => {
1288                                tokens.extend(quote! {
1289                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1290                                        key_paths_core::KeyPaths::readable_enum(
1291                                            #name::#v_ident,
1292                                            |e: &#name| match e { #name::#v_ident(v) => v.first().and_then(|opt| opt.as_ref()), _ => None }
1293                                        )
1294                                    }
1295                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1296                                        key_paths_core::KeyPaths::writable_enum(
1297                                            #name::#v_ident,
1298                                            |e: &#name| match e { #name::#v_ident(v) => v.first().and_then(|opt| opt.as_ref()), _ => None },
1299                                            |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut().and_then(|opt| opt.as_mut()), _ => None },
1300                                        )
1301                                    }
1302                                });
1303                            }
1304                            (WrapperKind::OptionVec, Some(inner_ty)) => {
1305                                tokens.extend(quote! {
1306                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1307                                        key_paths_core::KeyPaths::readable_enum(
1308                                            #name::#v_ident,
1309                                            |e: &#name| match e { #name::#v_ident(v) => v.as_ref().and_then(|vec| vec.first()), _ => None }
1310                                        )
1311                                    }
1312                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1313                                        key_paths_core::KeyPaths::writable_enum(
1314                                            #name::#v_ident,
1315                                            |e: &#name| match e { #name::#v_ident(v) => v.as_ref().and_then(|vec| vec.first()), _ => None },
1316                                            |e: &mut #name| match e { #name::#v_ident(v) => v.as_mut().and_then(|vec| vec.first_mut()), _ => None },
1317                                        )
1318                                    }
1319                                });
1320                            }
1321                            (WrapperKind::HashMapOption, Some(inner_ty)) => {
1322                                tokens.extend(quote! {
1323                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1324                                        key_paths_core::KeyPaths::readable_enum(
1325                                            #name::#v_ident,
1326                                            |e: &#name| match e { #name::#v_ident(v) => v.first().and_then(|(_, opt)| opt.as_ref()), _ => None }
1327                                        )
1328                                    }
1329                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1330                                        key_paths_core::KeyPaths::writable_enum(
1331                                            #name::#v_ident,
1332                                            |e: &#name| match e { #name::#v_ident(v) => v.first().and_then(|(_, opt)| opt.as_ref()), _ => None },
1333                                            |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut().and_then(|(_, opt)| opt.as_mut()), _ => None },
1334                                        )
1335                                    }
1336                                });
1337                            }
1338                            (WrapperKind::OptionHashMap, Some(inner_ty)) => {
1339                                tokens.extend(quote! {
1340                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1341                                        key_paths_core::KeyPaths::readable_enum(
1342                                            #name::#v_ident,
1343                                            |e: &#name| match e { #name::#v_ident(v) => v.as_ref().and_then(|map| map.first().map(|(_, v)| v)), _ => None }
1344                                        )
1345                                    }
1346                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1347                                        key_paths_core::KeyPaths::writable_enum(
1348                                            #name::#v_ident,
1349                                            |e: &#name| match e { #name::#v_ident(v) => v.as_ref().and_then(|map| map.first().map(|(_, v)| v)), _ => None },
1350                                            |e: &mut #name| match e { #name::#v_ident(v) => v.as_mut().and_then(|map| map.first_mut().map(|(_, v)| v)), _ => None },
1351                                        )
1352                                    }
1353                                });
1354                            }
1355                            */
1356                            (WrapperKind::None, None) => {
1357                                let inner_ty = field_ty;
1358                                tokens.extend(quote! {
1359                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1360                                        key_paths_core::KeyPaths::readable_enum(
1361                                            #name::#v_ident,
1362                                            |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None }
1363                                        )
1364                                    }
1365                                    pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1366                                        key_paths_core::KeyPaths::writable_enum(
1367                                            #name::#v_ident,
1368                                            |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None },
1369                                            |e: &mut #name| match e { #name::#v_ident(v) => Some(v), _ => None },
1370                                        )
1371                                    }
1372                                });
1373                            }
1374                            _ => {
1375                                tokens.extend(quote! {
1376                                    pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #field_ty> {
1377                                        key_paths_core::KeyPaths::readable_enum(
1378                                            #name::#v_ident,
1379                                            |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None }
1380                                        )
1381                                    }
1382                                });
1383                            }
1384                        }
1385                    }
1386                    _ => {
1387                        tokens.extend(quote! {
1388                            compile_error!("Casepaths derive supports only unit and single-field tuple variants");
1389                        });
1390                    }
1391                }
1392            }
1393            tokens
1394        }
1395        _ => quote! {
1396            compile_error!("Keypaths derive supports only structs and enums");
1397        },
1398    };
1399
1400    let expanded = quote! {
1401        impl #name {
1402            #methods
1403        }
1404    };
1405
1406    TokenStream::from(expanded)
1407}
1408
1409fn extract_wrapper_inner_type(ty: &Type) -> (WrapperKind, Option<Type>) {
1410    use syn::{GenericArgument, PathArguments};
1411    
1412    if let Type::Path(tp) = ty {
1413        if let Some(seg) = tp.path.segments.last() {
1414            let ident_str = seg.ident.to_string();
1415            
1416            if let PathArguments::AngleBracketed(ab) = &seg.arguments {
1417                let args: Vec<_> = ab.args.iter().collect();
1418                
1419                // Handle map types (HashMap, BTreeMap) - they have K, V parameters
1420                if ident_str == "HashMap" || ident_str == "BTreeMap" {
1421                    if let (Some(_key_arg), Some(value_arg)) = (args.get(0), args.get(1)) {
1422                        if let GenericArgument::Type(inner) = value_arg {
1423                            eprintln!("Detected {} type, extracting value type", ident_str);
1424                            return match ident_str.as_str() {
1425                                "HashMap" => (WrapperKind::HashMap, Some(inner.clone())),
1426                                "BTreeMap" => (WrapperKind::BTreeMap, Some(inner.clone())),
1427                                _ => (WrapperKind::None, None),
1428                            };
1429                        }
1430                    }
1431                }
1432                // Handle single-parameter container types
1433                else if let Some(arg) = args.get(0) {
1434                    if let GenericArgument::Type(inner) = arg {
1435                        // Check for nested containers first
1436                        let (inner_kind, inner_inner) = extract_wrapper_inner_type(inner);
1437                        
1438                        // Handle nested combinations
1439                        match (ident_str.as_str(), inner_kind) {
1440                            ("Option", WrapperKind::Box) => {
1441                                return (WrapperKind::OptionBox, inner_inner);
1442                            }
1443                            ("Option", WrapperKind::Rc) => {
1444                                return (WrapperKind::OptionRc, inner_inner);
1445                            }
1446                            ("Option", WrapperKind::Arc) => {
1447                                return (WrapperKind::OptionArc, inner_inner);
1448                            }
1449                            ("Option", WrapperKind::Vec) => {
1450                                return (WrapperKind::OptionVec, inner_inner);
1451                            }
1452                            ("Option", WrapperKind::HashMap) => {
1453                                return (WrapperKind::OptionHashMap, inner_inner);
1454                            }
1455                            ("Box", WrapperKind::Option) => {
1456                                return (WrapperKind::BoxOption, inner_inner);
1457                            }
1458                            ("Rc", WrapperKind::Option) => {
1459                                return (WrapperKind::RcOption, inner_inner);
1460                            }
1461                            ("Arc", WrapperKind::Option) => {
1462                                return (WrapperKind::ArcOption, inner_inner);
1463                            }
1464                            ("Vec", WrapperKind::Option) => {
1465                                return (WrapperKind::VecOption, inner_inner);
1466                            }
1467                            ("HashMap", WrapperKind::Option) => {
1468                                return (WrapperKind::HashMapOption, inner_inner);
1469                            }
1470                            _ => {
1471                                // Handle single-level containers
1472                                return match ident_str.as_str() {
1473                                    "Option" => (WrapperKind::Option, Some(inner.clone())),
1474                                    "Box" => (WrapperKind::Box, Some(inner.clone())),
1475                                    "Rc" => (WrapperKind::Rc, Some(inner.clone())),
1476                                    "Arc" => (WrapperKind::Arc, Some(inner.clone())),
1477                                    "Vec" => (WrapperKind::Vec, Some(inner.clone())),
1478                                    "HashSet" => (WrapperKind::HashSet, Some(inner.clone())),
1479                                    "BTreeSet" => (WrapperKind::BTreeSet, Some(inner.clone())),
1480                                    "VecDeque" => (WrapperKind::VecDeque, Some(inner.clone())),
1481                                    "LinkedList" => (WrapperKind::LinkedList, Some(inner.clone())),
1482                                    "BinaryHeap" => (WrapperKind::BinaryHeap, Some(inner.clone())),
1483                                    _ => (WrapperKind::None, None),
1484                                };
1485                            }
1486                        }
1487                    }
1488                }
1489            }
1490        }
1491    }
1492    (WrapperKind::None, None)
1493}
1494
1495
1496fn to_snake_case(name: &str) -> String {
1497    let mut out = String::new();
1498    for (i, c) in name.chars().enumerate() {
1499        if c.is_uppercase() {
1500            if i != 0 {
1501                out.push('_');
1502            }
1503            out.push(c.to_ascii_lowercase());
1504        } else {
1505            out.push(c);
1506        }
1507    }
1508    out
1509}
1510
1511#[proc_macro_derive(WritableKeypaths)]
1512pub fn derive_writable_keypaths(input: TokenStream) -> TokenStream {
1513    let input = parse_macro_input!(input as DeriveInput);
1514    let name = input.ident;
1515
1516    let methods = match input.data {
1517        Data::Struct(data_struct) => match data_struct.fields {
1518            Fields::Named(fields_named) => {
1519                let mut tokens = proc_macro2::TokenStream::new();
1520                for field in fields_named.named.iter() {
1521                    let field_ident = field.ident.as_ref().unwrap();
1522                    let ty = &field.ty;
1523
1524                    let w_fn = format_ident!("{}_w", field_ident);
1525                    let fw_fn = format_ident!("{}_fw", field_ident);
1526                    let fw_at_fn = format_ident!("{}_fw_at", field_ident);
1527
1528                    let (kind, inner_ty) = extract_wrapper_inner_type(ty);
1529
1530                    match (kind, inner_ty) {
1531                        (WrapperKind::Option, Some(inner_ty)) => {
1532                            tokens.extend(quote! {
1533                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1534                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1535                                }
1536                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1537                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.as_mut())
1538                                }
1539                            });
1540                        }
1541                        (WrapperKind::Vec, Some(inner_ty)) => {
1542                            tokens.extend(quote! {
1543                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1544                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1545                                }
1546                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1547                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.first_mut())
1548                                }
1549                                pub fn #fw_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1550                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(index))
1551                                }
1552                            });
1553                        }
1554                        (WrapperKind::HashMap, Some(inner_ty)) => {
1555                            tokens.extend(quote! {
1556                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1557                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1558                                }
1559                                pub fn #fw_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1560                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key))
1561                                }
1562                                pub fn #fw_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1563                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key))
1564                                }
1565                            });
1566                        }
1567                        (WrapperKind::Box, Some(inner_ty)) => {
1568                            tokens.extend(quote! {
1569                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1570                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut *s.#field_ident)
1571                                }
1572                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1573                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut *s.#field_ident))
1574                                }
1575                            });
1576                        }
1577                        (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
1578                            tokens.extend(quote! {
1579                                // Note: Rc/Arc are not writable due to shared ownership
1580                                // Only providing readable methods for these types
1581                            });
1582                        }
1583                        (WrapperKind::BTreeMap, Some(inner_ty)) => {
1584                            tokens.extend(quote! {
1585                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1586                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1587                                }
1588                                pub fn #fw_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1589                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key))
1590                                }
1591                                pub fn #fw_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1592                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(&key))
1593                                }
1594                            });
1595                        }
1596                        (WrapperKind::HashSet, Some(inner_ty)) => {
1597                            tokens.extend(quote! {
1598                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1599                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1600                                }
1601                                // Note: HashSet doesn't have direct mutable access to elements
1602                                // Only providing container-level writable access
1603                            });
1604                        }
1605                        (WrapperKind::BTreeSet, Some(inner_ty)) => {
1606                            tokens.extend(quote! {
1607                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1608                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1609                                }
1610                                // Note: BTreeSet doesn't have direct mutable access to elements
1611                                // Only providing container-level writable access
1612                            });
1613                        }
1614                        (WrapperKind::VecDeque, Some(inner_ty)) => {
1615                            tokens.extend(quote! {
1616                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1617                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1618                                }
1619                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1620                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.front_mut())
1621                                }
1622                                pub fn #fw_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1623                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#field_ident.get_mut(index))
1624                                }
1625                            });
1626                        }
1627                        (WrapperKind::LinkedList, Some(inner_ty)) => {
1628                            tokens.extend(quote! {
1629                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1630                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1631                                }
1632                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1633                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#field_ident.front_mut())
1634                                }
1635                            });
1636                        }
1637                        (WrapperKind::BinaryHeap, Some(inner_ty)) => {
1638                            tokens.extend(quote! {
1639                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1640                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1641                                }
1642                                // Note: BinaryHeap peek_mut() returns PeekMut wrapper that doesn't allow direct mutable access
1643                                // Only providing container-level writable access
1644                            });
1645                        }
1646                        (WrapperKind::None, None) => {
1647                            tokens.extend(quote! {
1648                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1649                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1650                                }
1651                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1652                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut s.#field_ident))
1653                                }
1654                            });
1655                        }
1656                        _ => {
1657                            tokens.extend(quote! {
1658                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1659                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#field_ident)
1660                                }
1661                            });
1662                        }
1663                    }
1664                }
1665                tokens
1666            }
1667            Fields::Unnamed(unnamed) => {
1668                let mut tokens = proc_macro2::TokenStream::new();
1669                for (idx, field) in unnamed.unnamed.iter().enumerate() {
1670                    let idx_lit = syn::Index::from(idx);
1671                    let ty = &field.ty;
1672
1673                    let w_fn = format_ident!("f{}_w", idx);
1674                    let fw_fn = format_ident!("f{}_fw", idx);
1675                    let fw_at_fn = format_ident!("f{}_fw_at", idx);
1676
1677                    let (kind, inner_ty) = extract_wrapper_inner_type(ty);
1678
1679                    match (kind, inner_ty) {
1680                        (WrapperKind::Option, Some(inner_ty)) => {
1681                            tokens.extend(quote! {
1682                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1683                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1684                                }
1685                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1686                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.as_mut())
1687                                }
1688                            });
1689                        }
1690                        (WrapperKind::Vec, Some(inner_ty)) => {
1691                            tokens.extend(quote! {
1692                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1693                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1694                                }
1695                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1696                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.first_mut())
1697                                }
1698                                pub fn #fw_at_fn(index: &'static usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1699                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.get_mut(*index))
1700                                }
1701                            });
1702                        }
1703                        (WrapperKind::HashMap, Some(inner_ty)) => {
1704                            tokens.extend(quote! {
1705                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1706                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1707                                }
1708                                pub fn #fw_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1709                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key))
1710                                }
1711                                pub fn #fw_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1712                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key))
1713                                }
1714                            });
1715                        }
1716                        (WrapperKind::Box, Some(inner_ty)) => {
1717                            tokens.extend(quote! {
1718                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1719                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut *s.#idx_lit)
1720                                }
1721                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1722                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut *s.#idx_lit))
1723                                }
1724                            });
1725                        }
1726                        (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
1727                            tokens.extend(quote! {
1728                                // Note: Rc/Arc are not writable due to shared ownership
1729                                // Only providing readable methods for these types
1730                            });
1731                        }
1732                        (WrapperKind::BTreeMap, Some(inner_ty)) => {
1733                            tokens.extend(quote! {
1734                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1735                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1736                                }
1737                                pub fn #fw_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1738                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key))
1739                                }
1740                                pub fn #fw_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
1741                                    key_paths_core::KeyPaths::failable_writable(move |s: &mut #name| s.#idx_lit.get_mut(&key))
1742                                }
1743                            });
1744                        }
1745                        (WrapperKind::HashSet, Some(inner_ty)) => {
1746                            tokens.extend(quote! {
1747                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1748                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1749                                }
1750                                // Note: HashSet doesn't have direct mutable access to elements
1751                                // Only providing container-level writable access
1752                            });
1753                        }
1754                        (WrapperKind::BTreeSet, Some(inner_ty)) => {
1755                            tokens.extend(quote! {
1756                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1757                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1758                                }
1759                                // Note: BTreeSet doesn't have direct mutable access to elements
1760                                // Only providing container-level writable access
1761                            });
1762                        }
1763                        (WrapperKind::VecDeque, Some(inner_ty)) => {
1764                            tokens.extend(quote! {
1765                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1766                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1767                                }
1768                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1769                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.front_mut())
1770                                }
1771                            });
1772                        }
1773                        (WrapperKind::LinkedList, Some(inner_ty)) => {
1774                            tokens.extend(quote! {
1775                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1776                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1777                                }
1778                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1779                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| s.#idx_lit.front_mut())
1780                                }
1781                            });
1782                        }
1783                        (WrapperKind::BinaryHeap, Some(inner_ty)) => {
1784                            tokens.extend(quote! {
1785                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1786                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1787                                }
1788                                // Note: BinaryHeap peek_mut() returns PeekMut wrapper that doesn't allow direct mutable access
1789                                // Only providing container-level writable access
1790                            });
1791                        }
1792                        (WrapperKind::None, None) => {
1793                            tokens.extend(quote! {
1794                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1795                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1796                                }
1797                                pub fn #fw_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1798                                    key_paths_core::KeyPaths::failable_writable(|s: &mut #name| Some(&mut s.#idx_lit))
1799                                }
1800                            });
1801                        }
1802                        _ => {
1803                            tokens.extend(quote! {
1804                                pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #ty> {
1805                                    key_paths_core::KeyPaths::writable(|s: &mut #name| &mut s.#idx_lit)
1806                                }
1807                            });
1808                        }
1809                    }
1810                }
1811                tokens
1812            }
1813            _ => quote! {
1814                compile_error!("WritableKeypaths derive supports only structs with named or unnamed fields");
1815            },
1816        },
1817        _ => quote! {
1818            compile_error!("WritableKeypaths derive supports only structs");
1819        },
1820    };
1821
1822    let expanded = quote! {
1823        impl #name {
1824            #methods
1825        }
1826    };
1827
1828    TokenStream::from(expanded)
1829}
1830
1831#[proc_macro_derive(Keypath)]
1832pub fn derive_keypath(input: TokenStream) -> TokenStream {
1833    let input = parse_macro_input!(input as DeriveInput);
1834    let name = input.ident;
1835
1836    let methods = match input.data {
1837        Data::Struct(data_struct) => match data_struct.fields {
1838            Fields::Named(fields_named) => {
1839                let mut tokens = proc_macro2::TokenStream::new();
1840                for field in fields_named.named.iter() {
1841                    let field_ident = field.ident.as_ref().unwrap();
1842                    let ty = &field.ty;
1843
1844                    let (kind, inner_ty) = extract_wrapper_inner_type(ty);
1845
1846                    match (kind, inner_ty) {
1847                        (WrapperKind::Option, Some(inner_ty)) => {
1848                            // For Option<T>, return failable readable keypath to inner type
1849                            tokens.extend(quote! {
1850                                pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1851                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref())
1852                                }
1853                            });
1854                        }
1855                        (WrapperKind::Vec, Some(inner_ty)) => {
1856                            // For Vec<T>, return failable readable keypath to first element
1857                            tokens.extend(quote! {
1858                                pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1859                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.first())
1860                                }
1861                            });
1862                        }
1863                        (WrapperKind::HashMap, Some(inner_ty)) => {
1864                            // For HashMap<K,V>, return readable keypath to the container
1865                            tokens.extend(quote! {
1866                                pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #ty> {
1867                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
1868                                }
1869                            });
1870                        }
1871                        (WrapperKind::BTreeMap, Some(inner_ty)) => {
1872                            // For BTreeMap<K,V>, return readable keypath to the container
1873                            tokens.extend(quote! {
1874                                pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #ty> {
1875                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
1876                                }
1877                            });
1878                        }
1879                        (WrapperKind::Box, Some(inner_ty)) => {
1880                            // For Box<T>, return readable keypath to inner type
1881                            tokens.extend(quote! {
1882                                pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1883                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
1884                                }
1885                            });
1886                        }
1887                        (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
1888                            // For Rc<T>/Arc<T>, return readable keypath to inner type
1889                            tokens.extend(quote! {
1890                                pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1891                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
1892                                }
1893                            });
1894                        }
1895                        (WrapperKind::HashSet, Some(inner_ty)) => {
1896                            // For HashSet<T>, return failable readable keypath to any element
1897                            tokens.extend(quote! {
1898                                pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1899                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.iter().next())
1900                                }
1901                            });
1902                        }
1903                        (WrapperKind::BTreeSet, Some(inner_ty)) => {
1904                            // For BTreeSet<T>, return failable readable keypath to any element
1905                            tokens.extend(quote! {
1906                                pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1907                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.iter().next())
1908                                }
1909                            });
1910                        }
1911                        (WrapperKind::VecDeque, Some(inner_ty)) => {
1912                            // For VecDeque<T>, return failable readable keypath to front element
1913                            tokens.extend(quote! {
1914                                pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1915                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.front())
1916                                }
1917                            });
1918                        }
1919                        (WrapperKind::LinkedList, Some(inner_ty)) => {
1920                            // For LinkedList<T>, return failable readable keypath to front element
1921                            tokens.extend(quote! {
1922                                pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1923                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.front())
1924                                }
1925                            });
1926                        }
1927                        (WrapperKind::BinaryHeap, Some(inner_ty)) => {
1928                            // For BinaryHeap<T>, return failable readable keypath to peek element
1929                            tokens.extend(quote! {
1930                                pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1931                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.peek())
1932                                }
1933                            });
1934                        }
1935                        (WrapperKind::None, None) => {
1936                            // For basic types, return readable keypath
1937                            tokens.extend(quote! {
1938                                pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #ty> {
1939                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
1940                                }
1941                            });
1942                        }
1943                        _ => {
1944                            // For unknown types, return readable keypath
1945                            tokens.extend(quote! {
1946                                pub fn #field_ident() -> key_paths_core::KeyPaths<#name, #ty> {
1947                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
1948                                }
1949                            });
1950                        }
1951                    }
1952                }
1953                tokens
1954            }
1955            Fields::Unnamed(unnamed) => {
1956                let mut tokens = proc_macro2::TokenStream::new();
1957                for (idx, field) in unnamed.unnamed.iter().enumerate() {
1958                    let idx_lit = syn::Index::from(idx);
1959                    let ty = &field.ty;
1960                    let field_name = format_ident!("f{}", idx);
1961
1962                    let (kind, inner_ty) = extract_wrapper_inner_type(ty);
1963
1964                    match (kind, inner_ty) {
1965                        (WrapperKind::Option, Some(inner_ty)) => {
1966                            tokens.extend(quote! {
1967                                pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1968                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref())
1969                                }
1970                            });
1971                        }
1972                        (WrapperKind::Vec, Some(inner_ty)) => {
1973                            tokens.extend(quote! {
1974                                pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1975                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.first())
1976                                }
1977                            });
1978                        }
1979                        (WrapperKind::HashMap, Some(inner_ty)) => {
1980                            tokens.extend(quote! {
1981                                pub fn #field_name() -> key_paths_core::KeyPaths<#name, #ty> {
1982                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
1983                                }
1984                            });
1985                        }
1986                        (WrapperKind::BTreeMap, Some(inner_ty)) => {
1987                            tokens.extend(quote! {
1988                                pub fn #field_name() -> key_paths_core::KeyPaths<#name, #ty> {
1989                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
1990                                }
1991                            });
1992                        }
1993                        (WrapperKind::Box, Some(inner_ty)) => {
1994                            tokens.extend(quote! {
1995                                pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
1996                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
1997                                }
1998                            });
1999                        }
2000                        (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
2001                            tokens.extend(quote! {
2002                                pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2003                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
2004                                }
2005                            });
2006                        }
2007                        (WrapperKind::HashSet, Some(inner_ty)) => {
2008                            tokens.extend(quote! {
2009                                pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2010                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.iter().next())
2011                                }
2012                            });
2013                        }
2014                        (WrapperKind::BTreeSet, Some(inner_ty)) => {
2015                            tokens.extend(quote! {
2016                                pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2017                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.iter().next())
2018                                }
2019                            });
2020                        }
2021                        (WrapperKind::VecDeque, Some(inner_ty)) => {
2022                            tokens.extend(quote! {
2023                                pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2024                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.front())
2025                                }
2026                            });
2027                        }
2028                        (WrapperKind::LinkedList, Some(inner_ty)) => {
2029                            tokens.extend(quote! {
2030                                pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2031                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.front())
2032                                }
2033                            });
2034                        }
2035                        (WrapperKind::BinaryHeap, Some(inner_ty)) => {
2036                            tokens.extend(quote! {
2037                                pub fn #field_name() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2038                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.peek())
2039                                }
2040                            });
2041                        }
2042                        (WrapperKind::None, None) => {
2043                            tokens.extend(quote! {
2044                                pub fn #field_name() -> key_paths_core::KeyPaths<#name, #ty> {
2045                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2046                                }
2047                            });
2048                        }
2049                        _ => {
2050                            tokens.extend(quote! {
2051                                pub fn #field_name() -> key_paths_core::KeyPaths<#name, #ty> {
2052                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2053                                }
2054                            });
2055                        }
2056                    }
2057                }
2058                tokens
2059            }
2060            _ => quote! {
2061                compile_error!("Keypath derive supports only structs with named or unnamed fields");
2062            },
2063        },
2064        _ => quote! {
2065            compile_error!("Keypath derive supports only structs");
2066        },
2067    };
2068
2069    let expanded = quote! {
2070        impl #name {
2071            #methods
2072        }
2073    };
2074
2075    TokenStream::from(expanded)
2076}
2077
2078#[proc_macro_derive(ReadableKeypaths)]
2079pub fn derive_readable_keypaths(input: TokenStream) -> TokenStream {
2080    let input = parse_macro_input!(input as DeriveInput);
2081    let name = input.ident;
2082
2083    let methods = match input.data {
2084        Data::Struct(data_struct) => match data_struct.fields {
2085            Fields::Named(fields_named) => {
2086                let mut tokens = proc_macro2::TokenStream::new();
2087                for field in fields_named.named.iter() {
2088                    let field_ident = field.ident.as_ref().unwrap();
2089                    let ty = &field.ty;
2090
2091                    let r_fn = format_ident!("{}_r", field_ident);
2092                    let fr_fn = format_ident!("{}_fr", field_ident);
2093                    let fr_at_fn = format_ident!("{}_fr_at", field_ident);
2094
2095                    let (kind, inner_ty) = extract_wrapper_inner_type(ty);
2096
2097                    match (kind, inner_ty) {
2098                        (WrapperKind::Option, Some(inner_ty)) => {
2099                            tokens.extend(quote! {
2100                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2101                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2102                                }
2103                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2104                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.as_ref())
2105                                }
2106                            });
2107                        }
2108                        (WrapperKind::Vec, Some(inner_ty)) => {
2109                            tokens.extend(quote! {
2110                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2111                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2112                                }
2113                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2114                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.first())
2115                                }
2116                                pub fn #fr_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2117                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(index))
2118                                }
2119                            });
2120                        }
2121                        (WrapperKind::HashMap, Some(inner_ty)) => {
2122                            tokens.extend(quote! {
2123                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2124                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2125                                }
2126                                pub fn #fr_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2127                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key))
2128                                }
2129                                pub fn #fr_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2130                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key))
2131                                }
2132                            });
2133                        }
2134                        (WrapperKind::Box, Some(inner_ty)) => {
2135                            tokens.extend(quote! {
2136                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2137                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
2138                                }
2139                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2140                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#field_ident))
2141                                }
2142                            });
2143                        }
2144                        (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
2145                            tokens.extend(quote! {
2146                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2147                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#field_ident)
2148                                }
2149                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2150                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#field_ident))
2151                                }
2152                            });
2153                        }
2154                        (WrapperKind::BTreeMap, Some(inner_ty)) => {
2155                            tokens.extend(quote! {
2156                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2157                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2158                                }
2159                                pub fn #fr_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2160                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key))
2161                                }
2162                                pub fn #fr_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2163                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(&key))
2164                                }
2165                            });
2166                        }
2167                        (WrapperKind::HashSet, Some(inner_ty)) => {
2168                            tokens.extend(quote! {
2169                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2170                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2171                                }
2172                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2173                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.iter().next())
2174                                }
2175                            });
2176                        }
2177                        (WrapperKind::BTreeSet, Some(inner_ty)) => {
2178                            tokens.extend(quote! {
2179                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2180                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2181                                }
2182                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2183                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.iter().next())
2184                                }
2185                            });
2186                        }
2187                        (WrapperKind::VecDeque, Some(inner_ty)) => {
2188                            tokens.extend(quote! {
2189                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2190                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2191                                }
2192                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2193                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.front())
2194                                }
2195                                pub fn #fr_at_fn(index: usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2196                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#field_ident.get(index))
2197                                }
2198                            });
2199                        }
2200                        (WrapperKind::LinkedList, Some(inner_ty)) => {
2201                            tokens.extend(quote! {
2202                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2203                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2204                                }
2205                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2206                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.front())
2207                                }
2208                            });
2209                        }
2210                        (WrapperKind::BinaryHeap, Some(inner_ty)) => {
2211                            tokens.extend(quote! {
2212                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2213                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2214                                }
2215                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2216                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#field_ident.peek())
2217                                }
2218                            });
2219                        }
2220                        (WrapperKind::None, None) => {
2221                            tokens.extend(quote! {
2222                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2223                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2224                                }
2225                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2226                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&s.#field_ident))
2227                                }
2228                            });
2229                        }
2230                        _ => {
2231                            tokens.extend(quote! {
2232                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2233                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#field_ident)
2234                                }
2235                            });
2236                        }
2237                    }
2238                }
2239                tokens
2240            }
2241            Fields::Unnamed(unnamed) => {
2242                let mut tokens = proc_macro2::TokenStream::new();
2243                for (idx, field) in unnamed.unnamed.iter().enumerate() {
2244                    let idx_lit = syn::Index::from(idx);
2245                    let ty = &field.ty;
2246
2247                    let r_fn = format_ident!("f{}_r", idx);
2248                    let fr_fn = format_ident!("f{}_fr", idx);
2249                    let fr_at_fn = format_ident!("f{}_fr_at", idx);
2250
2251                    let (kind, inner_ty) = extract_wrapper_inner_type(ty);
2252
2253                    match (kind, inner_ty) {
2254                        (WrapperKind::Option, Some(inner_ty)) => {
2255                            tokens.extend(quote! {
2256                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2257                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2258                                }
2259                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2260                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.as_ref())
2261                                }
2262                            });
2263                        }
2264                        (WrapperKind::Vec, Some(inner_ty)) => {
2265                            tokens.extend(quote! {
2266                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2267                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2268                                }
2269                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2270                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.first())
2271                                }
2272                                pub fn #fr_at_fn(index: &'static usize) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2273                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.get(*index))
2274                                }
2275                            });
2276                        }
2277                        (WrapperKind::HashMap, Some(inner_ty)) => {
2278                            tokens.extend(quote! {
2279                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2280                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2281                                }
2282                                pub fn #fr_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2283                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key))
2284                                }
2285                                pub fn #fr_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2286                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key))
2287                                }
2288                            });
2289                        }
2290                        (WrapperKind::Box, Some(inner_ty)) => {
2291                            tokens.extend(quote! {
2292                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2293                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
2294                                }
2295                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2296                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#idx_lit))
2297                                }
2298                            });
2299                        }
2300                        (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
2301                            tokens.extend(quote! {
2302                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2303                                    key_paths_core::KeyPaths::readable(|s: &#name| &*s.#idx_lit)
2304                                }
2305                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2306                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&*s.#idx_lit))
2307                                }
2308                            });
2309                        }
2310                        (WrapperKind::BTreeMap, Some(inner_ty)) => {
2311                            tokens.extend(quote! {
2312                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2313                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2314                                }
2315                                pub fn #fr_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2316                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key))
2317                                }
2318                                pub fn #fr_at_fn(key: String) -> key_paths_core::KeyPaths<#name, #inner_ty> {
2319                                    key_paths_core::KeyPaths::failable_readable(move |s: &#name| s.#idx_lit.get(&key))
2320                                }
2321                            });
2322                        }
2323                        (WrapperKind::HashSet, Some(inner_ty)) => {
2324                            tokens.extend(quote! {
2325                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2326                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2327                                }
2328                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2329                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.iter().next())
2330                                }
2331                            });
2332                        }
2333                        (WrapperKind::BTreeSet, Some(inner_ty)) => {
2334                            tokens.extend(quote! {
2335                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2336                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2337                                }
2338                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2339                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.iter().next())
2340                                }
2341                            });
2342                        }
2343                        (WrapperKind::VecDeque, Some(inner_ty)) => {
2344                            tokens.extend(quote! {
2345                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2346                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2347                                }
2348                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2349                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.front())
2350                                }
2351                            });
2352                        }
2353                        (WrapperKind::LinkedList, Some(inner_ty)) => {
2354                            tokens.extend(quote! {
2355                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2356                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2357                                }
2358                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2359                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.front())
2360                                }
2361                            });
2362                        }
2363                        (WrapperKind::BinaryHeap, Some(inner_ty)) => {
2364                            tokens.extend(quote! {
2365                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2366                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2367                                }
2368                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2369                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| s.#idx_lit.peek())
2370                                }
2371                            });
2372                        }
2373                        (WrapperKind::None, None) => {
2374                            tokens.extend(quote! {
2375                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2376                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2377                                }
2378                                pub fn #fr_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2379                                    key_paths_core::KeyPaths::failable_readable(|s: &#name| Some(&s.#idx_lit))
2380                                }
2381                            });
2382                        }
2383                        _ => {
2384                            tokens.extend(quote! {
2385                                pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #ty> {
2386                                    key_paths_core::KeyPaths::readable(|s: &#name| &s.#idx_lit)
2387                                }
2388                            });
2389                        }
2390                    }
2391                }
2392                tokens
2393            }
2394            _ => quote! {
2395                compile_error!("ReadableKeypaths derive supports only structs with named or unnamed fields");
2396            },
2397        },
2398        _ => quote! {
2399            compile_error!("ReadableKeypaths derive supports only structs");
2400        },
2401    };
2402
2403    let expanded = quote! {
2404        impl #name {
2405            #methods
2406        }
2407    };
2408
2409    TokenStream::from(expanded)
2410}
2411
2412#[proc_macro_derive(Casepaths)]
2413pub fn derive_casepaths(input: TokenStream) -> TokenStream {
2414    let input = parse_macro_input!(input as DeriveInput);
2415    let name = input.ident;
2416
2417    let tokens = match input.data {
2418        Data::Enum(data_enum) => {
2419            let mut tokens = proc_macro2::TokenStream::new();
2420            for variant in data_enum.variants.iter() {
2421                let v_ident = &variant.ident;
2422                let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
2423                let r_fn = format_ident!("{}_case_r", snake);
2424                let w_fn = format_ident!("{}_case_w", snake);
2425
2426                match &variant.fields {
2427                    Fields::Unit => {
2428                        tokens.extend(quote! {
2429                            pub fn #r_fn() -> key_paths_core::KeyPaths<#name, ()> {
2430                                static UNIT: () = ();
2431                                key_paths_core::KeyPaths::readable_enum(
2432                                    |_| #name::#v_ident,
2433                                    |e: &#name| match e { #name::#v_ident => Some(&UNIT), _ => None }
2434                                )
2435                            }
2436                        });
2437                    }
2438                    Fields::Unnamed(unnamed) if unnamed.unnamed.len() == 1 => {
2439                        let inner_ty = &unnamed.unnamed.first().unwrap().ty;
2440                        tokens.extend(quote! {
2441                            pub fn #r_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2442                                key_paths_core::KeyPaths::readable_enum(
2443                                    #name::#v_ident,
2444                                    |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None }
2445                                )
2446                            }
2447                            pub fn #w_fn() -> key_paths_core::KeyPaths<#name, #inner_ty> {
2448                                key_paths_core::KeyPaths::writable_enum(
2449                                    #name::#v_ident,
2450                                    |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None },
2451                                    |e: &mut #name| match e { #name::#v_ident(v) => Some(v), _ => None },
2452                                )
2453                            }
2454                        });
2455                    }
2456                    _ => {
2457                        tokens.extend(quote! {
2458                            compile_error!("Casepaths derive supports only unit and single-field tuple variants");
2459                        });
2460                    }
2461                }
2462            }
2463            tokens
2464        }
2465        _ => quote! { compile_error!("Casepaths can only be derived for enums"); },
2466    };
2467
2468    let expanded = quote! {
2469        impl #name {
2470            #tokens
2471        }
2472    };
2473
2474    TokenStream::from(expanded)
2475}