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