keypaths_proc/lib.rs
1use proc_macro::TokenStream;
2use quote::{format_ident, quote};
3use syn::{Data, DeriveInput, Fields, Type, Attribute, parse_macro_input, spanned::Spanned};
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 // Error handling containers
21 Result,
22 // Synchronization primitives
23 Mutex,
24 RwLock,
25 // Reference counting with weak references
26 Weak,
27 // String types (currently unused)
28 // String,
29 // OsString,
30 // PathBuf,
31 // Nested container support
32 OptionBox,
33 OptionRc,
34 OptionArc,
35 BoxOption,
36 RcOption,
37 ArcOption,
38 VecOption,
39 OptionVec,
40 HashMapOption,
41 OptionHashMap,
42 // Arc with synchronization primitives
43 ArcMutex,
44 ArcRwLock,
45 // Tagged types
46 Tagged,
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50enum MethodScope {
51 All,
52 Readable,
53 Writable,
54 Owned,
55}
56
57impl MethodScope {
58 fn includes_read(self) -> bool {
59 matches!(self, MethodScope::All | MethodScope::Readable)
60 }
61
62 fn includes_write(self) -> bool {
63 matches!(self, MethodScope::All | MethodScope::Writable)
64 }
65
66 fn includes_owned(self) -> bool {
67 matches!(self, MethodScope::All | MethodScope::Owned)
68 }
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72enum MethodKind {
73 Readable,
74 Writable,
75 Owned,
76}
77
78fn push_method(
79 target: &mut proc_macro2::TokenStream,
80 scope: MethodScope,
81 kind: MethodKind,
82 method_tokens: proc_macro2::TokenStream,
83) {
84 let include = match kind {
85 MethodKind::Readable => scope.includes_read(),
86 MethodKind::Writable => scope.includes_write(),
87 MethodKind::Owned => scope.includes_owned(),
88 };
89
90 if include {
91 target.extend(method_tokens);
92 }
93}
94
95fn method_scope_from_attrs(attrs: &[Attribute]) -> syn::Result<Option<MethodScope>> {
96 let mut scope: Option<MethodScope> = None;
97 for attr in attrs {
98 if attr.path().is_ident("Readable") {
99 if scope.is_some() {
100 return Err(syn::Error::new(attr.span(), "Only one of #[All], #[Readable], #[Writable], or #[Owned] may be used per field or variant"));
101 }
102 scope = Some(MethodScope::Readable);
103 } else if attr.path().is_ident("Writable") {
104 if scope.is_some() {
105 return Err(syn::Error::new(attr.span(), "Only one of #[All], #[Readable], #[Writable], or #[Owned] may be used per field or variant"));
106 }
107 scope = Some(MethodScope::Writable);
108 } else if attr.path().is_ident("Owned") {
109 if scope.is_some() {
110 return Err(syn::Error::new(attr.span(), "Only one of #[All], #[Readable], #[Writable], or #[Owned] may be used per field or variant"));
111 }
112 scope = Some(MethodScope::Owned);
113 } else if attr.path().is_ident("All") {
114 if scope.is_some() {
115 return Err(syn::Error::new(attr.span(), "Only one of #[All], #[Readable], #[Writable], or #[Owned] may be used per field or variant"));
116 }
117 scope = Some(MethodScope::All);
118 }
119 }
120 Ok(scope)
121}
122
123#[proc_macro_derive(Keypaths, attributes(Readable, Writable, Owned, All))]
124pub fn derive_keypaths(input: TokenStream) -> TokenStream {
125 let input = parse_macro_input!(input as DeriveInput);
126 let name = input.ident;
127
128 let default_scope = match method_scope_from_attrs(&input.attrs) {
129 Ok(Some(scope)) => scope,
130 Ok(None) => MethodScope::Readable,
131 Err(err) => return err.to_compile_error().into(),
132 };
133
134 let methods = match input.data {
135 Data::Struct(data_struct) => match data_struct.fields {
136 Fields::Named(fields_named) => {/**/
137 let mut tokens = proc_macro2::TokenStream::new();
138 for field in fields_named.named.iter() {
139 let field_ident = field.ident.as_ref().unwrap();
140 let ty = &field.ty;
141
142 let r_fn = format_ident!("{}_r", field_ident);
143 let w_fn = format_ident!("{}_w", field_ident);
144 let fr_fn = format_ident!("{}_fr", field_ident);
145 let fw_fn = format_ident!("{}_fw", field_ident);
146 let fr_at_fn = format_ident!("{}_fr_at", field_ident);
147 let fw_at_fn = format_ident!("{}_fw_at", field_ident);
148 // Owned keypath method names
149 let o_fn = format_ident!("{}_o", field_ident);
150 let fo_fn = format_ident!("{}_fo", field_ident);
151
152 let method_scope = match method_scope_from_attrs(&field.attrs) {
153 Ok(Some(scope)) => scope,
154 Ok(None) => default_scope,
155 Err(err) => return err.to_compile_error().into(),
156 };
157
158 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
159
160 match (kind, inner_ty.clone()) {
161 (WrapperKind::Option, Some(inner_ty)) => {
162 push_method(
163 &mut tokens,
164 method_scope,
165 MethodKind::Readable,
166 quote! {
167 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
168 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
169 }
170 },
171 );
172 let inner_ty_read = inner_ty.clone();
173 push_method(
174 &mut tokens,
175 method_scope,
176 MethodKind::Readable,
177 quote! {
178 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_read, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_read>> {
179 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref())
180 }
181 },
182 );
183 push_method(
184 &mut tokens,
185 method_scope,
186 MethodKind::Writable,
187 quote! {
188 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
189 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
190 }
191 },
192 );
193 let inner_ty_write = inner_ty.clone();
194 push_method(
195 &mut tokens,
196 method_scope,
197 MethodKind::Writable,
198 quote! {
199 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_write, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_write>> {
200 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.as_mut())
201 }
202 },
203 );
204 push_method(
205 &mut tokens,
206 method_scope,
207 MethodKind::Owned,
208 quote! {
209 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
210 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
211 }
212 },
213 );
214 // For Option fields, fo_fn() returns OptionalKeyPath that unwraps the Option
215 let inner_ty_owned = inner_ty.clone();
216 push_method(
217 &mut tokens,
218 method_scope,
219 MethodKind::Owned,
220 quote! {
221 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_owned, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_owned>> {
222 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref())
223 }
224 },
225 );
226 }
227 (WrapperKind::Vec, Some(inner_ty)) => {
228 let inner_ty_fr_at = inner_ty.clone();
229 push_method(
230 &mut tokens,
231 method_scope,
232 MethodKind::Readable,
233 quote! {
234 pub fn #fr_at_fn(index: usize) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr_at, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr_at>> {
235 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(index))
236 }
237 },
238 );
239 push_method(
240 &mut tokens,
241 method_scope,
242 MethodKind::Readable,
243 quote! {
244 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
245 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
246 }
247 },
248 );
249 let inner_ty_fr = inner_ty.clone();
250 push_method(
251 &mut tokens,
252 method_scope,
253 MethodKind::Readable,
254 quote! {
255 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
256 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.first())
257 }
258 },
259 );
260 let inner_ty_fw_at = inner_ty.clone();
261 push_method(
262 &mut tokens,
263 method_scope,
264 MethodKind::Writable,
265 quote! {
266 pub fn #fw_at_fn(index: usize) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw_at, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw_at>> {
267 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(index))
268 }
269 },
270 );
271 push_method(
272 &mut tokens,
273 method_scope,
274 MethodKind::Writable,
275 quote! {
276 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
277 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
278 }
279 },
280 );
281 let inner_ty_fw = inner_ty.clone();
282 push_method(
283 &mut tokens,
284 method_scope,
285 MethodKind::Writable,
286 quote! {
287 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
288 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.first_mut())
289 }
290 },
291 );
292 push_method(
293 &mut tokens,
294 method_scope,
295 MethodKind::Owned,
296 quote! {
297 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
298 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
299 }
300 },
301 );
302 let inner_ty_fo = inner_ty.clone();
303 push_method(
304 &mut tokens,
305 method_scope,
306 MethodKind::Owned,
307 quote! {
308 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
309 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.into_iter().next())
310 }
311 },
312 );
313 }
314 (WrapperKind::HashMap, Some(inner_ty)) => {
315 push_method(
316 &mut tokens,
317 method_scope,
318 MethodKind::Readable,
319 quote! {
320 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
321 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
322 }
323 },
324 );
325 let inner_ty_fr = inner_ty.clone();
326 push_method(
327 &mut tokens,
328 method_scope,
329 MethodKind::Readable,
330 quote! {
331 pub fn #fr_fn(key: String) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
332 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(&key))
333 }
334 },
335 );
336 let inner_ty_fr_at = inner_ty.clone();
337 push_method(
338 &mut tokens,
339 method_scope,
340 MethodKind::Readable,
341 quote! {
342 pub fn #fr_at_fn(key: String) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr_at, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr_at>> {
343 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(&key))
344 }
345 },
346 );
347 push_method(
348 &mut tokens,
349 method_scope,
350 MethodKind::Writable,
351 quote! {
352 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
353 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
354 }
355 },
356 );
357 let inner_ty_fw = inner_ty.clone();
358 push_method(
359 &mut tokens,
360 method_scope,
361 MethodKind::Writable,
362 quote! {
363 pub fn #fw_fn(key: String) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
364 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(&key))
365 }
366 },
367 );
368 let inner_ty_fw_at = inner_ty.clone();
369 push_method(
370 &mut tokens,
371 method_scope,
372 MethodKind::Writable,
373 quote! {
374 pub fn #fw_at_fn(key: String) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw_at, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw_at>> {
375 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(&key))
376 }
377 },
378 );
379 push_method(
380 &mut tokens,
381 method_scope,
382 MethodKind::Owned,
383 quote! {
384 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
385 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
386 }
387 },
388 );
389 let inner_ty_fo = inner_ty.clone();
390 push_method(
391 &mut tokens,
392 method_scope,
393 MethodKind::Owned,
394 quote! {
395 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
396 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.into_values().next())
397 }
398 },
399 );
400 }
401 (WrapperKind::Box, Some(inner_ty)) => {
402 push_method(
403 &mut tokens,
404 method_scope,
405 MethodKind::Readable,
406 quote! {
407 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
408 rust_keypaths::KeyPath::new(|s: &#name| &*s.#field_ident)
409 }
410 },
411 );
412 let inner_ty_fr = inner_ty.clone();
413 push_method(
414 &mut tokens,
415 method_scope,
416 MethodKind::Readable,
417 quote! {
418 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
419 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&*s.#field_ident))
420 }
421 },
422 );
423 push_method(
424 &mut tokens,
425 method_scope,
426 MethodKind::Writable,
427 quote! {
428 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
429 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut *s.#field_ident)
430 }
431 },
432 );
433 let inner_ty_fw = inner_ty.clone();
434 push_method(
435 &mut tokens,
436 method_scope,
437 MethodKind::Writable,
438 quote! {
439 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
440 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| Some(&mut *s.#field_ident))
441 }
442 },
443 );
444 push_method(
445 &mut tokens,
446 method_scope,
447 MethodKind::Owned,
448 quote! {
449 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
450 rust_keypaths::KeyPath::new(|s: &#name| *s.#field_ident)
451 }
452 },
453 );
454 let inner_ty_fo = inner_ty.clone();
455 push_method(
456 &mut tokens,
457 method_scope,
458 MethodKind::Owned,
459 quote! {
460 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
461 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(*s.#field_ident))
462 }
463 },
464 );
465 }
466 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
467 push_method(
468 &mut tokens,
469 method_scope,
470 MethodKind::Readable,
471 quote! {
472 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
473 rust_keypaths::KeyPath::new(|s: &#name| &*s.#field_ident)
474 }
475 },
476 );
477 let inner_ty_fr = inner_ty.clone();
478 push_method(
479 &mut tokens,
480 method_scope,
481 MethodKind::Readable,
482 quote! {
483 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
484 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&*s.#field_ident))
485 }
486 },
487 );
488 push_method(
489 &mut tokens,
490 method_scope,
491 MethodKind::Owned,
492 quote! {
493 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
494 rust_keypaths::KeyPath::new(|s: &#name| (*s.#field_ident).clone())
495 }
496 },
497 );
498 let inner_ty_fo = inner_ty.clone();
499 push_method(
500 &mut tokens,
501 method_scope,
502 MethodKind::Owned,
503 quote! {
504 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
505 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some((*s.#field_ident).clone()))
506 }
507 },
508 );
509 }
510 (WrapperKind::BTreeMap, Some(inner_ty)) => {
511 push_method(
512 &mut tokens,
513 method_scope,
514 MethodKind::Readable,
515 quote! {
516 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
517 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
518 }
519 },
520 );
521 push_method(
522 &mut tokens,
523 method_scope,
524 MethodKind::Writable,
525 quote! {
526 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
527 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
528 }
529 },
530 );
531 push_method(
532 &mut tokens,
533 method_scope,
534 MethodKind::Owned,
535 quote! {
536 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
537 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
538 }
539 },
540 );
541 let inner_ty_fo = inner_ty.clone();
542 push_method(
543 &mut tokens,
544 method_scope,
545 MethodKind::Owned,
546 quote! {
547 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
548 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.into_values().next())
549 }
550 },
551 );
552 // Note: Key-based access methods for BTreeMap require the exact key type
553 // For now, we'll skip generating these methods to avoid generic constraint issues
554 }
555 (WrapperKind::HashSet, Some(inner_ty)) => {
556 push_method(
557 &mut tokens,
558 method_scope,
559 MethodKind::Readable,
560 quote! {
561 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
562 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
563 }
564 },
565 );
566 let inner_ty_fr = inner_ty.clone();
567 push_method(
568 &mut tokens,
569 method_scope,
570 MethodKind::Readable,
571 quote! {
572 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
573 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.iter().next())
574 }
575 },
576 );
577 push_method(
578 &mut tokens,
579 method_scope,
580 MethodKind::Writable,
581 quote! {
582 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
583 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
584 }
585 },
586 );
587 push_method(
588 &mut tokens,
589 method_scope,
590 MethodKind::Owned,
591 quote! {
592 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
593 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
594 }
595 },
596 );
597 let inner_ty_fo = inner_ty.clone();
598 push_method(
599 &mut tokens,
600 method_scope,
601 MethodKind::Owned,
602 quote! {
603 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
604 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.into_iter().next())
605 }
606 },
607 );
608 }
609 (WrapperKind::BTreeSet, Some(inner_ty)) => {
610 push_method(
611 &mut tokens,
612 method_scope,
613 MethodKind::Readable,
614 quote! {
615 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
616 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
617 }
618 },
619 );
620 let inner_ty_fr = inner_ty.clone();
621 push_method(
622 &mut tokens,
623 method_scope,
624 MethodKind::Readable,
625 quote! {
626 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
627 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.iter().next())
628 }
629 },
630 );
631 push_method(
632 &mut tokens,
633 method_scope,
634 MethodKind::Writable,
635 quote! {
636 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
637 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
638 }
639 },
640 );
641 push_method(
642 &mut tokens,
643 method_scope,
644 MethodKind::Owned,
645 quote! {
646 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
647 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
648 }
649 },
650 );
651 let inner_ty_fo = inner_ty.clone();
652 push_method(
653 &mut tokens,
654 method_scope,
655 MethodKind::Owned,
656 quote! {
657 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
658 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.into_iter().next())
659 }
660 },
661 );
662 }
663 (WrapperKind::VecDeque, Some(inner_ty)) => {
664 push_method(
665 &mut tokens,
666 method_scope,
667 MethodKind::Readable,
668 quote! {
669 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
670 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
671 }
672 },
673 );
674 let inner_ty_fr = inner_ty.clone();
675 push_method(
676 &mut tokens,
677 method_scope,
678 MethodKind::Readable,
679 quote! {
680 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
681 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.front())
682 }
683 },
684 );
685 let inner_ty_fr_at = inner_ty.clone();
686 push_method(
687 &mut tokens,
688 method_scope,
689 MethodKind::Readable,
690 quote! {
691 pub fn #fr_at_fn(index: usize) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr_at, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr_at>> {
692 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(index))
693 }
694 },
695 );
696 push_method(
697 &mut tokens,
698 method_scope,
699 MethodKind::Writable,
700 quote! {
701 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
702 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
703 }
704 },
705 );
706 let inner_ty_fw = inner_ty.clone();
707 push_method(
708 &mut tokens,
709 method_scope,
710 MethodKind::Writable,
711 quote! {
712 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
713 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.front_mut())
714 }
715 },
716 );
717 let inner_ty_fw_at = inner_ty.clone();
718 push_method(
719 &mut tokens,
720 method_scope,
721 MethodKind::Writable,
722 quote! {
723 pub fn #fw_at_fn(index: usize) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw_at, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw_at>> {
724 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(index))
725 }
726 },
727 );
728 push_method(
729 &mut tokens,
730 method_scope,
731 MethodKind::Owned,
732 quote! {
733 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
734 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
735 }
736 },
737 );
738 let inner_ty_fo = inner_ty.clone();
739 push_method(
740 &mut tokens,
741 method_scope,
742 MethodKind::Owned,
743 quote! {
744 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
745 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.into_iter().next())
746 }
747 },
748 );
749 }
750 (WrapperKind::LinkedList, Some(inner_ty)) => {
751 push_method(
752 &mut tokens,
753 method_scope,
754 MethodKind::Readable,
755 quote! {
756 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
757 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
758 }
759 },
760 );
761 let inner_ty_fr = inner_ty.clone();
762 push_method(
763 &mut tokens,
764 method_scope,
765 MethodKind::Readable,
766 quote! {
767 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
768 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.front())
769 }
770 },
771 );
772 push_method(
773 &mut tokens,
774 method_scope,
775 MethodKind::Writable,
776 quote! {
777 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
778 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
779 }
780 },
781 );
782 let inner_ty_fw = inner_ty.clone();
783 push_method(
784 &mut tokens,
785 method_scope,
786 MethodKind::Writable,
787 quote! {
788 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
789 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.front_mut())
790 }
791 },
792 );
793 push_method(
794 &mut tokens,
795 method_scope,
796 MethodKind::Owned,
797 quote! {
798 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
799 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
800 }
801 },
802 );
803 let inner_ty_fo = inner_ty.clone();
804 push_method(
805 &mut tokens,
806 method_scope,
807 MethodKind::Owned,
808 quote! {
809 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
810 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.into_iter().next())
811 }
812 },
813 );
814 }
815 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
816 push_method(
817 &mut tokens,
818 method_scope,
819 MethodKind::Readable,
820 quote! {
821 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
822 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
823 }
824 },
825 );
826 push_method(
827 &mut tokens,
828 method_scope,
829 MethodKind::Writable,
830 quote! {
831 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
832 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
833 }
834 },
835 );
836 push_method(
837 &mut tokens,
838 method_scope,
839 MethodKind::Owned,
840 quote! {
841 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
842 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
843 }
844 },
845 );
846 let inner_ty_fo = inner_ty.clone();
847 push_method(
848 &mut tokens,
849 method_scope,
850 MethodKind::Owned,
851 quote! {
852 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
853 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.into_iter().next())
854 }
855 },
856 );
857 // Note: BinaryHeap peek() returns &T, but we need &inner_ty
858 // For now, we'll skip failable methods for BinaryHeap to avoid type issues
859 }
860 (WrapperKind::Result, Some(inner_ty)) => {
861 push_method(
862 &mut tokens,
863 method_scope,
864 MethodKind::Readable,
865 quote! {
866 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
867 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
868 }
869 },
870 );
871 let inner_ty_fr = inner_ty.clone();
872 push_method(
873 &mut tokens,
874 method_scope,
875 MethodKind::Readable,
876 quote! {
877 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
878 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref().ok())
879 }
880 },
881 );
882 push_method(
883 &mut tokens,
884 method_scope,
885 MethodKind::Writable,
886 quote! {
887 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
888 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
889 }
890 },
891 );
892 // Note: Result<T, E> doesn't support failable_writable for inner type
893 // Only providing container-level writable access
894 push_method(
895 &mut tokens,
896 method_scope,
897 MethodKind::Owned,
898 quote! {
899 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
900 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
901 }
902 },
903 );
904 let inner_ty_fo = inner_ty.clone();
905 push_method(
906 &mut tokens,
907 method_scope,
908 MethodKind::Owned,
909 quote! {
910 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
911 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.ok())
912 }
913 },
914 );
915 }
916 (WrapperKind::Mutex, Some(_inner_ty)) => {
917 push_method(
918 &mut tokens,
919 method_scope,
920 MethodKind::Readable,
921 quote! {
922 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
923 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
924 }
925 },
926 );
927 push_method(
928 &mut tokens,
929 method_scope,
930 MethodKind::Writable,
931 quote! {
932 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
933 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
934 }
935 },
936 );
937 // Note: Mutex<T> doesn't support direct access to inner type due to lifetime constraints
938 // Only providing container-level access
939 push_method(
940 &mut tokens,
941 method_scope,
942 MethodKind::Owned,
943 quote! {
944 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
945 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
946 }
947 },
948 );
949 }
950 (WrapperKind::RwLock, Some(_inner_ty)) => {
951 push_method(
952 &mut tokens,
953 method_scope,
954 MethodKind::Readable,
955 quote! {
956 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
957 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
958 }
959 },
960 );
961 push_method(
962 &mut tokens,
963 method_scope,
964 MethodKind::Writable,
965 quote! {
966 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
967 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
968 }
969 },
970 );
971 // Note: RwLock<T> doesn't support direct access to inner type due to lifetime constraints
972 // Only providing container-level access
973 push_method(
974 &mut tokens,
975 method_scope,
976 MethodKind::Owned,
977 quote! {
978 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
979 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
980 }
981 },
982 );
983 }
984 (WrapperKind::ArcMutex, Some(_inner_ty)) => {
985 push_method(
986 &mut tokens,
987 method_scope,
988 MethodKind::Readable,
989 quote! {
990 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
991 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
992 }
993 },
994 );
995 // Note: Arc<Mutex<T>> doesn't support writable access (Arc is immutable)
996 // Note: Arc<Mutex<T>> doesn't support direct access to inner type due to lifetime constraints
997 // Only providing container-level access
998 push_method(
999 &mut tokens,
1000 method_scope,
1001 MethodKind::Owned,
1002 quote! {
1003 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1004 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1005 }
1006 },
1007 );
1008 }
1009 (WrapperKind::ArcRwLock, Some(_inner_ty)) => {
1010 push_method(
1011 &mut tokens,
1012 method_scope,
1013 MethodKind::Readable,
1014 quote! {
1015 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1016 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1017 }
1018 },
1019 );
1020 // Note: Arc<RwLock<T>> doesn't support writable access (Arc is immutable)
1021 // Note: Arc<RwLock<T>> doesn't support direct access to inner type due to lifetime constraints
1022 // Only providing container-level access
1023 push_method(
1024 &mut tokens,
1025 method_scope,
1026 MethodKind::Owned,
1027 quote! {
1028 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1029 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1030 }
1031 },
1032 );
1033 }
1034 (WrapperKind::Weak, Some(_inner_ty)) => {
1035 push_method(
1036 &mut tokens,
1037 method_scope,
1038 MethodKind::Readable,
1039 quote! {
1040 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1041 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1042 }
1043 },
1044 );
1045 // Note: Weak<T> doesn't support writable access (it's immutable)
1046 // Note: Weak<T> doesn't support direct access to inner type due to lifetime constraints
1047 // Only providing container-level access
1048 push_method(
1049 &mut tokens,
1050 method_scope,
1051 MethodKind::Owned,
1052 quote! {
1053 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1054 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1055 }
1056 },
1057 );
1058 }
1059 // Nested container combinations
1060 (WrapperKind::OptionBox, Some(inner_ty)) => {
1061 push_method(
1062 &mut tokens,
1063 method_scope,
1064 MethodKind::Readable,
1065 quote! {
1066 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1067 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1068 }
1069 },
1070 );
1071 let inner_ty_fr = inner_ty.clone();
1072 push_method(
1073 &mut tokens,
1074 method_scope,
1075 MethodKind::Readable,
1076 quote! {
1077 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
1078 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref().map(|b| &**b))
1079 }
1080 },
1081 );
1082 push_method(
1083 &mut tokens,
1084 method_scope,
1085 MethodKind::Writable,
1086 quote! {
1087 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
1088 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
1089 }
1090 },
1091 );
1092 let inner_ty_fw = inner_ty.clone();
1093 push_method(
1094 &mut tokens,
1095 method_scope,
1096 MethodKind::Writable,
1097 quote! {
1098 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
1099 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.as_mut().map(|b| &mut **b))
1100 }
1101 },
1102 );
1103 push_method(
1104 &mut tokens,
1105 method_scope,
1106 MethodKind::Owned,
1107 quote! {
1108 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1109 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1110 }
1111 },
1112 );
1113 let inner_ty_fo = inner_ty.clone();
1114 push_method(
1115 &mut tokens,
1116 method_scope,
1117 MethodKind::Owned,
1118 quote! {
1119 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
1120 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.map(|b| *b))
1121 }
1122 },
1123 );
1124 }
1125 (WrapperKind::OptionRc, Some(inner_ty)) => {
1126 push_method(
1127 &mut tokens,
1128 method_scope,
1129 MethodKind::Readable,
1130 quote! {
1131 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1132 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1133 }
1134 },
1135 );
1136 let inner_ty_fr = inner_ty.clone();
1137 push_method(
1138 &mut tokens,
1139 method_scope,
1140 MethodKind::Readable,
1141 quote! {
1142 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
1143 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref().map(|r| &**r))
1144 }
1145 },
1146 );
1147 push_method(
1148 &mut tokens,
1149 method_scope,
1150 MethodKind::Owned,
1151 quote! {
1152 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1153 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1154 }
1155 },
1156 );
1157 let inner_ty_fo = inner_ty.clone();
1158 push_method(
1159 &mut tokens,
1160 method_scope,
1161 MethodKind::Owned,
1162 quote! {
1163 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
1164 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.map(|r| (*r).clone()))
1165 }
1166 },
1167 );
1168 }
1169 (WrapperKind::OptionArc, Some(inner_ty)) => {
1170 push_method(
1171 &mut tokens,
1172 method_scope,
1173 MethodKind::Readable,
1174 quote! {
1175 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1176 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1177 }
1178 },
1179 );
1180 let inner_ty_fr = inner_ty.clone();
1181 push_method(
1182 &mut tokens,
1183 method_scope,
1184 MethodKind::Readable,
1185 quote! {
1186 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
1187 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref().map(|a| &**a))
1188 }
1189 },
1190 );
1191 push_method(
1192 &mut tokens,
1193 method_scope,
1194 MethodKind::Owned,
1195 quote! {
1196 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1197 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1198 }
1199 },
1200 );
1201 let inner_ty_fo = inner_ty.clone();
1202 push_method(
1203 &mut tokens,
1204 method_scope,
1205 MethodKind::Owned,
1206 quote! {
1207 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
1208 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.map(|a| (*a).clone()))
1209 }
1210 },
1211 );
1212 }
1213 (WrapperKind::BoxOption, Some(inner_ty)) => {
1214 let inner_ty_fr = inner_ty.clone();
1215 push_method(
1216 &mut tokens,
1217 method_scope,
1218 MethodKind::Readable,
1219 quote! {
1220 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
1221 rust_keypaths::OptionalKeyPath::new(|s: &#name| (*s.#field_ident).as_ref())
1222 }
1223 },
1224 );
1225 let inner_ty_fw = inner_ty.clone();
1226 push_method(
1227 &mut tokens,
1228 method_scope,
1229 MethodKind::Writable,
1230 quote! {
1231 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
1232 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| (*s.#field_ident).as_mut())
1233 }
1234 },
1235 );
1236 }
1237 (WrapperKind::RcOption, Some(inner_ty)) => {
1238 let inner_ty_fr = inner_ty.clone();
1239 push_method(
1240 &mut tokens,
1241 method_scope,
1242 MethodKind::Readable,
1243 quote! {
1244 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
1245 rust_keypaths::OptionalKeyPath::new(|s: &#name| (*s.#field_ident).as_ref())
1246 }
1247 },
1248 );
1249 }
1250 (WrapperKind::ArcOption, Some(inner_ty)) => {
1251 let inner_ty_fr = inner_ty.clone();
1252 push_method(
1253 &mut tokens,
1254 method_scope,
1255 MethodKind::Readable,
1256 quote! {
1257 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
1258 rust_keypaths::OptionalKeyPath::new(|s: &#name| (*s.#field_ident).as_ref())
1259 }
1260 },
1261 );
1262 }
1263 (WrapperKind::VecOption, Some(inner_ty)) => {
1264 push_method(
1265 &mut tokens,
1266 method_scope,
1267 MethodKind::Readable,
1268 quote! {
1269 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1270 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1271 }
1272 },
1273 );
1274 let inner_ty_fr = inner_ty.clone();
1275 push_method(
1276 &mut tokens,
1277 method_scope,
1278 MethodKind::Readable,
1279 quote! {
1280 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
1281 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.first().and_then(|opt| opt.as_ref()))
1282 }
1283 },
1284 );
1285 let inner_ty_fr_at = inner_ty.clone();
1286 push_method(
1287 &mut tokens,
1288 method_scope,
1289 MethodKind::Readable,
1290 quote! {
1291 pub fn #fr_at_fn(index: usize) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr_at, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr_at>> {
1292 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(index).and_then(|opt| opt.as_ref()))
1293 }
1294 },
1295 );
1296 push_method(
1297 &mut tokens,
1298 method_scope,
1299 MethodKind::Writable,
1300 quote! {
1301 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
1302 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
1303 }
1304 },
1305 );
1306 let inner_ty_fw = inner_ty.clone();
1307 push_method(
1308 &mut tokens,
1309 method_scope,
1310 MethodKind::Writable,
1311 quote! {
1312 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
1313 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.first_mut().and_then(|opt| opt.as_mut()))
1314 }
1315 },
1316 );
1317 let inner_ty_fw_at = inner_ty.clone();
1318 push_method(
1319 &mut tokens,
1320 method_scope,
1321 MethodKind::Writable,
1322 quote! {
1323 pub fn #fw_at_fn(index: usize) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw_at, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw_at>> {
1324 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(index).and_then(|opt| opt.as_mut()))
1325 }
1326 },
1327 );
1328 push_method(
1329 &mut tokens,
1330 method_scope,
1331 MethodKind::Owned,
1332 quote! {
1333 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1334 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1335 }
1336 },
1337 );
1338 let inner_ty_fo = inner_ty.clone();
1339 push_method(
1340 &mut tokens,
1341 method_scope,
1342 MethodKind::Owned,
1343 quote! {
1344 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
1345 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.into_iter().flatten().next())
1346 }
1347 },
1348 );
1349 }
1350 (WrapperKind::OptionVec, Some(inner_ty)) => {
1351 push_method(
1352 &mut tokens,
1353 method_scope,
1354 MethodKind::Readable,
1355 quote! {
1356 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1357 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1358 }
1359 },
1360 );
1361 let inner_ty_fr = inner_ty.clone();
1362 push_method(
1363 &mut tokens,
1364 method_scope,
1365 MethodKind::Readable,
1366 quote! {
1367 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
1368 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref().and_then(|v| v.first()))
1369 }
1370 },
1371 );
1372 let inner_ty_fr_at = inner_ty.clone();
1373 push_method(
1374 &mut tokens,
1375 method_scope,
1376 MethodKind::Readable,
1377 quote! {
1378 pub fn #fr_at_fn(index: usize) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr_at, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr_at>> {
1379 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.as_ref().and_then(|v| v.get(index)))
1380 }
1381 },
1382 );
1383 push_method(
1384 &mut tokens,
1385 method_scope,
1386 MethodKind::Writable,
1387 quote! {
1388 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
1389 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
1390 }
1391 },
1392 );
1393 let inner_ty_fw = inner_ty.clone();
1394 push_method(
1395 &mut tokens,
1396 method_scope,
1397 MethodKind::Writable,
1398 quote! {
1399 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
1400 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.as_mut().and_then(|v| v.first_mut()))
1401 }
1402 },
1403 );
1404 let inner_ty_fw_at = inner_ty.clone();
1405 push_method(
1406 &mut tokens,
1407 method_scope,
1408 MethodKind::Writable,
1409 quote! {
1410 pub fn #fw_at_fn(index: usize) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw_at, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw_at>> {
1411 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.as_mut().and_then(|v| v.get_mut(index)))
1412 }
1413 },
1414 );
1415 push_method(
1416 &mut tokens,
1417 method_scope,
1418 MethodKind::Owned,
1419 quote! {
1420 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1421 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1422 }
1423 },
1424 );
1425 let inner_ty_fo = inner_ty.clone();
1426 push_method(
1427 &mut tokens,
1428 method_scope,
1429 MethodKind::Owned,
1430 quote! {
1431 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
1432 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.and_then(|v| v.into_iter().next()))
1433 }
1434 },
1435 );
1436 }
1437 (WrapperKind::HashMapOption, Some(inner_ty)) => {
1438 push_method(
1439 &mut tokens,
1440 method_scope,
1441 MethodKind::Readable,
1442 quote! {
1443 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1444 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1445 }
1446 },
1447 );
1448 let inner_ty_fr = inner_ty.clone();
1449 push_method(
1450 &mut tokens,
1451 method_scope,
1452 MethodKind::Readable,
1453 quote! {
1454 pub fn #fr_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
1455 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(&key).and_then(|opt| opt.as_ref()))
1456 }
1457 },
1458 );
1459 let inner_ty_fr_at = inner_ty.clone();
1460 push_method(
1461 &mut tokens,
1462 method_scope,
1463 MethodKind::Readable,
1464 quote! {
1465 pub fn #fr_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr_at, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr_at>> {
1466 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(&key).and_then(|opt| opt.as_ref()))
1467 }
1468 },
1469 );
1470 push_method(
1471 &mut tokens,
1472 method_scope,
1473 MethodKind::Writable,
1474 quote! {
1475 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
1476 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
1477 }
1478 },
1479 );
1480 let inner_ty_fw = inner_ty.clone();
1481 push_method(
1482 &mut tokens,
1483 method_scope,
1484 MethodKind::Writable,
1485 quote! {
1486 pub fn #fw_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
1487 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(&key).and_then(|opt| opt.as_mut()))
1488 }
1489 },
1490 );
1491 let inner_ty_fw_at = inner_ty.clone();
1492 push_method(
1493 &mut tokens,
1494 method_scope,
1495 MethodKind::Writable,
1496 quote! {
1497 pub fn #fw_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw_at, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw_at>> {
1498 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(&key).and_then(|opt| opt.as_mut()))
1499 }
1500 },
1501 );
1502 push_method(
1503 &mut tokens,
1504 method_scope,
1505 MethodKind::Owned,
1506 quote! {
1507 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1508 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1509 }
1510 },
1511 );
1512 let inner_ty_fo = inner_ty.clone();
1513 push_method(
1514 &mut tokens,
1515 method_scope,
1516 MethodKind::Owned,
1517 quote! {
1518 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
1519 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.into_values().flatten().next())
1520 }
1521 },
1522 );
1523 }
1524 (WrapperKind::OptionHashMap, Some(inner_ty)) => {
1525 push_method(
1526 &mut tokens,
1527 method_scope,
1528 MethodKind::Readable,
1529 quote! {
1530 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1531 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1532 }
1533 },
1534 );
1535 let inner_ty_fr = inner_ty.clone();
1536 push_method(
1537 &mut tokens,
1538 method_scope,
1539 MethodKind::Readable,
1540 quote! {
1541 pub fn #fr_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
1542 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.as_ref().and_then(|m| m.get(&key)))
1543 }
1544 },
1545 );
1546 let inner_ty_fr_at = inner_ty.clone();
1547 push_method(
1548 &mut tokens,
1549 method_scope,
1550 MethodKind::Readable,
1551 quote! {
1552 pub fn #fr_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr_at, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr_at>> {
1553 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.as_ref().and_then(|m| m.get(&key)))
1554 }
1555 },
1556 );
1557 push_method(
1558 &mut tokens,
1559 method_scope,
1560 MethodKind::Writable,
1561 quote! {
1562 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
1563 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
1564 }
1565 },
1566 );
1567 let inner_ty_fw = inner_ty.clone();
1568 push_method(
1569 &mut tokens,
1570 method_scope,
1571 MethodKind::Writable,
1572 quote! {
1573 pub fn #fw_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
1574 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.as_mut().and_then(|m| m.get_mut(&key)))
1575 }
1576 },
1577 );
1578 let inner_ty_fw_at = inner_ty.clone();
1579 push_method(
1580 &mut tokens,
1581 method_scope,
1582 MethodKind::Writable,
1583 quote! {
1584 pub fn #fw_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw_at, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw_at>> {
1585 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.as_mut().and_then(|m| m.get_mut(&key)))
1586 }
1587 },
1588 );
1589 push_method(
1590 &mut tokens,
1591 method_scope,
1592 MethodKind::Owned,
1593 quote! {
1594 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1595 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1596 }
1597 },
1598 );
1599 let inner_ty_fo = inner_ty.clone();
1600 push_method(
1601 &mut tokens,
1602 method_scope,
1603 MethodKind::Owned,
1604 quote! {
1605 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
1606 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.and_then(|m| m.into_values().next()))
1607 }
1608 },
1609 );
1610 }
1611 (WrapperKind::None, None) => {
1612 push_method(
1613 &mut tokens,
1614 method_scope,
1615 MethodKind::Readable,
1616 quote! {
1617 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1618 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1619 }
1620 },
1621 );
1622 push_method(
1623 &mut tokens,
1624 method_scope,
1625 MethodKind::Readable,
1626 quote! {
1627 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
1628 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&s.#field_ident))
1629 }
1630 },
1631 );
1632 push_method(
1633 &mut tokens,
1634 method_scope,
1635 MethodKind::Writable,
1636 quote! {
1637 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
1638 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
1639 }
1640 },
1641 );
1642 push_method(
1643 &mut tokens,
1644 method_scope,
1645 MethodKind::Writable,
1646 quote! {
1647 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #ty>> {
1648 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| Some(&mut s.#field_ident))
1649 }
1650 },
1651 );
1652 push_method(
1653 &mut tokens,
1654 method_scope,
1655 MethodKind::Owned,
1656 quote! {
1657 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1658 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1659 }
1660 },
1661 );
1662 push_method(
1663 &mut tokens,
1664 method_scope,
1665 MethodKind::Owned,
1666 quote! {
1667 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
1668 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&s.#field_ident))
1669 }
1670 },
1671 );
1672 }
1673 _ => {
1674 push_method(
1675 &mut tokens,
1676 method_scope,
1677 MethodKind::Readable,
1678 quote! {
1679 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1680 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1681 }
1682 },
1683 );
1684 push_method(
1685 &mut tokens,
1686 method_scope,
1687 MethodKind::Writable,
1688 quote! {
1689 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
1690 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
1691 }
1692 },
1693 );
1694 push_method(
1695 &mut tokens,
1696 method_scope,
1697 MethodKind::Owned,
1698 quote! {
1699 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1700 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
1701 }
1702 },
1703 );
1704 }
1705 }
1706 }
1707 tokens
1708 }
1709 Fields::Unnamed(unnamed) => {
1710 let mut tokens = proc_macro2::TokenStream::new();
1711 for (idx, field) in unnamed.unnamed.iter().enumerate() {
1712 let idx_lit = syn::Index::from(idx);
1713 let ty = &field.ty;
1714
1715 let r_fn = format_ident!("f{}_r", idx);
1716 let w_fn = format_ident!("f{}_w", idx);
1717 let fr_fn = format_ident!("f{}_fr", idx);
1718 let fw_fn = format_ident!("f{}_fw", idx);
1719 let fr_at_fn = format_ident!("f{}_fr_at", idx);
1720 let fw_at_fn = format_ident!("f{}_fw_at", idx);
1721 // Owned keypath method names
1722 let o_fn = format_ident!("f{}_o", idx);
1723 let fo_fn = format_ident!("f{}_fo", idx);
1724
1725 let method_scope = match method_scope_from_attrs(&field.attrs) {
1726 Ok(Some(scope)) => scope,
1727 Ok(None) => default_scope,
1728 Err(err) => return err.to_compile_error().into(),
1729 };
1730
1731 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
1732
1733 match (kind, inner_ty.clone()) {
1734 (WrapperKind::Option, Some(inner_ty)) => {
1735 push_method(
1736 &mut tokens,
1737 method_scope,
1738 MethodKind::Readable,
1739 quote! {
1740 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1741 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
1742 }
1743 },
1744 );
1745 push_method(
1746 &mut tokens,
1747 method_scope,
1748 MethodKind::Writable,
1749 quote! {
1750 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
1751 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
1752 }
1753 },
1754 );
1755 let inner_ty_fr = inner_ty.clone();
1756 push_method(
1757 &mut tokens,
1758 method_scope,
1759 MethodKind::Readable,
1760 quote! {
1761 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
1762 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.as_ref())
1763 }
1764 },
1765 );
1766 let inner_ty_fw = inner_ty.clone();
1767 push_method(
1768 &mut tokens,
1769 method_scope,
1770 MethodKind::Writable,
1771 quote! {
1772 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
1773 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.as_mut())
1774 }
1775 },
1776 );
1777 push_method(
1778 &mut tokens,
1779 method_scope,
1780 MethodKind::Owned,
1781 quote! {
1782 // Owned keypath methods
1783 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1784 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
1785 }
1786 },
1787 );
1788 let inner_ty_fo = inner_ty.clone();
1789 push_method(
1790 &mut tokens,
1791 method_scope,
1792 MethodKind::Owned,
1793 quote! {
1794 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
1795 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit)
1796 }
1797 },
1798 );
1799 }
1800 (WrapperKind::Vec, Some(inner_ty)) => {
1801 push_method(
1802 &mut tokens,
1803 method_scope,
1804 MethodKind::Readable,
1805 quote! {
1806 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1807 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
1808 }
1809 },
1810 );
1811 push_method(
1812 &mut tokens,
1813 method_scope,
1814 MethodKind::Writable,
1815 quote! {
1816 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
1817 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
1818 }
1819 },
1820 );
1821 let inner_ty_fr = inner_ty.clone();
1822 push_method(
1823 &mut tokens,
1824 method_scope,
1825 MethodKind::Readable,
1826 quote! {
1827 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
1828 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.first())
1829 }
1830 },
1831 );
1832 let inner_ty_fw = inner_ty.clone();
1833 push_method(
1834 &mut tokens,
1835 method_scope,
1836 MethodKind::Writable,
1837 quote! {
1838 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
1839 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.first_mut())
1840 }
1841 },
1842 );
1843 let inner_ty_fr_at = inner_ty.clone();
1844 push_method(
1845 &mut tokens,
1846 method_scope,
1847 MethodKind::Readable,
1848 quote! {
1849 pub fn #fr_at_fn(index: &'static usize) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr_at, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr_at>> {
1850 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.get(*index))
1851 }
1852 },
1853 );
1854 let inner_ty_fw_at = inner_ty.clone();
1855 push_method(
1856 &mut tokens,
1857 method_scope,
1858 MethodKind::Writable,
1859 quote! {
1860 pub fn #fw_at_fn(index: &'static usize) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw_at, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw_at>> {
1861 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.get_mut(*index))
1862 }
1863 },
1864 );
1865 push_method(
1866 &mut tokens,
1867 method_scope,
1868 MethodKind::Owned,
1869 quote! {
1870 // Owned keypath methods
1871 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1872 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
1873 }
1874 },
1875 );
1876 let inner_ty_fo = inner_ty.clone();
1877 push_method(
1878 &mut tokens,
1879 method_scope,
1880 MethodKind::Owned,
1881 quote! {
1882 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
1883 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.into_iter().next())
1884 }
1885 },
1886 );
1887 }
1888 (WrapperKind::HashMap, Some(inner_ty)) => {
1889 push_method(
1890 &mut tokens,
1891 method_scope,
1892 MethodKind::Readable,
1893 quote! {
1894 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1895 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
1896 }
1897 },
1898 );
1899 push_method(
1900 &mut tokens,
1901 method_scope,
1902 MethodKind::Writable,
1903 quote! {
1904 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
1905 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
1906 }
1907 },
1908 );
1909 let inner_ty_fr = inner_ty.clone();
1910 push_method(
1911 &mut tokens,
1912 method_scope,
1913 MethodKind::Readable,
1914 quote! {
1915 pub fn #fr_fn(key: String) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
1916 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#idx_lit.get(&key))
1917 }
1918 },
1919 );
1920 let inner_ty_fw = inner_ty.clone();
1921 push_method(
1922 &mut tokens,
1923 method_scope,
1924 MethodKind::Writable,
1925 quote! {
1926 pub fn #fw_fn(key: String) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
1927 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#idx_lit.get_mut(&key))
1928 }
1929 },
1930 );
1931 let inner_ty_fr_at = inner_ty.clone();
1932 push_method(
1933 &mut tokens,
1934 method_scope,
1935 MethodKind::Readable,
1936 quote! {
1937 pub fn #fr_at_fn(key: String) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr_at, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr_at>> {
1938 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#idx_lit.get(&key))
1939 }
1940 },
1941 );
1942 let inner_ty_fw_at = inner_ty.clone();
1943 push_method(
1944 &mut tokens,
1945 method_scope,
1946 MethodKind::Writable,
1947 quote! {
1948 pub fn #fw_at_fn(key: String) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw_at, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw_at>> {
1949 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#idx_lit.get_mut(&key))
1950 }
1951 },
1952 );
1953 push_method(
1954 &mut tokens,
1955 method_scope,
1956 MethodKind::Owned,
1957 quote! {
1958 // Owned keypath methods
1959 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
1960 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
1961 }
1962 },
1963 );
1964 let inner_ty_fo = inner_ty.clone();
1965 push_method(
1966 &mut tokens,
1967 method_scope,
1968 MethodKind::Owned,
1969 quote! {
1970 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
1971 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.into_values().next())
1972 }
1973 },
1974 );
1975 }
1976 (WrapperKind::Box, Some(inner_ty)) => {
1977 let inner_ty_read = inner_ty.clone();
1978 push_method(
1979 &mut tokens,
1980 method_scope,
1981 MethodKind::Readable,
1982 quote! {
1983 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty_read, impl for<'r> Fn(&'r #name) -> &'r #inner_ty_read> {
1984 rust_keypaths::KeyPath::new(|s: &#name| &*s.#idx_lit)
1985 }
1986 },
1987 );
1988 let inner_ty_write = inner_ty.clone();
1989 push_method(
1990 &mut tokens,
1991 method_scope,
1992 MethodKind::Writable,
1993 quote! {
1994 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty_write, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty_write> {
1995 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut *s.#idx_lit)
1996 }
1997 },
1998 );
1999 let inner_ty_fr = inner_ty.clone();
2000 push_method(
2001 &mut tokens,
2002 method_scope,
2003 MethodKind::Readable,
2004 quote! {
2005 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
2006 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&*s.#idx_lit))
2007 }
2008 },
2009 );
2010 let inner_ty_fw = inner_ty.clone();
2011 push_method(
2012 &mut tokens,
2013 method_scope,
2014 MethodKind::Writable,
2015 quote! {
2016 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
2017 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| Some(&mut *s.#idx_lit))
2018 }
2019 },
2020 );
2021 let inner_ty_owned = inner_ty.clone();
2022 push_method(
2023 &mut tokens,
2024 method_scope,
2025 MethodKind::Owned,
2026 quote! {
2027 // Owned keypath methods
2028 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #inner_ty_owned, impl for<'r> Fn(&'r #name) -> &'r #inner_ty_owned> {
2029 rust_keypaths::KeyPath::new(|s: &#name| *s.#idx_lit)
2030 }
2031 },
2032 );
2033 let inner_ty_fo = inner_ty.clone();
2034 push_method(
2035 &mut tokens,
2036 method_scope,
2037 MethodKind::Owned,
2038 quote! {
2039 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
2040 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(*s.#idx_lit))
2041 }
2042 },
2043 );
2044 }
2045 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
2046 let inner_ty_read = inner_ty.clone();
2047 push_method(
2048 &mut tokens,
2049 method_scope,
2050 MethodKind::Readable,
2051 quote! {
2052 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty_read, impl for<'r> Fn(&'r #name) -> &'r #inner_ty_read> {
2053 rust_keypaths::KeyPath::new(|s: &#name| &*s.#idx_lit)
2054 }
2055 },
2056 );
2057 let inner_ty_fr = inner_ty.clone();
2058 push_method(
2059 &mut tokens,
2060 method_scope,
2061 MethodKind::Readable,
2062 quote! {
2063 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
2064 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&*s.#idx_lit))
2065 }
2066 },
2067 );
2068 let inner_ty_owned = inner_ty.clone();
2069 push_method(
2070 &mut tokens,
2071 method_scope,
2072 MethodKind::Owned,
2073 quote! {
2074 // Owned keypath methods
2075 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #inner_ty_owned, impl for<'r> Fn(&'r #name) -> &'r #inner_ty_owned> {
2076 rust_keypaths::KeyPath::new(|s: &#name| (*s.#idx_lit).clone())
2077 }
2078 },
2079 );
2080 let inner_ty_fo = inner_ty.clone();
2081 push_method(
2082 &mut tokens,
2083 method_scope,
2084 MethodKind::Owned,
2085 quote! {
2086 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
2087 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some((*s.#idx_lit).clone()))
2088 }
2089 },
2090 );
2091 }
2092 (WrapperKind::BTreeMap, Some(inner_ty)) => {
2093 push_method(
2094 &mut tokens,
2095 method_scope,
2096 MethodKind::Readable,
2097 quote! {
2098 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2099 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2100 }
2101 },
2102 );
2103 push_method(
2104 &mut tokens,
2105 method_scope,
2106 MethodKind::Writable,
2107 quote! {
2108 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2109 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2110 }
2111 },
2112 );
2113 push_method(
2114 &mut tokens,
2115 method_scope,
2116 MethodKind::Owned,
2117 quote! {
2118 // Owned keypath methods
2119 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2120 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
2121 }
2122 },
2123 );
2124 let inner_ty_fo = inner_ty.clone();
2125 push_method(
2126 &mut tokens,
2127 method_scope,
2128 MethodKind::Owned,
2129 quote! {
2130 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
2131 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.into_values().next())
2132 }
2133 // Note: Key-based access methods for BTreeMap require the exact key type
2134 // For now, we'll skip generating these methods to avoid generic constraint issues
2135 },
2136 );
2137 }
2138 (WrapperKind::HashSet, Some(inner_ty)) => {
2139 push_method(
2140 &mut tokens,
2141 method_scope,
2142 MethodKind::Readable,
2143 quote! {
2144 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2145 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2146 }
2147 },
2148 );
2149 push_method(
2150 &mut tokens,
2151 method_scope,
2152 MethodKind::Writable,
2153 quote! {
2154 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2155 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2156 }
2157 },
2158 );
2159 let inner_ty_fr = inner_ty.clone();
2160 push_method(
2161 &mut tokens,
2162 method_scope,
2163 MethodKind::Readable,
2164 quote! {
2165 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
2166 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.iter().next())
2167 }
2168 },
2169 );
2170 push_method(
2171 &mut tokens,
2172 method_scope,
2173 MethodKind::Owned,
2174 quote! {
2175 // Owned keypath methods
2176 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2177 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
2178 }
2179 },
2180 );
2181 let inner_ty_fo = inner_ty.clone();
2182 push_method(
2183 &mut tokens,
2184 method_scope,
2185 MethodKind::Owned,
2186 quote! {
2187 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
2188 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.into_iter().next())
2189 }
2190 },
2191 );
2192 }
2193 (WrapperKind::BTreeSet, Some(inner_ty)) => {
2194 push_method(
2195 &mut tokens,
2196 method_scope,
2197 MethodKind::Readable,
2198 quote! {
2199 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2200 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2201 }
2202 },
2203 );
2204 push_method(
2205 &mut tokens,
2206 method_scope,
2207 MethodKind::Writable,
2208 quote! {
2209 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2210 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2211 }
2212 },
2213 );
2214 let inner_ty_fr = inner_ty.clone();
2215 push_method(
2216 &mut tokens,
2217 method_scope,
2218 MethodKind::Readable,
2219 quote! {
2220 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
2221 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.iter().next())
2222 }
2223 },
2224 );
2225 push_method(
2226 &mut tokens,
2227 method_scope,
2228 MethodKind::Owned,
2229 quote! {
2230 // Owned keypath methods
2231 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2232 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
2233 }
2234 },
2235 );
2236 let inner_ty_fo = inner_ty.clone();
2237 push_method(
2238 &mut tokens,
2239 method_scope,
2240 MethodKind::Owned,
2241 quote! {
2242 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
2243 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.into_iter().next())
2244 }
2245 },
2246 );
2247 }
2248 (WrapperKind::VecDeque, Some(inner_ty)) => {
2249 push_method(
2250 &mut tokens,
2251 method_scope,
2252 MethodKind::Readable,
2253 quote! {
2254 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2255 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2256 }
2257 },
2258 );
2259 push_method(
2260 &mut tokens,
2261 method_scope,
2262 MethodKind::Writable,
2263 quote! {
2264 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2265 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2266 }
2267 },
2268 );
2269 let inner_ty_fr = inner_ty.clone();
2270 push_method(
2271 &mut tokens,
2272 method_scope,
2273 MethodKind::Readable,
2274 quote! {
2275 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
2276 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.front())
2277 }
2278 },
2279 );
2280 let inner_ty_fw = inner_ty.clone();
2281 push_method(
2282 &mut tokens,
2283 method_scope,
2284 MethodKind::Writable,
2285 quote! {
2286 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
2287 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.front_mut())
2288 }
2289 },
2290 );
2291 push_method(
2292 &mut tokens,
2293 method_scope,
2294 MethodKind::Owned,
2295 quote! {
2296 // Owned keypath methods
2297 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2298 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
2299 }
2300 },
2301 );
2302 let inner_ty_fo = inner_ty.clone();
2303 push_method(
2304 &mut tokens,
2305 method_scope,
2306 MethodKind::Owned,
2307 quote! {
2308 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
2309 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.into_iter().next())
2310 }
2311 },
2312 );
2313 }
2314 (WrapperKind::LinkedList, Some(inner_ty)) => {
2315 push_method(
2316 &mut tokens,
2317 method_scope,
2318 MethodKind::Readable,
2319 quote! {
2320 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2321 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2322 }
2323 },
2324 );
2325 push_method(
2326 &mut tokens,
2327 method_scope,
2328 MethodKind::Writable,
2329 quote! {
2330 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2331 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2332 }
2333 },
2334 );
2335 let inner_ty_fr = inner_ty.clone();
2336 push_method(
2337 &mut tokens,
2338 method_scope,
2339 MethodKind::Readable,
2340 quote! {
2341 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
2342 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.front())
2343 }
2344 },
2345 );
2346 let inner_ty_fw = inner_ty.clone();
2347 push_method(
2348 &mut tokens,
2349 method_scope,
2350 MethodKind::Writable,
2351 quote! {
2352 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
2353 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.front_mut())
2354 }
2355 },
2356 );
2357 push_method(
2358 &mut tokens,
2359 method_scope,
2360 MethodKind::Owned,
2361 quote! {
2362 // Owned keypath methods
2363 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2364 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
2365 }
2366 },
2367 );
2368 let inner_ty_fo = inner_ty.clone();
2369 push_method(
2370 &mut tokens,
2371 method_scope,
2372 MethodKind::Owned,
2373 quote! {
2374 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
2375 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.into_iter().next())
2376 }
2377 },
2378 );
2379 }
2380 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
2381 push_method(
2382 &mut tokens,
2383 method_scope,
2384 MethodKind::Readable,
2385 quote! {
2386 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2387 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2388 }
2389 },
2390 );
2391 push_method(
2392 &mut tokens,
2393 method_scope,
2394 MethodKind::Writable,
2395 quote! {
2396 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2397 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2398 }
2399 },
2400 );
2401 let inner_ty_fr = inner_ty.clone();
2402 push_method(
2403 &mut tokens,
2404 method_scope,
2405 MethodKind::Readable,
2406 quote! {
2407 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
2408 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.peek())
2409 }
2410 },
2411 );
2412 let inner_ty_fw = inner_ty.clone();
2413 push_method(
2414 &mut tokens,
2415 method_scope,
2416 MethodKind::Writable,
2417 quote! {
2418 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty_fw, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty_fw>> {
2419 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.peek_mut().map(|v| &mut **v))
2420 }
2421 },
2422 );
2423 push_method(
2424 &mut tokens,
2425 method_scope,
2426 MethodKind::Owned,
2427 quote! {
2428 // Owned keypath methods
2429 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2430 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
2431 }
2432 },
2433 );
2434 let inner_ty_fo = inner_ty.clone();
2435 push_method(
2436 &mut tokens,
2437 method_scope,
2438 MethodKind::Owned,
2439 quote! {
2440 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
2441 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.into_iter().next())
2442 }
2443 },
2444 );
2445 }
2446 (WrapperKind::Result, Some(inner_ty)) => {
2447 push_method(
2448 &mut tokens,
2449 method_scope,
2450 MethodKind::Readable,
2451 quote! {
2452 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2453 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2454 }
2455 },
2456 );
2457 push_method(
2458 &mut tokens,
2459 method_scope,
2460 MethodKind::Writable,
2461 quote! {
2462 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2463 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2464 }
2465 },
2466 );
2467 let inner_ty_fr = inner_ty.clone();
2468 push_method(
2469 &mut tokens,
2470 method_scope,
2471 MethodKind::Readable,
2472 quote! {
2473 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fr, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fr>> {
2474 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.as_ref().ok())
2475 }
2476 },
2477 );
2478 push_method(
2479 &mut tokens,
2480 method_scope,
2481 MethodKind::Owned,
2482 quote! {
2483 // Note: Result<T, E> doesn't support failable_writable for inner type
2484 // Only providing container-level writable access
2485 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2486 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
2487 }
2488 },
2489 );
2490 let inner_ty_fo = inner_ty.clone();
2491 push_method(
2492 &mut tokens,
2493 method_scope,
2494 MethodKind::Owned,
2495 quote! {
2496 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty_fo, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty_fo>> {
2497 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.ok())
2498 }
2499 },
2500 );
2501 }
2502 (WrapperKind::Mutex, Some(_inner_ty)) => {
2503 push_method(
2504 &mut tokens,
2505 method_scope,
2506 MethodKind::Readable,
2507 quote! {
2508 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2509 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2510 }
2511 },
2512 );
2513 push_method(
2514 &mut tokens,
2515 method_scope,
2516 MethodKind::Writable,
2517 quote! {
2518 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2519 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2520 }
2521 },
2522 );
2523 push_method(
2524 &mut tokens,
2525 method_scope,
2526 MethodKind::Owned,
2527 quote! {
2528 // Note: Mutex<T> doesn't support direct access to inner type due to lifetime constraints
2529 // Only providing container-level access
2530 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2531 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
2532 }
2533 },
2534 );
2535 }
2536 (WrapperKind::RwLock, Some(_inner_ty)) => {
2537 push_method(
2538 &mut tokens,
2539 method_scope,
2540 MethodKind::Readable,
2541 quote! {
2542 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2543 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2544 }
2545 },
2546 );
2547 push_method(
2548 &mut tokens,
2549 method_scope,
2550 MethodKind::Writable,
2551 quote! {
2552 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2553 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2554 }
2555 },
2556 );
2557 push_method(
2558 &mut tokens,
2559 method_scope,
2560 MethodKind::Owned,
2561 quote! {
2562 // Note: RwLock<T> doesn't support direct access to inner type due to lifetime constraints
2563 // Only providing container-level access
2564 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2565 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
2566 }
2567 },
2568 );
2569 }
2570 (WrapperKind::Weak, Some(_inner_ty)) => {
2571 push_method(
2572 &mut tokens,
2573 method_scope,
2574 MethodKind::Readable,
2575 quote! {
2576 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2577 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2578 }
2579 },
2580 );
2581 push_method(
2582 &mut tokens,
2583 method_scope,
2584 MethodKind::Owned,
2585 quote! {
2586 // Note: Weak<T> doesn't support writable access (it's immutable)
2587 // Note: Weak<T> doesn't support direct access to inner type due to lifetime constraints
2588 // Only providing container-level access
2589 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2590 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
2591 }
2592 },
2593 );
2594 }
2595 // Nested container combinations for tuple structs - COMMENTED OUT FOR NOW
2596 /*
2597 (WrapperKind::OptionBox, Some(inner_ty)) => {
2598 tokens.extend(quote! {
2599 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2600 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2601 }
2602 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2603 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2604 }
2605 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
2606 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.as_ref().map(|b| &**b))
2607 }
2608 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
2609 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.as_mut().map(|b| &mut **b))
2610 }
2611 });
2612 }
2613 (WrapperKind::OptionRc, Some(inner_ty)) => {
2614 tokens.extend(quote! {
2615 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2616 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2617 }
2618 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
2619 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.as_ref().map(|r| &**r))
2620 }
2621 });
2622 }
2623 (WrapperKind::OptionArc, Some(inner_ty)) => {
2624 tokens.extend(quote! {
2625 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2626 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2627 }
2628 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
2629 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.as_ref().map(|a| &**a))
2630 }
2631 });
2632 }
2633 (WrapperKind::BoxOption, Some(inner_ty)) => {
2634 tokens.extend(quote! {
2635 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2636 rust_keypaths::KeyPath::new(|s: &#name| &*s.#idx_lit)
2637 }
2638 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2639 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut *s.#idx_lit)
2640 }
2641 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
2642 rust_keypaths::OptionalKeyPath::new(|s: &#name| (*s.#idx_lit).as_ref())
2643 }
2644 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
2645 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| (*s.#idx_lit).as_mut())
2646 }
2647 });
2648 }
2649 (WrapperKind::RcOption, Some(inner_ty)) => {
2650 tokens.extend(quote! {
2651 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2652 rust_keypaths::KeyPath::new(|s: &#name| &*s.#idx_lit)
2653 }
2654 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
2655 rust_keypaths::OptionalKeyPath::new(|s: &#name| (*s.#idx_lit).as_ref())
2656 }
2657 });
2658 }
2659 (WrapperKind::ArcOption, Some(inner_ty)) => {
2660 tokens.extend(quote! {
2661 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2662 rust_keypaths::KeyPath::new(|s: &#name| &*s.#idx_lit)
2663 }
2664 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
2665 rust_keypaths::OptionalKeyPath::new(|s: &#name| (*s.#idx_lit).as_ref())
2666 }
2667 });
2668 }
2669 (WrapperKind::VecOption, Some(inner_ty)) => {
2670 tokens.extend(quote! {
2671 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2672 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2673 }
2674 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2675 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2676 }
2677 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
2678 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.first().and_then(|opt| opt.as_ref()))
2679 }
2680 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
2681 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.first_mut().and_then(|opt| opt.as_mut()))
2682 }
2683 });
2684 }
2685 (WrapperKind::OptionVec, Some(inner_ty)) => {
2686 tokens.extend(quote! {
2687 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2688 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2689 }
2690 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2691 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2692 }
2693 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
2694 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.as_ref().and_then(|v| v.first()))
2695 }
2696 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
2697 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.as_mut().and_then(|v| v.first_mut()))
2698 }
2699 });
2700 }
2701 (WrapperKind::HashMapOption, Some(inner_ty)) => {
2702 tokens.extend(quote! {
2703 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2704 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2705 }
2706 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2707 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2708 }
2709 pub fn #fr_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
2710 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#idx_lit.get(&key).and_then(|opt| opt.as_ref()))
2711 }
2712 pub fn #fw_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
2713 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#idx_lit.get_mut(&key).and_then(|opt| opt.as_mut()))
2714 }
2715 });
2716 }
2717 (WrapperKind::OptionHashMap, Some(inner_ty)) => {
2718 tokens.extend(quote! {
2719 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2720 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2721 }
2722 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2723 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2724 }
2725 pub fn #fr_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
2726 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#idx_lit.as_ref().and_then(|m| m.get(&key)))
2727 }
2728 pub fn #fw_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: K) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
2729 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#idx_lit.as_mut().and_then(|m| m.get_mut(&key)))
2730 }
2731 });
2732 }
2733 */
2734 (WrapperKind::None, None) => {
2735 push_method(
2736 &mut tokens,
2737 method_scope,
2738 MethodKind::Readable,
2739 quote! {
2740 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2741 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2742 }
2743 },
2744 );
2745 push_method(
2746 &mut tokens,
2747 method_scope,
2748 MethodKind::Writable,
2749 quote! {
2750 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
2751 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
2752 }
2753 },
2754 );
2755 push_method(
2756 &mut tokens,
2757 method_scope,
2758 MethodKind::Readable,
2759 quote! {
2760 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
2761 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&s.#idx_lit))
2762 }
2763 },
2764 );
2765 push_method(
2766 &mut tokens,
2767 method_scope,
2768 MethodKind::Writable,
2769 quote! {
2770 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #ty>> {
2771 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| Some(&mut s.#idx_lit))
2772 }
2773 },
2774 );
2775 push_method(
2776 &mut tokens,
2777 method_scope,
2778 MethodKind::Owned,
2779 quote! {
2780 // Owned keypath methods
2781 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2782 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
2783 }
2784 },
2785 );
2786 push_method(
2787 &mut tokens,
2788 method_scope,
2789 MethodKind::Owned,
2790 quote! {
2791 pub fn #fo_fn() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
2792 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(s.#idx_lit))
2793 }
2794 },
2795 );
2796 }
2797 _ => {
2798 push_method(
2799 &mut tokens,
2800 method_scope,
2801 MethodKind::Readable,
2802 quote! {
2803 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2804 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
2805 }
2806 },
2807 );
2808 push_method(
2809 &mut tokens,
2810 method_scope,
2811 MethodKind::Owned,
2812 quote! {
2813 // Owned keypath methods
2814 pub fn #o_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
2815 rust_keypaths::KeyPath::new(|s: &#name| s.#idx_lit)
2816 }
2817 },
2818 );
2819 }
2820 }
2821 }
2822 tokens
2823 }
2824 _ => quote! {
2825 compile_error!("Keypaths derive supports only structs with named or unnamed fields");
2826 },
2827 },
2828 Data::Enum(data_enum) => {
2829 let mut tokens = proc_macro2::TokenStream::new();
2830 for variant in data_enum.variants.iter() {
2831 let v_ident = &variant.ident;
2832 let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
2833 let r_fn = format_ident!("{}_case_r", snake);
2834 let w_fn = format_ident!("{}_case_w", snake);
2835 let _fr_fn = format_ident!("{}_case_fr", snake);
2836 let _fw_fn = format_ident!("{}_case_fw", snake);
2837 let fr_at_fn = format_ident!("{}_case_fr_at", snake);
2838 let fw_at_fn = format_ident!("{}_case_fw_at", snake);
2839
2840 match &variant.fields {
2841 Fields::Unit => {
2842 tokens.extend(quote! {
2843 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, (), impl for<'r> Fn(&'r #name) -> &'r ()> {
2844 static UNIT: () = ();
2845 rust_keypaths::KeyPaths::readable_enum(
2846 |_| #name::#v_ident,
2847 |e: &#name| match e { #name::#v_ident => Some(&UNIT), _ => None }
2848 )
2849 }
2850 });
2851 }
2852 Fields::Unnamed(unnamed) if unnamed.unnamed.len() == 1 => {
2853 let field_ty = &unnamed.unnamed.first().unwrap().ty;
2854 let (kind, inner_ty_opt) = extract_wrapper_inner_type(field_ty);
2855
2856 match (kind, inner_ty_opt) {
2857 (WrapperKind::Option, Some(inner_ty)) => {
2858 tokens.extend(quote! {
2859 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
2860 rust_keypaths::KeyPaths::readable_enum(
2861 #name::#v_ident,
2862 |e: &#name| match e { #name::#v_ident(v) => v.as_ref(), _ => None }
2863 )
2864 }
2865 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
2866 rust_keypaths::KeyPaths::writable_enum(
2867 #name::#v_ident,
2868 |e: &#name| match e { #name::#v_ident(v) => v.as_ref(), _ => None },
2869 |e: &mut #name| match e { #name::#v_ident(v) => v.as_mut(), _ => None },
2870 )
2871 }
2872 });
2873 }
2874 (WrapperKind::Vec, Some(inner_ty)) => {
2875 tokens.extend(quote! {
2876 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
2877 rust_keypaths::KeyPaths::readable_enum(
2878 #name::#v_ident,
2879 |e: &#name| match e { #name::#v_ident(v) => v.first(), _ => None }
2880 )
2881 }
2882 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
2883 rust_keypaths::KeyPaths::writable_enum(
2884 #name::#v_ident,
2885 |e: &#name| match e { #name::#v_ident(v) => v.first(), _ => None },
2886 |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut(), _ => None },
2887 )
2888 }
2889 pub fn #fr_at_fn(index: &'static usize) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
2890 rust_keypaths::KeyPaths::readable_enum(
2891 #name::#v_ident,
2892 |e: &#name| match e { #name::#v_ident(v) => v.get(*index), _ => None }
2893 )
2894 }
2895 pub fn #fw_at_fn(index: &'static usize) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
2896 rust_keypaths::KeyPaths::writable_enum(
2897 #name::#v_ident,
2898 |e: &#name| match e { #name::#v_ident(v) => v.get(*index), _ => None },
2899 |e: &mut #name| match e { #name::#v_ident(v) => v.get_mut(*index), _ => None },
2900 )
2901 }
2902 });
2903 }
2904 (WrapperKind::HashMap, Some(inner_ty)) => {
2905 tokens.extend(quote! {
2906 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
2907 rust_keypaths::KeyPaths::readable_enum(
2908 #name::#v_ident,
2909 |e: &#name| match e { #name::#v_ident(v) => v.first().map(|(_, v)| v), _ => None }
2910 )
2911 }
2912 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
2913 rust_keypaths::KeyPaths::writable_enum(
2914 #name::#v_ident,
2915 |e: &#name| match e { #name::#v_ident(v) => v.first().map(|(_, v)| v), _ => None },
2916 |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut().map(|(_, v)| v), _ => None },
2917 )
2918 }
2919 pub fn #fr_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: &'static K) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
2920 rust_keypaths::KeyPaths::readable_enum(
2921 #name::#v_ident,
2922 |e: &#name| match e { #name::#v_ident(v) => v.get(key), _ => None }
2923 )
2924 }
2925 pub fn #fw_at_fn<K: ::std::hash::Hash + ::std::cmp::Eq + 'static>(key: &'static K) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
2926 rust_keypaths::KeyPaths::writable_enum(
2927 #name::#v_ident,
2928 |e: &#name| match e { #name::#v_ident(v) => v.get(key), _ => None },
2929 |e: &mut #name| match e { #name::#v_ident(v) => v.get_mut(key), _ => None },
2930 )
2931 }
2932 });
2933 }
2934 (WrapperKind::Box, Some(inner_ty)) => {
2935 tokens.extend(quote! {
2936 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
2937 rust_keypaths::KeyPaths::readable_enum(
2938 #name::#v_ident,
2939 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
2940 )
2941 }
2942 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
2943 rust_keypaths::KeyPaths::writable_enum(
2944 #name::#v_ident,
2945 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None },
2946 |e: &mut #name| match e { #name::#v_ident(v) => Some(&mut *v), _ => None },
2947 )
2948 }
2949 });
2950 }
2951 (WrapperKind::Rc, Some(inner_ty))
2952 | (WrapperKind::Arc, Some(inner_ty)) => {
2953 tokens.extend(quote! {
2954 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
2955 rust_keypaths::KeyPaths::readable_enum(
2956 #name::#v_ident,
2957 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
2958 )
2959 }
2960 });
2961 }
2962 (WrapperKind::BTreeMap, Some(inner_ty)) => {
2963 tokens.extend(quote! {
2964 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
2965 rust_keypaths::KeyPaths::readable_enum(
2966 #name::#v_ident,
2967 |e: &#name| match e { #name::#v_ident(v) => v.first().map(|(_, v)| v), _ => None }
2968 )
2969 }
2970 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
2971 rust_keypaths::KeyPaths::writable_enum(
2972 #name::#v_ident,
2973 |e: &#name| match e { #name::#v_ident(v) => v.first().map(|(_, v)| v), _ => None },
2974 |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut().map(|(_, v)| v), _ => None },
2975 )
2976 }
2977 });
2978 }
2979 (WrapperKind::HashSet, Some(inner_ty)) => {
2980 tokens.extend(quote! {
2981 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
2982 rust_keypaths::KeyPaths::readable_enum(
2983 #name::#v_ident,
2984 |e: &#name| match e { #name::#v_ident(v) => v.iter().next(), _ => None }
2985 )
2986 }
2987 });
2988 }
2989 (WrapperKind::BTreeSet, Some(inner_ty)) => {
2990 tokens.extend(quote! {
2991 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
2992 rust_keypaths::KeyPaths::readable_enum(
2993 #name::#v_ident,
2994 |e: &#name| match e { #name::#v_ident(v) => v.iter().next(), _ => None }
2995 )
2996 }
2997 });
2998 }
2999 (WrapperKind::VecDeque, Some(inner_ty)) => {
3000 tokens.extend(quote! {
3001 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
3002 rust_keypaths::KeyPaths::readable_enum(
3003 #name::#v_ident,
3004 |e: &#name| match e { #name::#v_ident(v) => v.front(), _ => None }
3005 )
3006 }
3007 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
3008 rust_keypaths::KeyPaths::writable_enum(
3009 #name::#v_ident,
3010 |e: &#name| match e { #name::#v_ident(v) => v.front(), _ => None },
3011 |e: &mut #name| match e { #name::#v_ident(v) => v.front_mut(), _ => None },
3012 )
3013 }
3014 });
3015 }
3016 (WrapperKind::LinkedList, Some(inner_ty)) => {
3017 tokens.extend(quote! {
3018 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
3019 rust_keypaths::KeyPaths::readable_enum(
3020 #name::#v_ident,
3021 |e: &#name| match e { #name::#v_ident(v) => v.front(), _ => None }
3022 )
3023 }
3024 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
3025 rust_keypaths::KeyPaths::writable_enum(
3026 #name::#v_ident,
3027 |e: &#name| match e { #name::#v_ident(v) => v.front(), _ => None },
3028 |e: &mut #name| match e { #name::#v_ident(v) => v.front_mut(), _ => None },
3029 )
3030 }
3031 });
3032 }
3033 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
3034 tokens.extend(quote! {
3035 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
3036 rust_keypaths::KeyPaths::readable_enum(
3037 #name::#v_ident,
3038 |e: &#name| match e { #name::#v_ident(v) => v.peek(), _ => None }
3039 )
3040 }
3041 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
3042 rust_keypaths::KeyPaths::writable_enum(
3043 #name::#v_ident,
3044 |e: &#name| match e { #name::#v_ident(v) => v.peek(), _ => None },
3045 |e: &mut #name| match e { #name::#v_ident(v) => v.peek_mut().map(|v| &mut **v), _ => None },
3046 )
3047 }
3048 });
3049 }
3050 (WrapperKind::Result, Some(inner_ty)) => {
3051 tokens.extend(quote! {
3052 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
3053 rust_keypaths::KeyPaths::readable_enum(
3054 #name::#v_ident,
3055 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().ok(), _ => None }
3056 )
3057 }
3058 // Note: Result<T, E> doesn't support writable access for inner type
3059 // Only providing readable access
3060 });
3061 }
3062 (WrapperKind::Mutex, Some(inner_ty)) => {
3063 tokens.extend(quote! {
3064 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
3065 rust_keypaths::KeyPaths::readable_enum(
3066 #name::#v_ident,
3067 |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None }
3068 )
3069 }
3070 // Note: Mutex<T> doesn't support direct access to inner type due to lifetime constraints
3071 // Only providing container-level access
3072 });
3073 }
3074 (WrapperKind::RwLock, Some(inner_ty)) => {
3075 tokens.extend(quote! {
3076 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
3077 rust_keypaths::KeyPaths::readable_enum(
3078 #name::#v_ident,
3079 |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None }
3080 )
3081 }
3082 // Note: RwLock<T> doesn't support direct access to inner type due to lifetime constraints
3083 // Only providing container-level access
3084 });
3085 }
3086 (WrapperKind::Weak, Some(inner_ty)) => {
3087 tokens.extend(quote! {
3088 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
3089 rust_keypaths::KeyPaths::readable_enum(
3090 #name::#v_ident,
3091 |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None }
3092 )
3093 }
3094 // Note: Weak<T> doesn't support writable access (it's immutable)
3095 // Note: Weak<T> doesn't support direct access to inner type due to lifetime constraints
3096 // Only providing container-level access
3097 });
3098 }
3099 // Nested container combinations for enums - COMMENTED OUT FOR NOW
3100 /*
3101 (WrapperKind::OptionBox, Some(inner_ty)) => {
3102 tokens.extend(quote! {
3103 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
3104 rust_keypaths::KeyPaths::readable_enum(
3105 #name::#v_ident,
3106 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().map(|b| &**b), _ => None }
3107 )
3108 }
3109 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
3110 rust_keypaths::KeyPaths::writable_enum(
3111 #name::#v_ident,
3112 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().map(|b| &**b), _ => None },
3113 |e: &mut #name| match e { #name::#v_ident(v) => v.as_mut().map(|b| &mut **b), _ => None },
3114 )
3115 }
3116 });
3117 }
3118 (WrapperKind::OptionRc, Some(inner_ty)) => {
3119 tokens.extend(quote! {
3120 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
3121 rust_keypaths::KeyPaths::readable_enum(
3122 #name::#v_ident,
3123 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().map(|r| &**r), _ => None }
3124 )
3125 }
3126 });
3127 }
3128 (WrapperKind::OptionArc, Some(inner_ty)) => {
3129 tokens.extend(quote! {
3130 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
3131 rust_keypaths::KeyPaths::readable_enum(
3132 #name::#v_ident,
3133 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().map(|a| &**a), _ => None }
3134 )
3135 }
3136 });
3137 }
3138 (WrapperKind::BoxOption, Some(inner_ty)) => {
3139 tokens.extend(quote! {
3140 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
3141 rust_keypaths::KeyPaths::readable_enum(
3142 #name::#v_ident,
3143 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
3144 )
3145 }
3146 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #field_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #field_ty> {
3147 rust_keypaths::KeyPaths::writable_enum(
3148 #name::#v_ident,
3149 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None },
3150 |e: &mut #name| match e { #name::#v_ident(v) => Some(&mut *v), _ => None },
3151 )
3152 }
3153 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
3154 rust_keypaths::KeyPaths::readable_enum(
3155 #name::#v_ident,
3156 |e: &#name| match e { #name::#v_ident(v) => (*v).as_ref(), _ => None }
3157 )
3158 }
3159 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3160 rust_keypaths::KeyPaths::writable_enum(
3161 #name::#v_ident,
3162 |e: &#name| match e { #name::#v_ident(v) => (*v).as_ref(), _ => None },
3163 |e: &mut #name| match e { #name::#v_ident(v) => (*v).as_mut(), _ => None },
3164 )
3165 }
3166 });
3167 }
3168 (WrapperKind::RcOption, Some(inner_ty)) => {
3169 tokens.extend(quote! {
3170 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
3171 rust_keypaths::KeyPaths::readable_enum(
3172 #name::#v_ident,
3173 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
3174 )
3175 }
3176 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
3177 rust_keypaths::KeyPaths::readable_enum(
3178 #name::#v_ident,
3179 |e: &#name| match e { #name::#v_ident(v) => (*v).as_ref(), _ => None }
3180 )
3181 }
3182 });
3183 }
3184 (WrapperKind::ArcOption, Some(inner_ty)) => {
3185 tokens.extend(quote! {
3186 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
3187 rust_keypaths::KeyPaths::readable_enum(
3188 #name::#v_ident,
3189 |e: &#name| match e { #name::#v_ident(v) => Some(&*v), _ => None }
3190 )
3191 }
3192 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
3193 rust_keypaths::KeyPaths::readable_enum(
3194 #name::#v_ident,
3195 |e: &#name| match e { #name::#v_ident(v) => (*v).as_ref(), _ => None }
3196 )
3197 }
3198 });
3199 }
3200 (WrapperKind::VecOption, Some(inner_ty)) => {
3201 tokens.extend(quote! {
3202 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
3203 rust_keypaths::KeyPaths::readable_enum(
3204 #name::#v_ident,
3205 |e: &#name| match e { #name::#v_ident(v) => v.first().and_then(|opt| opt.as_ref()), _ => None }
3206 )
3207 }
3208 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
3209 rust_keypaths::KeyPaths::writable_enum(
3210 #name::#v_ident,
3211 |e: &#name| match e { #name::#v_ident(v) => v.first().and_then(|opt| opt.as_ref()), _ => None },
3212 |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut().and_then(|opt| opt.as_mut()), _ => None },
3213 )
3214 }
3215 });
3216 }
3217 (WrapperKind::OptionVec, Some(inner_ty)) => {
3218 tokens.extend(quote! {
3219 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
3220 rust_keypaths::KeyPaths::readable_enum(
3221 #name::#v_ident,
3222 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().and_then(|vec| vec.first()), _ => None }
3223 )
3224 }
3225 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
3226 rust_keypaths::KeyPaths::writable_enum(
3227 #name::#v_ident,
3228 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().and_then(|vec| vec.first()), _ => None },
3229 |e: &mut #name| match e { #name::#v_ident(v) => v.as_mut().and_then(|vec| vec.first_mut()), _ => None },
3230 )
3231 }
3232 });
3233 }
3234 (WrapperKind::HashMapOption, Some(inner_ty)) => {
3235 tokens.extend(quote! {
3236 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
3237 rust_keypaths::KeyPaths::readable_enum(
3238 #name::#v_ident,
3239 |e: &#name| match e { #name::#v_ident(v) => v.first().and_then(|(_, opt)| opt.as_ref()), _ => None }
3240 )
3241 }
3242 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
3243 rust_keypaths::KeyPaths::writable_enum(
3244 #name::#v_ident,
3245 |e: &#name| match e { #name::#v_ident(v) => v.first().and_then(|(_, opt)| opt.as_ref()), _ => None },
3246 |e: &mut #name| match e { #name::#v_ident(v) => v.first_mut().and_then(|(_, opt)| opt.as_mut()), _ => None },
3247 )
3248 }
3249 });
3250 }
3251 (WrapperKind::OptionHashMap, Some(inner_ty)) => {
3252 tokens.extend(quote! {
3253 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
3254 rust_keypaths::KeyPaths::readable_enum(
3255 #name::#v_ident,
3256 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().and_then(|map| map.first().map(|(_, v)| v)), _ => None }
3257 )
3258 }
3259 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
3260 rust_keypaths::KeyPaths::writable_enum(
3261 #name::#v_ident,
3262 |e: &#name| match e { #name::#v_ident(v) => v.as_ref().and_then(|map| map.first().map(|(_, v)| v)), _ => None },
3263 |e: &mut #name| match e { #name::#v_ident(v) => v.as_mut().and_then(|map| map.first_mut().map(|(_, v)| v)), _ => None },
3264 )
3265 }
3266 });
3267 }
3268 */
3269 (WrapperKind::None, None) => {
3270 let inner_ty = field_ty;
3271 tokens.extend(quote! {
3272 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
3273 rust_keypaths::KeyPaths::readable_enum(
3274 #name::#v_ident,
3275 |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None }
3276 )
3277 }
3278 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
3279 rust_keypaths::KeyPaths::writable_enum(
3280 #name::#v_ident,
3281 |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None },
3282 |e: &mut #name| match e { #name::#v_ident(v) => Some(v), _ => None },
3283 )
3284 }
3285 });
3286 }
3287 _ => {
3288 tokens.extend(quote! {
3289 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
3290 rust_keypaths::KeyPaths::readable_enum(
3291 #name::#v_ident,
3292 |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None }
3293 )
3294 }
3295 });
3296 }
3297 }
3298 }
3299 Fields::Unnamed(unnamed) if unnamed.unnamed.len() > 1 => {
3300 // Multi-field tuple variants - generate methods for each field
3301 for (index, field) in unnamed.unnamed.iter().enumerate() {
3302 let field_ty = &field.ty;
3303 let field_fn = format_ident!("f{}", index);
3304 let r_fn = format_ident!("{}_{}_r", snake, field_fn);
3305 let w_fn = format_ident!("{}_{}_w", snake, field_fn);
3306
3307 // Generate pattern matching for this specific field
3308 let mut pattern_parts = Vec::new();
3309
3310 for i in 0..unnamed.unnamed.len() {
3311 if i == index {
3312 pattern_parts.push(quote! { v });
3313 } else {
3314 pattern_parts.push(quote! { _ });
3315 }
3316 }
3317
3318 let pattern = quote! { #name::#v_ident(#(#pattern_parts),*) };
3319 let match_expr = quote! { match e { #pattern => Some(v), _ => None } };
3320 let match_mut_expr = quote! { match e { #pattern => Some(v), _ => None } };
3321
3322 tokens.extend(quote! {
3323 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
3324 rust_keypaths::OptionalKeyPath::new(|e: &#name| #match_expr)
3325 }
3326 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #field_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #field_ty> {
3327 rust_keypaths::WritableOptionalKeyPath::new(|e: &mut #name| #match_mut_expr)
3328 }
3329 });
3330 }
3331 }
3332 Fields::Named(named) => {
3333 // Labeled enum variants - generate methods for each field
3334 for field in named.named.iter() {
3335 let field_ident = field.ident.as_ref().unwrap();
3336 let field_ty = &field.ty;
3337 let r_fn = format_ident!("{}_{}_r", snake, field_ident);
3338 let w_fn = format_ident!("{}_{}_w", snake, field_ident);
3339
3340 tokens.extend(quote! {
3341 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
3342 rust_keypaths::OptionalKeyPath::new(|e: &#name| match e { #name::#v_ident { #field_ident: v, .. } => Some(v), _ => None })
3343 }
3344 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #field_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #field_ty> {
3345 rust_keypaths::WritableOptionalKeyPath::new(|e: &mut #name| match e { #name::#v_ident { #field_ident: v, .. } => Some(v), _ => None })
3346 }
3347 });
3348 }
3349 }
3350 _ => {
3351 tokens.extend(quote! {
3352 compile_error!("Keypaths derive supports only unit, single-field, multi-field tuple, and labeled variants");
3353 });
3354 }
3355 }
3356 }
3357 tokens
3358 }
3359 _ => quote! {
3360 compile_error!("Keypaths derive supports only structs and enums");
3361 },
3362 };
3363
3364 let expanded = quote! {
3365 impl #name {
3366 #methods
3367 }
3368 };
3369
3370 TokenStream::from(expanded)
3371}
3372
3373fn extract_wrapper_inner_type(ty: &Type) -> (WrapperKind, Option<Type>) {
3374 use syn::{GenericArgument, PathArguments};
3375
3376 if let Type::Path(tp) = ty {
3377 if let Some(seg) = tp.path.segments.last() {
3378 let ident_str = seg.ident.to_string();
3379
3380 if let PathArguments::AngleBracketed(ab) = &seg.arguments {
3381 let args: Vec<_> = ab.args.iter().collect();
3382
3383 // Handle map types (HashMap, BTreeMap) - they have K, V parameters
3384 if ident_str == "HashMap" || ident_str == "BTreeMap" {
3385 if let (Some(_key_arg), Some(value_arg)) = (args.get(0), args.get(1)) {
3386 if let GenericArgument::Type(inner) = value_arg {
3387 eprintln!("Detected {} type, extracting value type", ident_str);
3388 // Check for nested Option in map values
3389 let (inner_kind, inner_inner) = extract_wrapper_inner_type(inner);
3390 match (ident_str.as_str(), inner_kind) {
3391 ("HashMap", WrapperKind::Option) => {
3392 return (WrapperKind::HashMapOption, inner_inner);
3393 }
3394 _ => {
3395 return match ident_str.as_str() {
3396 "HashMap" => (WrapperKind::HashMap, Some(inner.clone())),
3397 "BTreeMap" => (WrapperKind::BTreeMap, Some(inner.clone())),
3398 _ => (WrapperKind::None, None),
3399 };
3400 }
3401 }
3402 }
3403 }
3404 }
3405 // Handle single-parameter container types
3406 else if let Some(arg) = args.get(0) {
3407 if let GenericArgument::Type(inner) = arg {
3408 // Check for nested containers first
3409 let (inner_kind, inner_inner) = extract_wrapper_inner_type(inner);
3410
3411 // Handle nested combinations
3412 match (ident_str.as_str(), inner_kind) {
3413 ("Option", WrapperKind::Box) => {
3414 return (WrapperKind::OptionBox, inner_inner);
3415 }
3416 ("Option", WrapperKind::Rc) => {
3417 return (WrapperKind::OptionRc, inner_inner);
3418 }
3419 ("Option", WrapperKind::Arc) => {
3420 return (WrapperKind::OptionArc, inner_inner);
3421 }
3422 ("Option", WrapperKind::Vec) => {
3423 return (WrapperKind::OptionVec, inner_inner);
3424 }
3425 ("Option", WrapperKind::HashMap) => {
3426 return (WrapperKind::OptionHashMap, inner_inner);
3427 }
3428 ("Box", WrapperKind::Option) => {
3429 return (WrapperKind::BoxOption, inner_inner);
3430 }
3431 ("Rc", WrapperKind::Option) => {
3432 return (WrapperKind::RcOption, inner_inner);
3433 }
3434 ("Arc", WrapperKind::Option) => {
3435 return (WrapperKind::ArcOption, inner_inner);
3436 }
3437 ("Vec", WrapperKind::Option) => {
3438 return (WrapperKind::VecOption, inner_inner);
3439 }
3440 ("HashMap", WrapperKind::Option) => {
3441 return (WrapperKind::HashMapOption, inner_inner);
3442 }
3443 ("Arc", WrapperKind::Mutex) => {
3444 return (WrapperKind::ArcMutex, inner_inner);
3445 }
3446 ("Arc", WrapperKind::RwLock) => {
3447 return (WrapperKind::ArcRwLock, inner_inner);
3448 }
3449 _ => {
3450 // Handle single-level containers
3451 return match ident_str.as_str() {
3452 "Option" => (WrapperKind::Option, Some(inner.clone())),
3453 "Box" => (WrapperKind::Box, Some(inner.clone())),
3454 "Rc" => (WrapperKind::Rc, Some(inner.clone())),
3455 "Arc" => (WrapperKind::Arc, Some(inner.clone())),
3456 "Vec" => (WrapperKind::Vec, Some(inner.clone())),
3457 "HashSet" => (WrapperKind::HashSet, Some(inner.clone())),
3458 "BTreeSet" => (WrapperKind::BTreeSet, Some(inner.clone())),
3459 "VecDeque" => (WrapperKind::VecDeque, Some(inner.clone())),
3460 "LinkedList" => (WrapperKind::LinkedList, Some(inner.clone())),
3461 "BinaryHeap" => (WrapperKind::BinaryHeap, Some(inner.clone())),
3462 "Result" => (WrapperKind::Result, Some(inner.clone())),
3463 "Mutex" => (WrapperKind::Mutex, Some(inner.clone())),
3464 "RwLock" => (WrapperKind::RwLock, Some(inner.clone())),
3465 "Weak" => (WrapperKind::Weak, Some(inner.clone())),
3466 "Tagged" => (WrapperKind::Tagged, Some(inner.clone())),
3467 _ => (WrapperKind::None, None),
3468 };
3469 }
3470 }
3471 }
3472 }
3473 }
3474 }
3475 }
3476 (WrapperKind::None, None)
3477}
3478
3479
3480fn to_snake_case(name: &str) -> String {
3481 let mut out = String::new();
3482 for (i, c) in name.chars().enumerate() {
3483 if c.is_uppercase() {
3484 if i != 0 {
3485 out.push('_');
3486 }
3487 out.push(c.to_ascii_lowercase());
3488 } else {
3489 out.push(c);
3490 }
3491 }
3492 out
3493}
3494
3495#[proc_macro_derive(WritableKeypaths)]
3496pub fn derive_writable_keypaths(input: TokenStream) -> TokenStream {
3497 let input = parse_macro_input!(input as DeriveInput);
3498 let name = input.ident;
3499
3500 let methods = match input.data {
3501 Data::Struct(data_struct) => match data_struct.fields {
3502 Fields::Named(fields_named) => {
3503 let mut tokens = proc_macro2::TokenStream::new();
3504 for field in fields_named.named.iter() {
3505 let field_ident = field.ident.as_ref().unwrap();
3506 let ty = &field.ty;
3507
3508 let w_fn = format_ident!("{}_w", field_ident);
3509 let fw_fn = format_ident!("{}_fw", field_ident);
3510 let fw_at_fn = format_ident!("{}_fw_at", field_ident);
3511
3512 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
3513
3514 match (kind, inner_ty.clone()) {
3515 (WrapperKind::Option, Some(inner_ty)) => {
3516 tokens.extend(quote! {
3517 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3518 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3519 }
3520 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3521 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.as_mut())
3522 }
3523 });
3524 }
3525 (WrapperKind::Vec, Some(inner_ty)) => {
3526 tokens.extend(quote! {
3527 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3528 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3529 }
3530 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3531 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.first_mut())
3532 }
3533 pub fn #fw_at_fn(index: usize) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3534 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(index))
3535 }
3536 });
3537 }
3538 (WrapperKind::HashMap, Some(inner_ty)) => {
3539 tokens.extend(quote! {
3540 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3541 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3542 }
3543 pub fn #fw_fn(key: String) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3544 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(&key))
3545 }
3546 pub fn #fw_at_fn(key: String) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3547 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(&key))
3548 }
3549 });
3550 }
3551 (WrapperKind::Box, Some(inner_ty)) => {
3552 tokens.extend(quote! {
3553 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
3554 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut *s.#field_ident)
3555 }
3556 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3557 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| Some(&mut *s.#field_ident))
3558 }
3559 });
3560 }
3561 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
3562 tokens.extend(quote! {
3563 // Note: Rc/Arc are not writable due to shared ownership
3564 // Only providing readable methods for these types
3565 });
3566 }
3567 (WrapperKind::BTreeMap, Some(inner_ty)) => {
3568 tokens.extend(quote! {
3569 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3570 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3571 }
3572 pub fn #fw_fn(key: String) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3573 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(&key))
3574 }
3575 pub fn #fw_at_fn(key: String) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3576 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(&key))
3577 }
3578 });
3579 }
3580 (WrapperKind::HashSet, Some(inner_ty)) => {
3581 tokens.extend(quote! {
3582 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3583 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3584 }
3585 // Note: HashSet doesn't have direct mutable access to elements
3586 // Only providing container-level writable access
3587 });
3588 }
3589 (WrapperKind::BTreeSet, Some(inner_ty)) => {
3590 tokens.extend(quote! {
3591 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3592 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3593 }
3594 // Note: BTreeSet doesn't have direct mutable access to elements
3595 // Only providing container-level writable access
3596 });
3597 }
3598 (WrapperKind::VecDeque, Some(inner_ty)) => {
3599 tokens.extend(quote! {
3600 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3601 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3602 }
3603 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3604 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.front_mut())
3605 }
3606 pub fn #fw_at_fn(index: usize) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3607 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(index))
3608 }
3609 });
3610 }
3611 (WrapperKind::LinkedList, Some(inner_ty)) => {
3612 tokens.extend(quote! {
3613 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3614 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3615 }
3616 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3617 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.front_mut())
3618 }
3619 });
3620 }
3621 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
3622 tokens.extend(quote! {
3623 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3624 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3625 }
3626 // Note: BinaryHeap peek_mut() returns PeekMut wrapper that doesn't allow direct mutable access
3627 // Only providing container-level writable access
3628 });
3629 }
3630 (WrapperKind::Result, Some(inner_ty)) => {
3631 tokens.extend(quote! {
3632 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3633 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3634 }
3635 // Note: Result<T, E> doesn't support failable_writable for inner type
3636 // Only providing container-level writable access
3637 });
3638 }
3639 (WrapperKind::Mutex, Some(inner_ty)) => {
3640 tokens.extend(quote! {
3641 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3642 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3643 }
3644 // Note: Mutex<T> doesn't support direct access to inner type due to lifetime constraints
3645 // Only providing container-level writable access
3646 });
3647 }
3648 (WrapperKind::RwLock, Some(inner_ty)) => {
3649 tokens.extend(quote! {
3650 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3651 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3652 }
3653 // Note: RwLock<T> doesn't support direct access to inner type due to lifetime constraints
3654 // Only providing container-level writable access
3655 });
3656 }
3657 (WrapperKind::Weak, Some(inner_ty)) => {
3658 tokens.extend(quote! {
3659 // Note: Weak<T> doesn't support writable access (it's immutable)
3660 // No methods generated for Weak<T>
3661 });
3662 }
3663 (WrapperKind::None, None) => {
3664 tokens.extend(quote! {
3665 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3666 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3667 }
3668 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #ty>> {
3669 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| Some(&mut s.#field_ident))
3670 }
3671 });
3672 }
3673 _ => {
3674 tokens.extend(quote! {
3675 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3676 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident)
3677 }
3678 });
3679 }
3680 }
3681 }
3682 tokens
3683 }
3684 Fields::Unnamed(unnamed) => {
3685 let mut tokens = proc_macro2::TokenStream::new();
3686 for (idx, field) in unnamed.unnamed.iter().enumerate() {
3687 let idx_lit = syn::Index::from(idx);
3688 let ty = &field.ty;
3689
3690 let w_fn = format_ident!("f{}_w", idx);
3691 let fw_fn = format_ident!("f{}_fw", idx);
3692 let fw_at_fn = format_ident!("f{}_fw_at", idx);
3693
3694 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
3695
3696 match (kind, inner_ty.clone()) {
3697 (WrapperKind::Option, Some(inner_ty)) => {
3698 tokens.extend(quote! {
3699 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3700 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3701 }
3702 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3703 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.as_mut())
3704 }
3705 });
3706 }
3707 (WrapperKind::Vec, Some(inner_ty)) => {
3708 tokens.extend(quote! {
3709 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3710 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3711 }
3712 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3713 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.first_mut())
3714 }
3715 pub fn #fw_at_fn(index: &'static usize) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3716 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.get_mut(*index))
3717 }
3718 });
3719 }
3720 (WrapperKind::HashMap, Some(inner_ty)) => {
3721 tokens.extend(quote! {
3722 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3723 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3724 }
3725 pub fn #fw_fn(key: String) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3726 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#idx_lit.get_mut(&key))
3727 }
3728 pub fn #fw_at_fn(key: String) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3729 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#idx_lit.get_mut(&key))
3730 }
3731 });
3732 }
3733 (WrapperKind::Box, Some(inner_ty)) => {
3734 tokens.extend(quote! {
3735 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #inner_ty> {
3736 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut *s.#idx_lit)
3737 }
3738 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3739 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| Some(&mut *s.#idx_lit))
3740 }
3741 });
3742 }
3743 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
3744 tokens.extend(quote! {
3745 // Note: Rc/Arc are not writable due to shared ownership
3746 // Only providing readable methods for these types
3747 });
3748 }
3749 (WrapperKind::BTreeMap, Some(inner_ty)) => {
3750 tokens.extend(quote! {
3751 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3752 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3753 }
3754 pub fn #fw_fn(key: String) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3755 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#idx_lit.get_mut(&key))
3756 }
3757 pub fn #fw_at_fn(key: String) -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3758 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#idx_lit.get_mut(&key))
3759 }
3760 });
3761 }
3762 (WrapperKind::HashSet, Some(inner_ty)) => {
3763 tokens.extend(quote! {
3764 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3765 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3766 }
3767 // Note: HashSet doesn't have direct mutable access to elements
3768 // Only providing container-level writable access
3769 });
3770 }
3771 (WrapperKind::BTreeSet, Some(inner_ty)) => {
3772 tokens.extend(quote! {
3773 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3774 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3775 }
3776 // Note: BTreeSet doesn't have direct mutable access to elements
3777 // Only providing container-level writable access
3778 });
3779 }
3780 (WrapperKind::VecDeque, Some(inner_ty)) => {
3781 tokens.extend(quote! {
3782 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3783 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3784 }
3785 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3786 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.front_mut())
3787 }
3788 });
3789 }
3790 (WrapperKind::LinkedList, Some(inner_ty)) => {
3791 tokens.extend(quote! {
3792 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3793 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3794 }
3795 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
3796 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#idx_lit.front_mut())
3797 }
3798 });
3799 }
3800 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
3801 tokens.extend(quote! {
3802 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3803 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3804 }
3805 // Note: BinaryHeap peek_mut() returns PeekMut wrapper that doesn't allow direct mutable access
3806 // Only providing container-level writable access
3807 });
3808 }
3809 (WrapperKind::Result, Some(inner_ty)) => {
3810 tokens.extend(quote! {
3811 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3812 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3813 }
3814 // Note: Result<T, E> doesn't support failable_writable for inner type
3815 // Only providing container-level writable access
3816 });
3817 }
3818 (WrapperKind::Mutex, Some(inner_ty)) => {
3819 tokens.extend(quote! {
3820 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3821 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3822 }
3823 // Note: Mutex<T> doesn't support direct access to inner type due to lifetime constraints
3824 // Only providing container-level writable access
3825 });
3826 }
3827 (WrapperKind::RwLock, Some(inner_ty)) => {
3828 tokens.extend(quote! {
3829 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3830 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3831 }
3832 // Note: RwLock<T> doesn't support direct access to inner type due to lifetime constraints
3833 // Only providing container-level writable access
3834 });
3835 }
3836 (WrapperKind::Weak, Some(inner_ty)) => {
3837 tokens.extend(quote! {
3838 // Note: Weak<T> doesn't support writable access (it's immutable)
3839 // No methods generated for Weak<T>
3840 });
3841 }
3842 (WrapperKind::None, None) => {
3843 tokens.extend(quote! {
3844 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3845 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3846 }
3847 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #ty>> {
3848 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| Some(&mut s.#idx_lit))
3849 }
3850 });
3851 }
3852 _ => {
3853 tokens.extend(quote! {
3854 pub fn #w_fn() -> rust_keypaths::WritableKeyPath<#name, #ty, impl for<'r> Fn(&'r mut #name) -> &'r mut #ty> {
3855 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#idx_lit)
3856 }
3857 });
3858 }
3859 }
3860 }
3861 tokens
3862 }
3863 _ => quote! {
3864 compile_error!("WritableKeypaths derive supports only structs with named or unnamed fields");
3865 },
3866 },
3867 _ => quote! {
3868 compile_error!("WritableKeypaths derive supports only structs");
3869 },
3870 };
3871
3872 let expanded = quote! {
3873 impl #name {
3874 #methods
3875 }
3876 };
3877
3878 TokenStream::from(expanded)
3879}
3880
3881#[proc_macro_derive(Keypath)]
3882pub fn derive_keypath(input: TokenStream) -> TokenStream {
3883 let input = parse_macro_input!(input as DeriveInput);
3884 let name = input.ident;
3885
3886 let methods = match input.data {
3887 Data::Struct(data_struct) => match data_struct.fields {
3888 Fields::Named(fields_named) => {
3889 let mut tokens = proc_macro2::TokenStream::new();
3890 for field in fields_named.named.iter() {
3891 let field_ident = field.ident.as_ref().unwrap();
3892 let ty = &field.ty;
3893
3894 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
3895
3896 match (kind, inner_ty.clone()) {
3897 (WrapperKind::Option, Some(inner_ty)) => {
3898 // For Option<T>, return failable readable keypath to inner type
3899 tokens.extend(quote! {
3900 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
3901 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref())
3902 }
3903 });
3904 }
3905 (WrapperKind::Vec, Some(inner_ty)) => {
3906 // For Vec<T>, return failable readable keypath to first element
3907 tokens.extend(quote! {
3908 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
3909 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.first())
3910 }
3911 });
3912 }
3913 (WrapperKind::HashMap, Some(inner_ty)) => {
3914 // For HashMap<K,V>, return readable keypath to the container
3915 tokens.extend(quote! {
3916 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
3917 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
3918 }
3919 });
3920 }
3921 (WrapperKind::BTreeMap, Some(inner_ty)) => {
3922 // For BTreeMap<K,V>, return readable keypath to the container
3923 tokens.extend(quote! {
3924 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
3925 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
3926 }
3927 });
3928 }
3929 (WrapperKind::Box, Some(inner_ty)) => {
3930 // For Box<T>, return readable keypath to inner type
3931 tokens.extend(quote! {
3932 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
3933 rust_keypaths::KeyPath::new(|s: &#name| &*s.#field_ident)
3934 }
3935 });
3936 }
3937 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
3938 // For Rc<T>/Arc<T>, return readable keypath to inner type
3939 tokens.extend(quote! {
3940 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
3941 rust_keypaths::KeyPath::new(|s: &#name| &*s.#field_ident)
3942 }
3943 });
3944 }
3945 (WrapperKind::HashSet, Some(inner_ty)) => {
3946 // For HashSet<T>, return failable readable keypath to any element
3947 tokens.extend(quote! {
3948 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
3949 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.iter().next())
3950 }
3951 });
3952 }
3953 (WrapperKind::BTreeSet, Some(inner_ty)) => {
3954 // For BTreeSet<T>, return failable readable keypath to any element
3955 tokens.extend(quote! {
3956 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
3957 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.iter().next())
3958 }
3959 });
3960 }
3961 (WrapperKind::VecDeque, Some(inner_ty)) => {
3962 // For VecDeque<T>, return failable readable keypath to front element
3963 tokens.extend(quote! {
3964 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
3965 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.front())
3966 }
3967 });
3968 }
3969 (WrapperKind::LinkedList, Some(inner_ty)) => {
3970 // For LinkedList<T>, return failable readable keypath to front element
3971 tokens.extend(quote! {
3972 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
3973 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.front())
3974 }
3975 });
3976 }
3977 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
3978 // For BinaryHeap<T>, return failable readable keypath to peek element
3979 tokens.extend(quote! {
3980 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
3981 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.peek())
3982 }
3983 });
3984 }
3985 (WrapperKind::Result, Some(inner_ty)) => {
3986 // For Result<T, E>, return failable readable keypath to Ok value
3987 tokens.extend(quote! {
3988 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
3989 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref().ok())
3990 }
3991 });
3992 }
3993 (WrapperKind::Mutex, Some(inner_ty)) => {
3994 // For Mutex<T>, return readable keypath to the container (not inner type due to lifetime issues)
3995 tokens.extend(quote! {
3996 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
3997 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
3998 }
3999 });
4000 }
4001 (WrapperKind::RwLock, Some(inner_ty)) => {
4002 // For RwLock<T>, return readable keypath to the container (not inner type due to lifetime issues)
4003 tokens.extend(quote! {
4004 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
4005 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4006 }
4007 });
4008 }
4009 (WrapperKind::Weak, Some(inner_ty)) => {
4010 // For Weak<T>, return readable keypath to the container (not inner type due to lifetime issues)
4011 tokens.extend(quote! {
4012 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
4013 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4014 }
4015 });
4016 }
4017 (WrapperKind::None, None) => {
4018 // For basic types, return readable keypath
4019 tokens.extend(quote! {
4020 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
4021 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4022 }
4023 });
4024 }
4025 _ => {
4026 // For unknown types, return readable keypath
4027 tokens.extend(quote! {
4028 pub fn #field_ident() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
4029 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4030 }
4031 });
4032 }
4033 }
4034 }
4035 tokens
4036 }
4037 Fields::Unnamed(unnamed) => {
4038 let mut tokens = proc_macro2::TokenStream::new();
4039 for (idx, field) in unnamed.unnamed.iter().enumerate() {
4040 let idx_lit = syn::Index::from(idx);
4041 let ty = &field.ty;
4042 let field_name = format_ident!("f{}", idx);
4043
4044 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
4045
4046 match (kind, inner_ty.clone()) {
4047 (WrapperKind::Option, Some(inner_ty)) => {
4048 tokens.extend(quote! {
4049 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4050 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.as_ref())
4051 }
4052 });
4053 }
4054 (WrapperKind::Vec, Some(inner_ty)) => {
4055 tokens.extend(quote! {
4056 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4057 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.first())
4058 }
4059 });
4060 }
4061 (WrapperKind::HashMap, Some(inner_ty)) => {
4062 tokens.extend(quote! {
4063 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
4064 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4065 }
4066 });
4067 }
4068 (WrapperKind::BTreeMap, Some(inner_ty)) => {
4069 tokens.extend(quote! {
4070 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
4071 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4072 }
4073 });
4074 }
4075 (WrapperKind::Box, Some(inner_ty)) => {
4076 tokens.extend(quote! {
4077 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4078 rust_keypaths::KeyPath::new(|s: &#name| &*s.#idx_lit)
4079 }
4080 });
4081 }
4082 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
4083 tokens.extend(quote! {
4084 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4085 rust_keypaths::KeyPath::new(|s: &#name| &*s.#idx_lit)
4086 }
4087 });
4088 }
4089 (WrapperKind::HashSet, Some(inner_ty)) => {
4090 tokens.extend(quote! {
4091 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4092 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.iter().next())
4093 }
4094 });
4095 }
4096 (WrapperKind::BTreeSet, Some(inner_ty)) => {
4097 tokens.extend(quote! {
4098 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4099 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.iter().next())
4100 }
4101 });
4102 }
4103 (WrapperKind::VecDeque, Some(inner_ty)) => {
4104 tokens.extend(quote! {
4105 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4106 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.front())
4107 }
4108 });
4109 }
4110 (WrapperKind::LinkedList, Some(inner_ty)) => {
4111 tokens.extend(quote! {
4112 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4113 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.front())
4114 }
4115 });
4116 }
4117 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
4118 tokens.extend(quote! {
4119 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4120 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.peek())
4121 }
4122 });
4123 }
4124 (WrapperKind::Result, Some(inner_ty)) => {
4125 tokens.extend(quote! {
4126 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4127 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.as_ref().ok())
4128 }
4129 });
4130 }
4131 (WrapperKind::Mutex, Some(inner_ty)) => {
4132 tokens.extend(quote! {
4133 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
4134 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4135 }
4136 });
4137 }
4138 (WrapperKind::RwLock, Some(inner_ty)) => {
4139 tokens.extend(quote! {
4140 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
4141 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4142 }
4143 });
4144 }
4145 (WrapperKind::Weak, Some(inner_ty)) => {
4146 tokens.extend(quote! {
4147 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
4148 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4149 }
4150 });
4151 }
4152 (WrapperKind::None, None) => {
4153 tokens.extend(quote! {
4154 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
4155 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4156 }
4157 });
4158 }
4159 _ => {
4160 tokens.extend(quote! {
4161 pub fn #field_name() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
4162 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4163 }
4164 });
4165 }
4166 }
4167 }
4168 tokens
4169 }
4170 _ => quote! {
4171 compile_error!("Keypath derive supports only structs with named or unnamed fields");
4172 },
4173 },
4174 Data::Enum(data_enum) => {
4175 let mut tokens = proc_macro2::TokenStream::new();
4176 for variant in data_enum.variants.iter() {
4177 let v_ident = &variant.ident;
4178 let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
4179
4180 match &variant.fields {
4181 Fields::Unit => {
4182 // Unit variant - return readable keypath to the variant itself
4183 tokens.extend(quote! {
4184 pub fn #snake() -> rust_keypaths::KeyPath<#name, #name, impl for<'r> Fn(&'r #name) -> &'r #name> {
4185 rust_keypaths::KeyPath::new(|s: &#name| s)
4186 }
4187 });
4188 }
4189 Fields::Unnamed(unnamed) => {
4190 if unnamed.unnamed.len() == 1 {
4191 // Single-field tuple variant - smart keypath selection
4192 let field_ty = &unnamed.unnamed[0].ty;
4193 let (kind, inner_ty) = extract_wrapper_inner_type(field_ty);
4194
4195 match (kind, inner_ty.clone()) {
4196 (WrapperKind::Option, Some(inner_ty)) => {
4197 tokens.extend(quote! {
4198 pub fn #snake() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4199 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4200 #name::#v_ident(inner) => inner.as_ref(),
4201 _ => None,
4202 })
4203 }
4204 });
4205 }
4206 (WrapperKind::Vec, Some(inner_ty)) => {
4207 tokens.extend(quote! {
4208 pub fn #snake() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4209 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4210 #name::#v_ident(inner) => inner.first(),
4211 _ => None,
4212 })
4213 }
4214 });
4215 }
4216 (WrapperKind::HashMap, Some(inner_ty)) => {
4217 tokens.extend(quote! {
4218 pub fn #snake() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
4219 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4220 #name::#v_ident(inner) => Some(inner),
4221 _ => None,
4222 })
4223 }
4224 });
4225 }
4226 (WrapperKind::BTreeMap, Some(inner_ty)) => {
4227 tokens.extend(quote! {
4228 pub fn #snake() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
4229 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4230 #name::#v_ident(inner) => Some(inner),
4231 _ => None,
4232 })
4233 }
4234 });
4235 }
4236 (WrapperKind::Box, Some(inner_ty)) => {
4237 tokens.extend(quote! {
4238 pub fn #snake() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4239 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4240 #name::#v_ident(inner) => Some(&**inner),
4241 _ => None,
4242 })
4243 }
4244 });
4245 }
4246 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
4247 tokens.extend(quote! {
4248 pub fn #snake() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4249 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4250 #name::#v_ident(inner) => Some(&**inner),
4251 _ => None,
4252 })
4253 }
4254 });
4255 }
4256 (WrapperKind::HashSet, Some(inner_ty)) => {
4257 tokens.extend(quote! {
4258 pub fn #snake() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4259 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4260 #name::#v_ident(inner) => inner.iter().next(),
4261 _ => None,
4262 })
4263 }
4264 });
4265 }
4266 (WrapperKind::BTreeSet, Some(inner_ty)) => {
4267 tokens.extend(quote! {
4268 pub fn #snake() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4269 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4270 #name::#v_ident(inner) => inner.iter().next(),
4271 _ => None,
4272 })
4273 }
4274 });
4275 }
4276 (WrapperKind::VecDeque, Some(inner_ty)) => {
4277 tokens.extend(quote! {
4278 pub fn #snake() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4279 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4280 #name::#v_ident(inner) => inner.front(),
4281 _ => None,
4282 })
4283 }
4284 });
4285 }
4286 (WrapperKind::LinkedList, Some(inner_ty)) => {
4287 tokens.extend(quote! {
4288 pub fn #snake() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4289 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4290 #name::#v_ident(inner) => inner.front(),
4291 _ => None,
4292 })
4293 }
4294 });
4295 }
4296 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
4297 tokens.extend(quote! {
4298 pub fn #snake() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4299 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4300 #name::#v_ident(inner) => inner.peek(),
4301 _ => None,
4302 })
4303 }
4304 });
4305 }
4306 (WrapperKind::Result, Some(inner_ty)) => {
4307 tokens.extend(quote! {
4308 pub fn #snake() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4309 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4310 #name::#v_ident(inner) => inner.as_ref().ok(),
4311 _ => None,
4312 })
4313 }
4314 });
4315 }
4316 (WrapperKind::Mutex, Some(inner_ty)) => {
4317 tokens.extend(quote! {
4318 pub fn #snake() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
4319 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4320 #name::#v_ident(inner) => Some(inner),
4321 _ => None,
4322 })
4323 }
4324 });
4325 }
4326 (WrapperKind::RwLock, Some(inner_ty)) => {
4327 tokens.extend(quote! {
4328 pub fn #snake() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
4329 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4330 #name::#v_ident(inner) => Some(inner),
4331 _ => None,
4332 })
4333 }
4334 });
4335 }
4336 (WrapperKind::Weak, Some(inner_ty)) => {
4337 tokens.extend(quote! {
4338 pub fn #snake() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
4339 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4340 #name::#v_ident(inner) => Some(inner),
4341 _ => None,
4342 })
4343 }
4344 });
4345 }
4346 (WrapperKind::None, None) => {
4347 // Basic type - return failable readable keypath
4348 tokens.extend(quote! {
4349 pub fn #snake() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
4350 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4351 #name::#v_ident(inner) => Some(inner),
4352 _ => None,
4353 })
4354 }
4355 });
4356 }
4357 _ => {
4358 // Unknown type - return failable readable keypath
4359 tokens.extend(quote! {
4360 pub fn #snake() -> rust_keypaths::KeyPath<#name, #field_ty, impl for<'r> Fn(&'r #name) -> &'r #field_ty> {
4361 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4362 #name::#v_ident(inner) => Some(inner),
4363 _ => None,
4364 })
4365 }
4366 });
4367 }
4368 }
4369 } else {
4370 // Multi-field tuple variant - return failable readable keypath to the variant
4371 tokens.extend(quote! {
4372 pub fn #snake() -> rust_keypaths::KeyPath<#name, #name, impl for<'r> Fn(&'r #name) -> &'r #name> {
4373 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4374 #name::#v_ident(..) => Some(s),
4375 _ => None,
4376 })
4377 }
4378 });
4379 }
4380 }
4381 Fields::Named(_named) => {
4382 // Named field variant - return failable readable keypath to the variant
4383 tokens.extend(quote! {
4384 pub fn #snake() -> rust_keypaths::KeyPath<#name, #name, impl for<'r> Fn(&'r #name) -> &'r #name> {
4385 rust_keypaths::OptionalKeyPath::new(|s: &#name| match s {
4386 #name::#v_ident { .. } => Some(s),
4387 _ => None,
4388 })
4389 }
4390 });
4391 }
4392 }
4393 }
4394 tokens
4395 }
4396 _ => quote! {
4397 compile_error!("Keypath derive supports only structs and enums");
4398 },
4399 };
4400
4401 let expanded = quote! {
4402 impl #name {
4403 #methods
4404 }
4405 };
4406
4407 TokenStream::from(expanded)
4408}
4409
4410#[proc_macro_derive(ReadableKeypaths)]
4411pub fn derive_readable_keypaths(input: TokenStream) -> TokenStream {
4412 let input = parse_macro_input!(input as DeriveInput);
4413 let name = input.ident;
4414
4415 let methods = match input.data {
4416 Data::Struct(data_struct) => match data_struct.fields {
4417 Fields::Named(fields_named) => {
4418 let mut tokens = proc_macro2::TokenStream::new();
4419 for field in fields_named.named.iter() {
4420 let field_ident = field.ident.as_ref().unwrap();
4421 let ty = &field.ty;
4422
4423 let r_fn = format_ident!("{}_r", field_ident);
4424 let fr_fn = format_ident!("{}_fr", field_ident);
4425 let fr_at_fn = format_ident!("{}_fr_at", field_ident);
4426
4427 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
4428
4429 match (kind, inner_ty.clone()) {
4430 (WrapperKind::Option, Some(inner_ty)) => {
4431 tokens.extend(quote! {
4432 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4433 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4434 }
4435 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4436 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref())
4437 }
4438 });
4439 }
4440 (WrapperKind::Vec, Some(inner_ty)) => {
4441 tokens.extend(quote! {
4442 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4443 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4444 }
4445 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4446 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.first())
4447 }
4448 pub fn #fr_at_fn(index: usize) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4449 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(index))
4450 }
4451 });
4452 }
4453 (WrapperKind::HashMap, Some(inner_ty)) => {
4454 tokens.extend(quote! {
4455 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4456 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4457 }
4458 pub fn #fr_fn(key: String) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4459 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(&key))
4460 }
4461 pub fn #fr_at_fn(key: String) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4462 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(&key))
4463 }
4464 });
4465 }
4466 (WrapperKind::Box, Some(inner_ty)) => {
4467 tokens.extend(quote! {
4468 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
4469 rust_keypaths::KeyPath::new(|s: &#name| &*s.#field_ident)
4470 }
4471 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4472 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&*s.#field_ident))
4473 }
4474 });
4475 }
4476 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
4477 tokens.extend(quote! {
4478 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
4479 rust_keypaths::KeyPath::new(|s: &#name| &*s.#field_ident)
4480 }
4481 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4482 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&*s.#field_ident))
4483 }
4484 });
4485 }
4486 (WrapperKind::BTreeMap, Some(inner_ty)) => {
4487 tokens.extend(quote! {
4488 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4489 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4490 }
4491 pub fn #fr_fn(key: String) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4492 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(&key))
4493 }
4494 pub fn #fr_at_fn(key: String) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4495 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(&key))
4496 }
4497 });
4498 }
4499 (WrapperKind::HashSet, Some(inner_ty)) => {
4500 tokens.extend(quote! {
4501 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4502 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4503 }
4504 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4505 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.iter().next())
4506 }
4507 });
4508 }
4509 (WrapperKind::BTreeSet, Some(inner_ty)) => {
4510 tokens.extend(quote! {
4511 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4512 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4513 }
4514 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4515 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.iter().next())
4516 }
4517 });
4518 }
4519 (WrapperKind::VecDeque, Some(inner_ty)) => {
4520 tokens.extend(quote! {
4521 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4522 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4523 }
4524 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4525 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.front())
4526 }
4527 pub fn #fr_at_fn(index: usize) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4528 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(index))
4529 }
4530 });
4531 }
4532 (WrapperKind::LinkedList, Some(inner_ty)) => {
4533 tokens.extend(quote! {
4534 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4535 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4536 }
4537 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4538 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.front())
4539 }
4540 });
4541 }
4542 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
4543 tokens.extend(quote! {
4544 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4545 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4546 }
4547 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4548 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.peek())
4549 }
4550 });
4551 }
4552 (WrapperKind::Result, Some(inner_ty)) => {
4553 tokens.extend(quote! {
4554 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4555 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4556 }
4557 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4558 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref().ok())
4559 }
4560 });
4561 }
4562 (WrapperKind::Mutex, Some(inner_ty)) => {
4563 tokens.extend(quote! {
4564 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4565 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4566 }
4567 // Note: Mutex<T> doesn't support direct access to inner type due to lifetime constraints
4568 // Only providing container-level access
4569 });
4570 }
4571 (WrapperKind::RwLock, Some(inner_ty)) => {
4572 tokens.extend(quote! {
4573 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4574 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4575 }
4576 // Note: RwLock<T> doesn't support direct access to inner type due to lifetime constraints
4577 // Only providing container-level access
4578 });
4579 }
4580 (WrapperKind::Weak, Some(inner_ty)) => {
4581 tokens.extend(quote! {
4582 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4583 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4584 }
4585 // Note: Weak<T> doesn't support direct access to inner type due to lifetime constraints
4586 // Only providing container-level access
4587 });
4588 }
4589 (WrapperKind::None, None) => {
4590 tokens.extend(quote! {
4591 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4592 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4593 }
4594 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
4595 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&s.#field_ident))
4596 }
4597 });
4598 }
4599 _ => {
4600 tokens.extend(quote! {
4601 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4602 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident)
4603 }
4604 });
4605 }
4606 }
4607 }
4608 tokens
4609 }
4610 Fields::Unnamed(unnamed) => {
4611 let mut tokens = proc_macro2::TokenStream::new();
4612 for (idx, field) in unnamed.unnamed.iter().enumerate() {
4613 let idx_lit = syn::Index::from(idx);
4614 let ty = &field.ty;
4615
4616 let r_fn = format_ident!("f{}_r", idx);
4617 let fr_fn = format_ident!("f{}_fr", idx);
4618 let fr_at_fn = format_ident!("f{}_fr_at", idx);
4619
4620 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
4621
4622 match (kind, inner_ty.clone()) {
4623 (WrapperKind::Option, Some(inner_ty)) => {
4624 tokens.extend(quote! {
4625 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4626 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4627 }
4628 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4629 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.as_ref())
4630 }
4631 });
4632 }
4633 (WrapperKind::Vec, Some(inner_ty)) => {
4634 tokens.extend(quote! {
4635 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4636 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4637 }
4638 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4639 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.first())
4640 }
4641 pub fn #fr_at_fn(index: &'static usize) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4642 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.get(*index))
4643 }
4644 });
4645 }
4646 (WrapperKind::HashMap, Some(inner_ty)) => {
4647 tokens.extend(quote! {
4648 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4649 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4650 }
4651 pub fn #fr_fn(key: String) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4652 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#idx_lit.get(&key))
4653 }
4654 pub fn #fr_at_fn(key: String) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4655 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#idx_lit.get(&key))
4656 }
4657 });
4658 }
4659 (WrapperKind::Box, Some(inner_ty)) => {
4660 tokens.extend(quote! {
4661 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
4662 rust_keypaths::KeyPath::new(|s: &#name| &*s.#idx_lit)
4663 }
4664 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4665 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&*s.#idx_lit))
4666 }
4667 });
4668 }
4669 (WrapperKind::Rc, Some(inner_ty)) | (WrapperKind::Arc, Some(inner_ty)) => {
4670 tokens.extend(quote! {
4671 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> &'r #inner_ty> {
4672 rust_keypaths::KeyPath::new(|s: &#name| &*s.#idx_lit)
4673 }
4674 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4675 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&*s.#idx_lit))
4676 }
4677 });
4678 }
4679 (WrapperKind::BTreeMap, Some(inner_ty)) => {
4680 tokens.extend(quote! {
4681 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4682 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4683 }
4684 pub fn #fr_fn(key: String) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4685 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#idx_lit.get(&key))
4686 }
4687 pub fn #fr_at_fn(key: String) -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4688 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#idx_lit.get(&key))
4689 }
4690 });
4691 }
4692 (WrapperKind::HashSet, Some(inner_ty)) => {
4693 tokens.extend(quote! {
4694 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4695 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4696 }
4697 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4698 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.iter().next())
4699 }
4700 });
4701 }
4702 (WrapperKind::BTreeSet, Some(inner_ty)) => {
4703 tokens.extend(quote! {
4704 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4705 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4706 }
4707 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4708 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.iter().next())
4709 }
4710 });
4711 }
4712 (WrapperKind::VecDeque, Some(inner_ty)) => {
4713 tokens.extend(quote! {
4714 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4715 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4716 }
4717 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4718 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.front())
4719 }
4720 });
4721 }
4722 (WrapperKind::LinkedList, Some(inner_ty)) => {
4723 tokens.extend(quote! {
4724 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4725 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4726 }
4727 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4728 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.front())
4729 }
4730 });
4731 }
4732 (WrapperKind::BinaryHeap, Some(inner_ty)) => {
4733 tokens.extend(quote! {
4734 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4735 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4736 }
4737 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4738 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.peek())
4739 }
4740 });
4741 }
4742 (WrapperKind::Result, Some(inner_ty)) => {
4743 tokens.extend(quote! {
4744 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4745 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4746 }
4747 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4748 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#idx_lit.as_ref().ok())
4749 }
4750 });
4751 }
4752 (WrapperKind::Mutex, Some(inner_ty)) => {
4753 tokens.extend(quote! {
4754 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4755 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4756 }
4757 // Note: Mutex<T> doesn't support direct access to inner type due to lifetime constraints
4758 // Only providing container-level access
4759 });
4760 }
4761 (WrapperKind::RwLock, Some(inner_ty)) => {
4762 tokens.extend(quote! {
4763 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4764 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4765 }
4766 // Note: RwLock<T> doesn't support direct access to inner type due to lifetime constraints
4767 // Only providing container-level access
4768 });
4769 }
4770 (WrapperKind::Weak, Some(inner_ty)) => {
4771 tokens.extend(quote! {
4772 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4773 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4774 }
4775 // Note: Weak<T> doesn't support direct access to inner type due to lifetime constraints
4776 // Only providing container-level access
4777 });
4778 }
4779 (WrapperKind::None, None) => {
4780 tokens.extend(quote! {
4781 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4782 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4783 }
4784 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> Option<&'r #ty>> {
4785 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&s.#idx_lit))
4786 }
4787 });
4788 }
4789 _ => {
4790 tokens.extend(quote! {
4791 pub fn #r_fn() -> rust_keypaths::KeyPath<#name, #ty, impl for<'r> Fn(&'r #name) -> &'r #ty> {
4792 rust_keypaths::KeyPath::new(|s: &#name| &s.#idx_lit)
4793 }
4794 });
4795 }
4796 }
4797 }
4798 tokens
4799 }
4800 _ => quote! {
4801 compile_error!("ReadableKeypaths derive supports only structs with named or unnamed fields");
4802 },
4803 },
4804 _ => quote! {
4805 compile_error!("ReadableKeypaths derive supports only structs");
4806 },
4807 };
4808
4809 let expanded = quote! {
4810 impl #name {
4811 #methods
4812 }
4813 };
4814
4815 TokenStream::from(expanded)
4816}
4817
4818#[proc_macro_derive(Casepaths, attributes(Readable, Writable, All))]
4819pub fn derive_casepaths(input: TokenStream) -> TokenStream {
4820 let input = parse_macro_input!(input as DeriveInput);
4821 let name = input.ident;
4822
4823 // Get default scope from attributes
4824 let default_scope = match method_scope_from_attrs(&input.attrs) {
4825 Ok(Some(scope)) => scope,
4826 Ok(None) => MethodScope::Readable, // Default to readable
4827 Err(e) => return e.to_compile_error().into(),
4828 };
4829
4830 let tokens = match input.data {
4831 Data::Enum(data_enum) => {
4832 let mut tokens = proc_macro2::TokenStream::new();
4833 for variant in data_enum.variants.iter() {
4834 let v_ident = &variant.ident;
4835 let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
4836
4837 // Get variant-specific scope
4838 let variant_scope = match method_scope_from_attrs(&variant.attrs) {
4839 Ok(Some(scope)) => scope,
4840 Ok(None) => default_scope.clone(),
4841 Err(_) => default_scope.clone(),
4842 };
4843
4844 let r_fn = format_ident!("{}_case_r", snake);
4845 let w_fn = format_ident!("{}_case_w", snake);
4846 let fr_fn = format_ident!("{}_case_fr", snake);
4847 let fw_fn = format_ident!("{}_case_fw", snake);
4848
4849 match &variant.fields {
4850 Fields::Unit => {
4851 // Unit variants - return OptionalKeyPath that checks if variant matches
4852 if variant_scope.includes_read() {
4853 tokens.extend(quote! {
4854 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, (), impl for<'r> Fn(&'r #name) -> Option<&'r ()>> {
4855 static UNIT: () = ();
4856 rust_keypaths::OptionalKeyPath::new(|e: &#name| match e { #name::#v_ident => Some(&UNIT), _ => None })
4857 }
4858 });
4859 }
4860 }
4861 Fields::Unnamed(unnamed) if unnamed.unnamed.len() == 1 => {
4862 let inner_ty = &unnamed.unnamed.first().unwrap().ty;
4863
4864 // Single-field variant - extract the inner value
4865 // Generate EnumKeyPath for single-field variants to support embedding
4866 if variant_scope.includes_read() {
4867 let embed_fn = format_ident!("{}_case_embed", snake);
4868 let enum_kp_fn = format_ident!("{}_case_enum", snake);
4869 tokens.extend(quote! {
4870 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4871 rust_keypaths::OptionalKeyPath::new(|e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None })
4872 }
4873 // Alias for fr_fn - returns OptionalKeyPath (enum casepaths are always optional)
4874 pub fn #r_fn() -> rust_keypaths::OptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty>> {
4875 rust_keypaths::OptionalKeyPath::new(|e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None })
4876 }
4877 // EnumKeyPath version with embedding support
4878 pub fn #enum_kp_fn() -> rust_keypaths::EnumKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #inner_ty> + 'static, impl Fn(#inner_ty) -> #name + 'static> {
4879 rust_keypaths::EnumKeyPath::readable_enum(
4880 |value: #inner_ty| #name::#v_ident(value),
4881 |e: &#name| match e { #name::#v_ident(v) => Some(v), _ => None }
4882 )
4883 }
4884 // Embed method - creates the enum variant from a value
4885 pub fn #embed_fn(value: #inner_ty) -> #name {
4886 #name::#v_ident(value)
4887 }
4888 });
4889 }
4890 if variant_scope.includes_write() {
4891 tokens.extend(quote! {
4892 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
4893 rust_keypaths::WritableOptionalKeyPath::new(|e: &mut #name| match e { #name::#v_ident(v) => Some(v), _ => None })
4894 }
4895 // Alias for fw_fn - returns WritableOptionalKeyPath (enum casepaths are always optional)
4896 pub fn #w_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #inner_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #inner_ty>> {
4897 rust_keypaths::WritableOptionalKeyPath::new(|e: &mut #name| match e { #name::#v_ident(v) => Some(v), _ => None })
4898 }
4899 });
4900 }
4901 }
4902 // Multi-field tuple variant: Enum::Variant(T1, T2, ...)
4903 Fields::Unnamed(unnamed) => {
4904 let field_types: Vec<_> = unnamed.unnamed.iter().map(|f| &f.ty).collect();
4905 let tuple_ty = quote! { (#(#field_types),*) };
4906
4907 // Generate pattern matching for tuple fields
4908 let field_patterns: Vec<_> = (0..unnamed.unnamed.len())
4909 .map(|i| format_ident!("f{}", i))
4910 .collect();
4911
4912 if variant_scope.includes_read() {
4913 tokens.extend(quote! {
4914 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #tuple_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #tuple_ty>> {
4915 rust_keypaths::OptionalKeyPath::new(|e: &#name| match e { #name::#v_ident(#(#field_patterns),*) => Some(&(#(#field_patterns),*)), _ => None })
4916 }
4917 });
4918 }
4919 if variant_scope.includes_write() {
4920 tokens.extend(quote! {
4921 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #tuple_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #tuple_ty>> {
4922 rust_keypaths::WritableOptionalKeyPath::new(|e: &mut #name| match e { #name::#v_ident(#(#field_patterns),*) => Some((#(#field_patterns),*)), _ => None })
4923 }
4924 });
4925 }
4926 }
4927
4928 // Labeled variant: Enum::Variant { field1: T1, field2: T2, ... }
4929 Fields::Named(named) => {
4930 let field_names: Vec<_> = named.named.iter().map(|f| f.ident.as_ref().unwrap()).collect();
4931 let field_types: Vec<_> = named.named.iter().map(|f| &f.ty).collect();
4932 let tuple_ty = quote! { (#(#field_types),*) };
4933
4934 if variant_scope.includes_read() {
4935 tokens.extend(quote! {
4936 pub fn #fr_fn() -> rust_keypaths::OptionalKeyPath<#name, #tuple_ty, impl for<'r> Fn(&'r #name) -> Option<&'r #tuple_ty>> {
4937 rust_keypaths::OptionalKeyPath::new(|e: &#name| match e { #name::#v_ident { #(#field_names: ref #field_names),* } => Some(&(#(#field_names),*)), _ => None })
4938 }
4939 });
4940 }
4941 if variant_scope.includes_write() {
4942 tokens.extend(quote! {
4943 pub fn #fw_fn() -> rust_keypaths::WritableOptionalKeyPath<#name, #tuple_ty, impl for<'r> Fn(&'r mut #name) -> Option<&'r mut #tuple_ty>> {
4944 rust_keypaths::WritableOptionalKeyPath::new(|e: &mut #name| match e { #name::#v_ident { #(#field_names: ref mut #field_names),* } => Some((#(#field_names),*)), _ => None })
4945 }
4946 });
4947 }
4948 }
4949 }
4950 }
4951 tokens
4952 }
4953 _ => quote! { compile_error!("Casepaths can only be derived for enums"); },
4954 };
4955
4956 let expanded = quote! {
4957 impl #name {
4958 #tokens
4959 }
4960 };
4961
4962 TokenStream::from(expanded)
4963}
4964
4965#[proc_macro_derive(PartialKeypaths)]
4966pub fn derive_partial_keypaths(input: TokenStream) -> TokenStream {
4967 let input = parse_macro_input!(input as DeriveInput);
4968 let name = input.ident;
4969
4970 let methods = match input.data {
4971 Data::Struct(data_struct) => match data_struct.fields {
4972 Fields::Named(fields_named) => {
4973 let mut tokens = proc_macro2::TokenStream::new();
4974 for field in fields_named.named.iter() {
4975 let field_ident = field.ident.as_ref().unwrap();
4976 let ty = &field.ty;
4977
4978 let r_fn = format_ident!("{}_partial_r", field_ident);
4979 let w_fn = format_ident!("{}_partial_w", field_ident);
4980 let fr_fn = format_ident!("{}_partial_fr", field_ident);
4981 let fw_fn = format_ident!("{}_partial_fw", field_ident);
4982 let fr_at_fn = format_ident!("{}_partial_fr_at", field_ident);
4983 let fw_at_fn = format_ident!("{}_partial_fw_at", field_ident);
4984 // Owned keypath method names
4985 let o_fn = format_ident!("{}_partial_o", field_ident);
4986 let fo_fn = format_ident!("{}_partial_fo", field_ident);
4987
4988 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
4989
4990 match (kind, inner_ty.clone()) {
4991 (WrapperKind::Option, Some(inner_ty)) => {
4992 tokens.extend(quote! {
4993 pub fn #r_fn() -> rust_keypaths::PartialOptionalKeyPath<#name> {
4994 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref()).to_partial()
4995 }
4996 pub fn #w_fn() -> rust_keypaths::PartialWritableOptionalKeyPath<#name> {
4997 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.as_mut()).to_partial()
4998 }
4999 pub fn #fr_fn() -> rust_keypaths::PartialOptionalKeyPath<#name> {
5000 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref()).to_partial()
5001 }
5002 pub fn #fw_fn() -> rust_keypaths::PartialWritableOptionalKeyPath<#name> {
5003 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.as_mut()).to_partial()
5004 }
5005 // Owned keypath methods - these don't make sense for Option types
5006 // as we can't return owned values from references
5007 });
5008 }
5009 (WrapperKind::Vec, Some(inner_ty)) => {
5010 tokens.extend(quote! {
5011 pub fn #fr_at_fn(index: usize) -> rust_keypaths::PartialOptionalKeyPath<#name> {
5012 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(index)).to_partial()
5013 }
5014 pub fn #fw_at_fn(index: usize) -> rust_keypaths::PartialWritableOptionalKeyPath<#name> {
5015 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(index)).to_partial()
5016 }
5017 pub fn #r_fn() -> rust_keypaths::PartialKeyPath<#name> {
5018 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident).to_partial()
5019 }
5020 pub fn #w_fn() -> rust_keypaths::PartialWritableKeyPath<#name> {
5021 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident).to_partial()
5022 }
5023 pub fn #fr_fn() -> rust_keypaths::PartialOptionalKeyPath<#name> {
5024 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.first()).to_partial()
5025 }
5026 pub fn #fw_fn() -> rust_keypaths::PartialWritableOptionalKeyPath<#name> {
5027 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.first_mut()).to_partial()
5028 }
5029 // Owned keypath methods - not supported for Vec as we need references
5030 });
5031 }
5032 (WrapperKind::HashMap, Some(inner_ty)) => {
5033 tokens.extend(quote! {
5034 pub fn #r_fn() -> rust_keypaths::PartialKeyPath<#name> {
5035 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident).to_partial()
5036 }
5037 pub fn #w_fn() -> rust_keypaths::PartialWritableKeyPath<#name> {
5038 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident).to_partial()
5039 }
5040 pub fn #fr_fn(key: String) -> rust_keypaths::PartialOptionalKeyPath<#name> {
5041 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(&key)).to_partial()
5042 }
5043 pub fn #fw_fn(key: String) -> rust_keypaths::PartialWritableOptionalKeyPath<#name> {
5044 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(&key)).to_partial()
5045 }
5046 pub fn #fr_at_fn(key: String) -> rust_keypaths::PartialOptionalKeyPath<#name> {
5047 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(&key)).to_partial()
5048 }
5049 pub fn #fw_at_fn(key: String) -> rust_keypaths::PartialWritableOptionalKeyPath<#name> {
5050 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(&key)).to_partial()
5051 }
5052 // Owned keypath methods - not supported for HashMap as we need references
5053 });
5054 }
5055 _ => {
5056 // Default case for simple types
5057 tokens.extend(quote! {
5058 pub fn #r_fn() -> rust_keypaths::PartialKeyPath<#name> {
5059 rust_keypaths::KeyPath::new(|s: &#name| &s.#field_ident).to_partial()
5060 }
5061 pub fn #w_fn() -> rust_keypaths::PartialWritableKeyPath<#name> {
5062 rust_keypaths::WritableKeyPath::new(|s: &mut #name| &mut s.#field_ident).to_partial()
5063 }
5064 // Owned keypath methods - not supported as we need references
5065 });
5066 }
5067 }
5068 }
5069 tokens
5070 }
5071 _ => quote! { compile_error!("PartialKeypaths can only be derived for structs with named fields"); },
5072 },
5073 _ => quote! { compile_error!("PartialKeypaths can only be derived for structs"); },
5074 };
5075
5076 let expanded = quote! {
5077 impl #name {
5078 #methods
5079 }
5080 };
5081
5082 TokenStream::from(expanded)
5083}
5084
5085#[proc_macro_derive(AnyKeypaths)]
5086pub fn derive_any_keypaths(input: TokenStream) -> TokenStream {
5087 let input = parse_macro_input!(input as DeriveInput);
5088 let name = input.ident;
5089
5090 let methods = match input.data {
5091 Data::Struct(data_struct) => match data_struct.fields {
5092 Fields::Named(fields_named) => {
5093 let mut tokens = proc_macro2::TokenStream::new();
5094 for field in fields_named.named.iter() {
5095 let field_ident = field.ident.as_ref().unwrap();
5096 let ty = &field.ty;
5097
5098 let r_fn = format_ident!("{}_any_r", field_ident);
5099 let w_fn = format_ident!("{}_any_w", field_ident);
5100 let fr_fn = format_ident!("{}_any_fr", field_ident);
5101 let fw_fn = format_ident!("{}_any_fw", field_ident);
5102 let fr_at_fn = format_ident!("{}_any_fr_at", field_ident);
5103 let fw_at_fn = format_ident!("{}_any_fw_at", field_ident);
5104 // Owned keypath method names
5105 let o_fn = format_ident!("{}_any_o", field_ident);
5106 let fo_fn = format_ident!("{}_any_fo", field_ident);
5107
5108 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
5109
5110 match (kind, inner_ty.clone()) {
5111 (WrapperKind::Option, Some(inner_ty)) => {
5112 tokens.extend(quote! {
5113 pub fn #r_fn() -> rust_keypaths::AnyKeyPath {
5114 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref()).to_any()
5115 }
5116 pub fn #w_fn() -> rust_keypaths::AnyWritableKeyPath {
5117 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.as_mut()).to_any()
5118 }
5119 pub fn #fr_fn() -> rust_keypaths::AnyKeyPath {
5120 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.as_ref()).to_any()
5121 }
5122 pub fn #fw_fn() -> rust_keypaths::AnyWritableKeyPath {
5123 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.as_mut()).to_any()
5124 }
5125 // Owned keypath methods - not supported for Option types
5126 });
5127 }
5128 (WrapperKind::Vec, Some(inner_ty)) => {
5129 tokens.extend(quote! {
5130 pub fn #fr_at_fn(index: usize) -> rust_keypaths::AnyKeyPath {
5131 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(index)).to_any()
5132 }
5133 pub fn #fw_at_fn(index: usize) -> rust_keypaths::AnyWritableKeyPath {
5134 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(index)).to_any()
5135 }
5136 pub fn #r_fn() -> rust_keypaths::AnyKeyPath {
5137 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&s.#field_ident)).to_any()
5138 }
5139 pub fn #w_fn() -> rust_keypaths::AnyWritableKeyPath {
5140 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| Some(&mut s.#field_ident)).to_any()
5141 }
5142 pub fn #fr_fn() -> rust_keypaths::AnyKeyPath {
5143 rust_keypaths::OptionalKeyPath::new(|s: &#name| s.#field_ident.first()).to_any()
5144 }
5145 pub fn #fw_fn() -> rust_keypaths::AnyWritableKeyPath {
5146 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| s.#field_ident.first_mut()).to_any()
5147 }
5148 // Owned keypath methods - not supported for Vec
5149 });
5150 }
5151 (WrapperKind::HashMap, Some(inner_ty)) => {
5152 tokens.extend(quote! {
5153 pub fn #r_fn() -> rust_keypaths::AnyKeyPath {
5154 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&s.#field_ident)).to_any()
5155 }
5156 pub fn #w_fn() -> rust_keypaths::AnyWritableKeyPath {
5157 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| Some(&mut s.#field_ident)).to_any()
5158 }
5159 pub fn #fr_fn(key: String) -> rust_keypaths::AnyKeyPath {
5160 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(&key)).to_any()
5161 }
5162 pub fn #fw_fn(key: String) -> rust_keypaths::AnyWritableKeyPath {
5163 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(&key)).to_any()
5164 }
5165 pub fn #fr_at_fn(key: String) -> rust_keypaths::AnyKeyPath {
5166 rust_keypaths::OptionalKeyPath::new(move |s: &#name| s.#field_ident.get(&key)).to_any()
5167 }
5168 pub fn #fw_at_fn(key: String) -> rust_keypaths::AnyWritableKeyPath {
5169 rust_keypaths::WritableOptionalKeyPath::new(move |s: &mut #name| s.#field_ident.get_mut(&key)).to_any()
5170 }
5171 // Owned keypath methods - not supported for HashMap
5172 });
5173 }
5174 _ => {
5175 // Default case for simple types
5176 tokens.extend(quote! {
5177 pub fn #r_fn() -> rust_keypaths::AnyKeyPath {
5178 rust_keypaths::OptionalKeyPath::new(|s: &#name| Some(&s.#field_ident)).to_any()
5179 }
5180 pub fn #w_fn() -> rust_keypaths::AnyWritableKeyPath {
5181 rust_keypaths::WritableOptionalKeyPath::new(|s: &mut #name| Some(&mut s.#field_ident)).to_any()
5182 }
5183 // Owned keypath methods - not supported as we need references
5184 });
5185 }
5186 }
5187 }
5188 tokens
5189 }
5190 _ => quote! { compile_error!("AnyKeypaths can only be derived for structs with named fields"); },
5191 },
5192 _ => quote! { compile_error!("AnyKeypaths can only be derived for structs"); },
5193 };
5194
5195 let expanded = quote! {
5196 impl #name {
5197 #methods
5198 }
5199 };
5200
5201 TokenStream::from(expanded)
5202}
5203
5204// /// A helper macro that provides suggestions when there are type mismatches with container types.
5205// /// This macro helps users understand when to use adapter methods like for_arc(), for_box(), etc.
5206// #[proc_macro]
5207// pub fn keypath_suggestion(input: TokenStream) -> TokenStream {
5208// let input_str = input.to_string();
5209//
5210// // Parse the input to understand what the user is trying to do
5211// let suggestion = if input_str.contains("Arc<") && input_str.contains("KeyPaths<") {
5212// "💡 Suggestion: If you have a KeyPaths<SomeStruct, Value> but need KeyPaths<Arc<SomeStruct>, Value>, use the .for_arc() adapter method:\n let arc_keypath = your_keypath.for_arc();"
5213// } else if input_str.contains("Box<") && input_str.contains("KeyPaths<") {
5214// "💡 Suggestion: If you have a KeyPaths<SomeStruct, Value> but need KeyPaths<Box<SomeStruct>, Value>, use the .for_box() adapter method:\n let box_keypath = your_keypath.for_box();"
5215// } else if input_str.contains("Rc<") && input_str.contains("KeyPaths<") {
5216// "💡 Suggestion: If you have a KeyPaths<SomeStruct, Value> but need KeyPaths<Rc<SomeStruct>, Value>, use the .for_rc() adapter method:\n let rc_keypath = your_keypath.for_rc();"
5217// } else if input_str.contains("Option<") && input_str.contains("KeyPaths<") {
5218// "💡 Suggestion: If you have a KeyPaths<SomeStruct, Value> but need KeyPaths<Option<SomeStruct>, Value>, use the .for_option() adapter method:\n let option_keypath = your_keypath.for_option();"
5219// } else if input_str.contains("Result<") && input_str.contains("KeyPaths<") {
5220// "💡 Suggestion: If you have a KeyPaths<SomeStruct, Value> but need KeyPaths<Result<SomeStruct, E>, Value>, use the .for_result() adapter method:\n let result_keypath = your_keypath.for_result();"
5221// } else if input_str.contains("Mutex<") && input_str.contains("KeyPaths<") {
5222// "💡 Suggestion: For Mutex<T> containers, use the .with_mutex() method from WithContainer trait (no cloning):\n use rust_keypaths::WithContainer;\n your_keypath.with_mutex(&mutex, |value| { /* work with value */ });"
5223// } else if input_str.contains("RwLock<") && input_str.contains("KeyPaths<") {
5224// "💡 Suggestion: For RwLock<T> containers, use the .with_rwlock() method from WithContainer trait (no cloning):\n use rust_keypaths::WithContainer;\n your_keypath.with_rwlock(&rwlock, |value| { /* work with value */ });"
5225// } else {
5226// "💡 Suggestion: Use adapter methods to work with different container types:\n - .for_arc() for Arc<T>\n - .for_box() for Box<T>\n - .for_rc() for Rc<T>\n - .for_option() for Option<T>\n - .for_result() for Result<T, E>\n - .with_mutex() for Mutex<T> (import WithContainer trait)\n - .with_rwlock() for RwLock<T> (import WithContainer trait)\n - .for_arc_mutex() for Arc<Mutex<T>> (with parking_lot feature)\n - .for_arc_rwlock() for Arc<RwLock<T>> (with parking_lot feature)"
5227// };
5228//
5229// let expanded = quote! {
5230// compile_error!(#suggestion);
5231// };
5232//
5233// TokenStream::from(expanded)
5234// }
5235
5236// /// A helper macro that provides compile-time suggestions for common KeyPaths usage patterns.
5237// /// This macro can be used to get helpful error messages when there are type mismatches.
5238// #[proc_macro]
5239// pub fn keypath_help(input: TokenStream) -> TokenStream {
5240// let input_str = input.to_string();
5241//
5242// let help_message = if input_str.is_empty() {
5243// "🔧 KeyPaths Help: Use adapter methods to work with different container types:\n - .for_arc() for Arc<T> containers\n - .for_box() for Box<T> containers\n - .for_rc() for Rc<T> containers\n - .for_option() for Option<T> containers\n - .for_result() for Result<T, E> containers\n - .with_mutex() for Mutex<T> containers (import WithContainer trait)\n - .with_rwlock() for RwLock<T> containers (import WithContainer trait)\n - .for_arc_mutex() for Arc<Mutex<T>> containers (with parking_lot feature)\n - .for_arc_rwlock() for Arc<RwLock<T>> containers (with parking_lot feature)\n\nExample: let arc_keypath = my_keypath.for_arc();\nFor Mutex/RwLock: use rust_keypaths::WithContainer; then my_keypath.with_mutex(&mutex, |value| { ... });\nFor Arc<Mutex>/Arc<RwLock>: let arc_mutex_keypath = my_keypath.for_arc_mutex();".to_string()
5244// } else {
5245// format!("🔧 KeyPaths Help for '{}': Use adapter methods to work with different container types. See documentation for more details.", input_str)
5246// };
5247//
5248// let expanded = quote! {
5249// compile_error!(#help_message);
5250// };
5251//
5252// TokenStream::from(expanded)
5253// }