key_paths_derive/lib.rs
1use proc_macro::TokenStream;
2use quote::{ToTokens, format_ident, quote};
3use syn::{Data, DeriveInput, Fields, Type, 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 // Reference counting with weak references
23 Weak,
24 // String and owned text
25 String,
26 OptionString,
27 // Interior mutability (std::cell)
28 Cell,
29 RefCell,
30 OptionCell,
31 OptionRefCell,
32 // Lazy init (once_cell, std::sync::OnceLock, std::sync::LazyLock)
33 OnceCell,
34 Lazy,
35 OptionOnceCell,
36 OptionLazy,
37 // Marker / zero-size
38 PhantomData,
39 OptionPhantomData,
40 // Range iterators (std::ops::Range, RangeInclusive)
41 Range,
42 OptionRange,
43 // Nested container support
44 OptionBox,
45 OptionRc,
46 OptionArc,
47 BoxOption,
48 RcOption,
49 ArcOption,
50 VecOption,
51 OptionVec,
52 VecDequeOption,
53 OptionVecDeque,
54 LinkedListOption,
55 OptionLinkedList,
56 BinaryHeapOption,
57 OptionBinaryHeap,
58 HashSetOption,
59 OptionHashSet,
60 BTreeSetOption,
61 OptionBTreeSet,
62 ResultOption,
63 OptionResult,
64 HashMapOption,
65 OptionHashMap,
66 BTreeMapOption,
67 OptionBTreeMap,
68 // Arc with synchronization primitives (default)
69 StdArcMutex,
70 StdArcRwLock,
71 StdArcMutexOption,
72 StdArcRwLockOption,
73 OptionStdArcMutex,
74 OptionStdArcRwLock,
75 // Synchronization primitives default
76 StdMutex,
77 StdRwLock,
78 StdMutexOption,
79 StdRwLockOption,
80 OptionStdMutex,
81 OptionStdRwLock,
82 // Synchronization primitives (parking_lot)
83 Mutex,
84 RwLock,
85 OptionMutex,
86 OptionRwLock,
87 // Synchronization primitives (tokio::sync - requires tokio feature)
88 TokioMutex,
89 TokioRwLock,
90 // parking_lot
91 ArcMutex,
92 ArcRwLock,
93 ArcMutexOption,
94 ArcRwLockOption,
95 OptionArcMutex,
96 OptionArcRwLock,
97 MutexOption,
98 RwLockOption,
99 // Arc with synchronization primitives (tokio::sync - requires tokio feature)
100 TokioArcMutex,
101 TokioArcRwLock,
102 OptionTokioArcMutex,
103 OptionTokioArcRwLock,
104 // arc-swap (`arc-swap` feature): derive emits `SyncKp` only — struct `field()`, enum variant `snake()` (no `field_kp()`, no `*_lock()` suffix).
105 /// `arc_swap::ArcSwap<T>` or `ArcSwapAny<Arc<T>>` (bare; nested under `Arc<…>`)
106 BareArcSwap,
107 /// `arc_swap::ArcSwapOption<T>` or `ArcSwapAny<Option<Arc<T>>>` (bare)
108 BareArcSwapOption,
109 /// `Arc<arc_swap::ArcSwap<T>>` (requires rust-key-paths `arc-swap` feature)
110 ArcArcSwap,
111 /// `Arc<arc_swap::ArcSwapOption<T>>`
112 ArcArcSwapOption,
113 OptionArcArcSwap,
114 OptionArcArcSwapOption,
115 // Tagged types
116 Tagged,
117 OptionTagged,
118 // Clone-on-write (std::borrow::Cow)
119 Cow,
120 OptionCow,
121 // Reference types (&T, &str, &[T], etc.)
122 Reference,
123 OptionReference,
124 // Atomic types (std::sync::atomic::*)
125 Atomic,
126 OptionAtomic,
127 // Pin types
128 Pin,
129 PinBox,
130 /// Field marked with #[pin] - plain type (pin_project pattern)
131 PinnedField,
132 /// Field marked with #[pin] - Future type (pin_project pattern)
133 PinnedFuture,
134 /// Field marked with #[pin] - Box<dyn Future> (pin_project pattern)
135 PinnedBoxFuture,
136}
137
138/// Helper function to check if a type path is exactly under std::sync (not lock_api or parking_lot).
139/// Requires the path to start with "std" then "sync" so we don't confuse with RwLock<RawRwLock, T> (lock_api).
140fn is_std_sync_type(path: &syn::Path) -> bool {
141 let segments: Vec<_> = path.segments.iter().map(|s| s.ident.to_string()).collect();
142 segments.len() >= 2
143 && segments.get(0).map(|s| s.as_str()) == Some("std")
144 && segments.get(1).map(|s| s.as_str()) == Some("sync")
145}
146
147/// Helper function to check if a type path is exactly under tokio::sync.
148fn is_tokio_sync_type(path: &syn::Path) -> bool {
149 let segments: Vec<_> = path.segments.iter().map(|s| s.ident.to_string()).collect();
150 segments.len() >= 2
151 && segments.get(0).map(|s| s.as_str()) == Some("tokio")
152 && segments.get(1).map(|s| s.as_str()) == Some("sync")
153}
154
155/// Helper function to check if a type path is under parking_lot (RwLock/Mutex from lock_api).
156/// Use so we never treat parking_lot::RwLock as std::sync::RwLock.
157fn is_parking_lot_type(path: &syn::Path) -> bool {
158 path.segments.first().map(|s| s.ident == "parking_lot") == Some(true)
159}
160
161/// True if `path` starts with the `arc_swap` or `arcswap` crate alias (hyphenated dep `arc-swap` → `arc_swap`).
162fn is_arcswap_crate_path(path: &syn::Path) -> bool {
163 path.segments.first().is_some_and(|s| {
164 matches!(
165 s.ident.to_string().as_str(),
166 "arc_swap" | "arcswap"
167 )
168 })
169}
170
171fn angle_bracket_first_type(args: &syn::PathArguments) -> Option<&syn::Type> {
172 match args {
173 syn::PathArguments::AngleBracketed(ab) => ab.args.iter().find_map(|a| match a {
174 syn::GenericArgument::Type(t) => Some(t),
175 _ => None,
176 }),
177 _ => None,
178 }
179}
180
181/// Classify `ArcSwapAny<P>` payloads: `Arc<T>` → bare ArcSwap (`ArcSwap<T>`), `Option<Arc<T>>` → ArcSwapOption.
182fn arc_swap_any_payload_kind(payload: &Type) -> Option<(WrapperKind, Type)> {
183 let syn::Type::Path(tp) = payload else {
184 return None;
185 };
186 let seg = tp.path.segments.last()?;
187 match seg.ident.to_string().as_str() {
188 "Arc" => {
189 let t = angle_bracket_first_type(&seg.arguments)?.clone();
190 Some((WrapperKind::BareArcSwap, t))
191 }
192 "Option" => {
193 let opt_inner = angle_bracket_first_type(&seg.arguments)?;
194 let syn::Type::Path(tp2) = opt_inner else {
195 return None;
196 };
197 let seg2 = tp2.path.segments.last()?;
198 if seg2.ident == "Arc" {
199 let t = angle_bracket_first_type(&seg2.arguments)?.clone();
200 Some((WrapperKind::BareArcSwapOption, t))
201 } else {
202 None
203 }
204 }
205 _ => None,
206 }
207}
208
209/// First path segment before `ArcSwap` / `ArcSwapOption` in `Arc<…>` or `Option<Arc<…>>` fields.
210fn arc_swap_crate_ident_from_container_ty(ty: &syn::Type) -> syn::Ident {
211 fn peel(ty: &syn::Type) -> Option<syn::Ident> {
212 let syn::Type::Path(tp) = ty else {
213 return None;
214 };
215 let seg = tp.path.segments.last()?;
216 match seg.ident.to_string().as_str() {
217 "Option" => {
218 let inner = angle_bracket_first_type(&seg.arguments)?;
219 peel(inner)
220 }
221 "Arc" => {
222 let inner = angle_bracket_first_type(&seg.arguments)?;
223 let syn::Type::Path(inner_tp) = inner else {
224 return None;
225 };
226 let inner_seg = inner_tp.path.segments.last()?;
227 if matches!(
228 inner_seg.ident.to_string().as_str(),
229 "ArcSwap" | "ArcSwapOption" | "ArcSwapAny"
230 ) {
231 inner_tp.path.segments.first().map(|s| s.ident.clone())
232 } else {
233 None
234 }
235 }
236 _ => None,
237 }
238 }
239 peel(ty).unwrap_or_else(|| format_ident!("arc_swap"))
240}
241
242/// Helper function to check if a type path is under std::sync::atomic (strict prefix).
243fn is_std_sync_atomic_type(path: &syn::Path) -> bool {
244 let segments: Vec<_> = path.segments.iter().map(|s| s.ident.to_string()).collect();
245 segments.len() >= 3
246 && segments.get(0).map(|s| s.as_str()) == Some("std")
247 && segments.get(1).map(|s| s.as_str()) == Some("sync")
248 && segments.get(2).map(|s| s.as_str()) == Some("atomic")
249}
250
251/// Atomic type idents (no type params): AtomicBool, AtomicI8, etc.
252const ATOMIC_TYPE_IDENTS: &[&str] = &[
253 "AtomicBool",
254 "AtomicI8",
255 "AtomicI16",
256 "AtomicI32",
257 "AtomicI64",
258 "AtomicI128",
259 "AtomicIsize",
260 "AtomicU8",
261 "AtomicU16",
262 "AtomicU32",
263 "AtomicU64",
264 "AtomicU128",
265 "AtomicUsize",
266];
267
268fn extract_wrapper_inner_type(ty: &Type) -> (WrapperKind, Option<Type>) {
269 use syn::{GenericArgument, PathArguments};
270
271 // Handle reference types: &T, &'a str, &[T], etc.
272 if let Type::Reference(tr) = ty {
273 return (WrapperKind::Reference, Some((*tr.elem).clone()));
274 }
275
276 if let Type::Path(tp) = ty {
277 // Check if this is explicitly a std::sync type
278 let is_std_sync = is_std_sync_type(&tp.path);
279 // Check if this is explicitly a tokio::sync type
280 let is_tokio_sync = is_tokio_sync_type(&tp.path);
281
282 if let Some(seg) = tp.path.segments.last() {
283 let ident_str = seg.ident.to_string();
284
285 if let PathArguments::AngleBracketed(ab) = &seg.arguments {
286 let args: Vec<_> = ab.args.iter().collect();
287
288 // Handle map types (HashMap, BTreeMap) - they have K, V parameters
289 if ident_str == "HashMap" || ident_str == "BTreeMap" {
290 if let (Some(_key_arg), Some(value_arg)) = (args.get(0), args.get(1)) {
291 if let GenericArgument::Type(inner) = value_arg {
292 // Check for nested Option in map values
293 let (inner_kind, inner_inner) = extract_wrapper_inner_type(inner);
294 match (ident_str.as_str(), inner_kind) {
295 ("HashMap", WrapperKind::Option) => {
296 return (WrapperKind::HashMapOption, inner_inner);
297 }
298 ("BTreeMap", WrapperKind::Option) => {
299 return (WrapperKind::BTreeMapOption, inner_inner);
300 }
301 _ => {
302 return match ident_str.as_str() {
303 "HashMap" => (WrapperKind::HashMap, Some(inner.clone())),
304 "BTreeMap" => (WrapperKind::BTreeMap, Some(inner.clone())),
305 _ => (WrapperKind::None, None),
306 };
307 }
308 }
309 }
310 }
311 }
312 // Handle Cow<'a, B> - has lifetime then type parameter
313 else if ident_str == "Cow" {
314 if let Some(inner) = args.iter().find_map(|arg| {
315 if let GenericArgument::Type(t) = arg {
316 Some(t.clone())
317 } else {
318 None
319 }
320 }) {
321 return (WrapperKind::Cow, Some(inner));
322 }
323 }
324 // Handle single-parameter container types
325 else if let Some(arg) = args.get(0) {
326 if let GenericArgument::Type(inner) = arg {
327 // Check for nested containers first
328 let (inner_kind, inner_inner) = extract_wrapper_inner_type(inner);
329
330 // Handle nested combinations
331 match (ident_str.as_str(), inner_kind) {
332 ("Option", WrapperKind::Box) => {
333 return (WrapperKind::OptionBox, inner_inner);
334 }
335 ("Option", WrapperKind::Rc) => {
336 return (WrapperKind::OptionRc, inner_inner);
337 }
338 ("Option", WrapperKind::ArcArcSwap) => {
339 return (WrapperKind::OptionArcArcSwap, inner_inner);
340 }
341 ("Option", WrapperKind::ArcArcSwapOption) => {
342 return (WrapperKind::OptionArcArcSwapOption, inner_inner);
343 }
344 ("Option", WrapperKind::Arc) => {
345 return (WrapperKind::OptionArc, inner_inner);
346 }
347 ("Option", WrapperKind::Vec) => {
348 return (WrapperKind::OptionVec, inner_inner);
349 }
350 ("Option", WrapperKind::HashMap) => {
351 return (WrapperKind::OptionHashMap, inner_inner);
352 }
353 ("Option", WrapperKind::BTreeMap) => {
354 return (WrapperKind::OptionBTreeMap, inner_inner);
355 }
356 ("Option", WrapperKind::VecDeque) => {
357 return (WrapperKind::OptionVecDeque, inner_inner);
358 }
359 ("Option", WrapperKind::LinkedList) => {
360 return (WrapperKind::OptionLinkedList, inner_inner);
361 }
362 ("Option", WrapperKind::BinaryHeap) => {
363 return (WrapperKind::OptionBinaryHeap, inner_inner);
364 }
365 ("Option", WrapperKind::HashSet) => {
366 return (WrapperKind::OptionHashSet, inner_inner);
367 }
368 ("Option", WrapperKind::BTreeSet) => {
369 return (WrapperKind::OptionBTreeSet, inner_inner);
370 }
371 ("Option", WrapperKind::Result) => {
372 return (WrapperKind::OptionResult, inner_inner);
373 }
374 ("Option", WrapperKind::StdArcMutex) => {
375 return (WrapperKind::OptionStdArcMutex, inner_inner);
376 }
377 ("Option", WrapperKind::StdArcRwLock) => {
378 return (WrapperKind::OptionStdArcRwLock, inner_inner);
379 }
380 ("Option", WrapperKind::ArcMutex) => {
381 return (WrapperKind::OptionArcMutex, inner_inner);
382 }
383 ("Option", WrapperKind::ArcRwLock) => {
384 return (WrapperKind::OptionArcRwLock, inner_inner);
385 }
386 ("Option", WrapperKind::StdMutex) => {
387 return (WrapperKind::OptionStdMutex, inner_inner);
388 }
389 ("Option", WrapperKind::StdRwLock) => {
390 return (WrapperKind::OptionStdRwLock, inner_inner);
391 }
392 ("Option", WrapperKind::Mutex) => {
393 return (WrapperKind::OptionMutex, inner_inner);
394 }
395 ("Option", WrapperKind::RwLock) => {
396 return (WrapperKind::OptionRwLock, inner_inner);
397 }
398 ("Option", WrapperKind::TokioArcMutex) => {
399 return (WrapperKind::OptionTokioArcMutex, inner_inner);
400 }
401 ("Option", WrapperKind::TokioArcRwLock) => {
402 return (WrapperKind::OptionTokioArcRwLock, inner_inner);
403 }
404 ("Option", WrapperKind::Cow) => {
405 return (WrapperKind::OptionCow, inner_inner);
406 }
407 ("Option", WrapperKind::Tagged) => {
408 return (WrapperKind::OptionTagged, inner_inner);
409 }
410 ("Option", WrapperKind::Reference) => {
411 return (WrapperKind::OptionReference, Some(inner.clone()));
412 }
413 ("Option", WrapperKind::Atomic) => {
414 return (WrapperKind::OptionAtomic, Some(inner.clone()));
415 }
416 ("Option", WrapperKind::String) => {
417 return (WrapperKind::OptionString, None);
418 }
419 ("Option", WrapperKind::Cell) => {
420 return (WrapperKind::OptionCell, inner_inner);
421 }
422 ("Option", WrapperKind::RefCell) => {
423 return (WrapperKind::OptionRefCell, inner_inner);
424 }
425 ("Option", WrapperKind::OnceCell) => {
426 return (WrapperKind::OptionOnceCell, inner_inner);
427 }
428 ("Option", WrapperKind::Lazy) => {
429 return (WrapperKind::OptionLazy, inner_inner);
430 }
431 ("Option", WrapperKind::PhantomData) => {
432 return (WrapperKind::OptionPhantomData, inner_inner);
433 }
434 ("Option", WrapperKind::Range) => {
435 return (WrapperKind::OptionRange, inner_inner);
436 }
437 ("Pin", WrapperKind::Box) => {
438 return (WrapperKind::PinBox, inner_inner);
439 }
440 ("Box", WrapperKind::Option) => {
441 return (WrapperKind::BoxOption, inner_inner);
442 }
443 ("Rc", WrapperKind::Option) => {
444 return (WrapperKind::RcOption, inner_inner);
445 }
446 ("Arc", WrapperKind::Option) => {
447 return (WrapperKind::ArcOption, inner_inner);
448 }
449 ("Vec", WrapperKind::Option) => {
450 return (WrapperKind::VecOption, inner_inner);
451 }
452 ("VecDeque", WrapperKind::Option) => {
453 return (WrapperKind::VecDequeOption, inner_inner);
454 }
455 ("LinkedList", WrapperKind::Option) => {
456 return (WrapperKind::LinkedListOption, inner_inner);
457 }
458 ("BinaryHeap", WrapperKind::Option) => {
459 return (WrapperKind::BinaryHeapOption, inner_inner);
460 }
461 ("HashSet", WrapperKind::Option) => {
462 return (WrapperKind::HashSetOption, inner_inner);
463 }
464 ("BTreeSet", WrapperKind::Option) => {
465 return (WrapperKind::BTreeSetOption, inner_inner);
466 }
467 ("Result", WrapperKind::Option) => {
468 return (WrapperKind::ResultOption, inner_inner);
469 }
470 ("HashMap", WrapperKind::Option) => {
471 return (WrapperKind::HashMapOption, inner_inner);
472 }
473 // BTreeMapOption is handled in the map block (HashMap/BTreeMap)
474 // Mutex<Option<T>> / RwLock<Option<T>> (yields SyncKp value T)
475 // std::sync::Mutex<Option<T>> / RwLock<Option<T>>
476 ("Mutex", WrapperKind::Option) if is_std_sync_type(&tp.path) => {
477 return (WrapperKind::StdMutexOption, inner_inner);
478 }
479 ("RwLock", WrapperKind::Option) if is_std_sync_type(&tp.path) => {
480 return (WrapperKind::StdRwLockOption, inner_inner);
481 }
482 // parking_lot::Mutex<Option<T>> / RwLock<Option<T>>, and bare Mutex/RwLock assumed parking_lot
483 ("Mutex", WrapperKind::Option) => {
484 return (WrapperKind::MutexOption, inner_inner);
485 }
486 ("RwLock", WrapperKind::Option) => {
487 return (WrapperKind::RwLockOption, inner_inner);
488 }
489 // std::sync variants (when inner is StdMutex/StdRwLock)
490 ("Arc", WrapperKind::StdMutex) => {
491 return (WrapperKind::StdArcMutex, inner_inner);
492 }
493 ("Arc", WrapperKind::StdRwLock) => {
494 return (WrapperKind::StdArcRwLock, inner_inner);
495 }
496 ("Arc", WrapperKind::StdMutexOption) => {
497 return (WrapperKind::StdArcMutexOption, inner_inner);
498 }
499 ("Arc", WrapperKind::StdRwLockOption) => {
500 return (WrapperKind::StdArcRwLockOption, inner_inner);
501 }
502 // parking_lot variants (default - when inner is Mutex/RwLock without std::sync prefix)
503 ("Arc", WrapperKind::Mutex) => {
504 return (WrapperKind::ArcMutex, inner_inner);
505 }
506 ("Arc", WrapperKind::RwLock) => {
507 return (WrapperKind::ArcRwLock, inner_inner);
508 }
509 ("Arc", WrapperKind::MutexOption) => {
510 return (WrapperKind::ArcMutexOption, inner_inner);
511 }
512 ("Arc", WrapperKind::RwLockOption) => {
513 return (WrapperKind::ArcRwLockOption, inner_inner);
514 }
515 // tokio::sync variants (when inner is TokioMutex/TokioRwLock)
516 ("Arc", WrapperKind::TokioMutex) => {
517 return (WrapperKind::TokioArcMutex, inner_inner);
518 }
519 ("Arc", WrapperKind::TokioRwLock) => {
520 return (WrapperKind::TokioArcRwLock, inner_inner);
521 }
522 ("Arc", WrapperKind::BareArcSwap) => {
523 return (WrapperKind::ArcArcSwap, inner_inner);
524 }
525 ("Arc", WrapperKind::BareArcSwapOption) => {
526 return (WrapperKind::ArcArcSwapOption, inner_inner);
527 }
528 _ => {
529 // Handle single-level containers
530 // For Mutex and RwLock:
531 // - If path contains std::sync, it's std::sync (StdMutex/StdRwLock)
532 // - Otherwise, default to parking_lot (Mutex/RwLock)
533 return match ident_str.as_str() {
534 "Option" => (WrapperKind::Option, Some(inner.clone())),
535 "Box" => (WrapperKind::Box, Some(inner.clone())),
536 "Rc" => (WrapperKind::Rc, Some(inner.clone())),
537 "Arc" => (WrapperKind::Arc, Some(inner.clone())),
538 "Vec" => (WrapperKind::Vec, Some(inner.clone())),
539 "HashSet" => (WrapperKind::HashSet, Some(inner.clone())),
540 "BTreeSet" => (WrapperKind::BTreeSet, Some(inner.clone())),
541 "VecDeque" => (WrapperKind::VecDeque, Some(inner.clone())),
542 "LinkedList" => (WrapperKind::LinkedList, Some(inner.clone())),
543 "BinaryHeap" => (WrapperKind::BinaryHeap, Some(inner.clone())),
544 "Result" => (WrapperKind::Result, Some(inner.clone())),
545 // Explicit parking_lot path (lock_api::RwLock) — never treat as std
546 "Mutex" if is_parking_lot_type(&tp.path) => {
547 (WrapperKind::Mutex, Some(inner.clone()))
548 }
549 "RwLock" if is_parking_lot_type(&tp.path) => {
550 (WrapperKind::RwLock, Some(inner.clone()))
551 }
552 // std::sync::Mutex and std::sync::RwLock only when path starts with std::sync
553 "Mutex" if is_std_sync => {
554 (WrapperKind::StdMutex, Some(inner.clone()))
555 }
556 "RwLock" if is_std_sync => {
557 (WrapperKind::StdRwLock, Some(inner.clone()))
558 }
559 // tokio::sync::Mutex and tokio::sync::RwLock
560 "Mutex" if is_tokio_sync => {
561 (WrapperKind::TokioMutex, Some(inner.clone()))
562 }
563 "RwLock" if is_tokio_sync => {
564 (WrapperKind::TokioRwLock, Some(inner.clone()))
565 }
566 // Default: parking_lot (bare Mutex/RwLock or unknown path)
567 "Mutex" => (WrapperKind::Mutex, Some(inner.clone())),
568 "RwLock" => (WrapperKind::RwLock, Some(inner.clone())),
569 "ArcSwap" if is_arcswap_crate_path(&tp.path) => {
570 (WrapperKind::BareArcSwap, Some(inner.clone()))
571 }
572 "ArcSwapOption" if is_arcswap_crate_path(&tp.path) => {
573 (WrapperKind::BareArcSwapOption, Some(inner.clone()))
574 }
575 "ArcSwapAny" if is_arcswap_crate_path(&tp.path) => {
576 if let Some((kind, peeled)) =
577 arc_swap_any_payload_kind(inner)
578 {
579 (kind, Some(peeled))
580 } else {
581 (WrapperKind::None, None)
582 }
583 }
584 "Weak" => (WrapperKind::Weak, Some(inner.clone())),
585 "Tagged" => (WrapperKind::Tagged, Some(inner.clone())),
586 "Cow" => (WrapperKind::Cow, Some(inner.clone())),
587 "AtomicPtr" if is_std_sync_atomic_type(&tp.path) => {
588 (WrapperKind::Atomic, None)
589 }
590 "Pin" => (WrapperKind::Pin, Some(inner.clone())),
591 "Cell" => (WrapperKind::Cell, Some(inner.clone())),
592 "RefCell" => (WrapperKind::RefCell, Some(inner.clone())),
593 "OnceCell" | "OnceLock" => {
594 (WrapperKind::OnceCell, Some(inner.clone()))
595 }
596 "Lazy" | "LazyLock" => (WrapperKind::Lazy, Some(inner.clone())),
597 "PhantomData" => {
598 (WrapperKind::PhantomData, Some(inner.clone()))
599 }
600 "Range" | "RangeInclusive" => {
601 (WrapperKind::Range, Some(inner.clone()))
602 }
603 _ => (WrapperKind::None, None),
604 };
605 }
606 }
607 }
608 }
609 }
610 // Handle atomic types with no angle bracket args (AtomicBool, AtomicI32, etc.)
611 if matches!(seg.arguments, PathArguments::None) {
612 if ident_str == "String" {
613 return (WrapperKind::String, None);
614 }
615 if is_std_sync_atomic_type(&tp.path)
616 && ATOMIC_TYPE_IDENTS.contains(&ident_str.as_str())
617 {
618 return (WrapperKind::Atomic, None);
619 }
620 }
621 }
622 }
623 (WrapperKind::None, None)
624}
625
626/// Check if a field has the #[pin] attribute (pin_project pattern).
627fn field_has_pin_attr(field: &syn::Field) -> bool {
628 field
629 .attrs
630 .iter()
631 .any(|attr| attr.path().get_ident().map(|i| i == "pin").unwrap_or(false))
632}
633
634/// Check if a type is a Future (dyn Future, impl Future, or Box<dyn Future>).
635fn is_future_type(ty: &Type) -> bool {
636 use syn::{GenericArgument, PathArguments, TypeParamBound};
637
638 match ty {
639 Type::TraitObject(trait_obj) => trait_obj.bounds.iter().any(|b| {
640 if let TypeParamBound::Trait(t) = b {
641 t.path
642 .segments
643 .last()
644 .map(|s| s.ident == "Future")
645 .unwrap_or(false)
646 } else {
647 false
648 }
649 }),
650 Type::ImplTrait(impl_trait) => impl_trait.bounds.iter().any(|b| {
651 if let TypeParamBound::Trait(t) = b {
652 t.path
653 .segments
654 .last()
655 .map(|s| s.ident == "Future")
656 .unwrap_or(false)
657 } else {
658 false
659 }
660 }),
661 Type::Path(tp) => {
662 if let Some(seg) = tp.path.segments.last() {
663 match seg.ident.to_string().as_str() {
664 "Box" | "Pin" => {
665 if let PathArguments::AngleBracketed(args) = &seg.arguments {
666 if let Some(GenericArgument::Type(inner)) = args.args.first() {
667 return is_future_type(inner);
668 }
669 }
670 }
671 _ => {}
672 }
673 }
674 false
675 }
676 _ => false,
677 }
678}
679
680/// Extract Output type from Future trait bound (dyn Future<Output = T>, impl Future<Output = T>, etc.).
681fn extract_future_output(ty: &Type) -> Option<Type> {
682 use syn::{GenericArgument, PathArguments, TypeParamBound};
683
684 let bounds = match ty {
685 Type::TraitObject(t) => &t.bounds,
686 Type::ImplTrait(t) => &t.bounds,
687 Type::Path(tp) => {
688 if let Some(seg) = tp.path.segments.last() {
689 if matches!(seg.ident.to_string().as_str(), "Box" | "Pin") {
690 if let PathArguments::AngleBracketed(args) = &seg.arguments {
691 if let Some(GenericArgument::Type(inner)) = args.args.first() {
692 return extract_future_output(inner);
693 }
694 }
695 }
696 }
697 return None;
698 }
699 _ => return None,
700 };
701
702 for bound in bounds {
703 if let TypeParamBound::Trait(trait_bound) = bound {
704 if let Some(seg) = trait_bound.path.segments.last() {
705 if seg.ident == "Future" {
706 if let PathArguments::AngleBracketed(args) = &seg.arguments {
707 for arg in &args.args {
708 if let GenericArgument::AssocType(assoc) = arg {
709 if assoc.ident == "Output" {
710 return Some(assoc.ty.clone());
711 }
712 }
713 }
714 }
715 }
716 }
717 }
718 }
719 None
720}
721
722/// For HashMap<K,V> or BTreeMap<K,V>, returns Some((key_ty, value_ty)).
723fn extract_map_key_value(ty: &Type) -> Option<(Type, Type)> {
724 use syn::{GenericArgument, PathArguments};
725
726 if let Type::Path(tp) = ty {
727 if let Some(seg) = tp.path.segments.last() {
728 let ident_str = seg.ident.to_string();
729 if ident_str == "HashMap" || ident_str == "BTreeMap" {
730 if let PathArguments::AngleBracketed(ab) = &seg.arguments {
731 let args: Vec<_> = ab.args.iter().collect();
732 if let (Some(key_arg), Some(value_arg)) = (args.get(0), args.get(1)) {
733 if let (GenericArgument::Type(key_ty), GenericArgument::Type(value_ty)) =
734 (key_arg, value_arg)
735 {
736 return Some((key_ty.clone(), value_ty.clone()));
737 }
738 }
739 }
740 }
741 }
742 }
743 None
744}
745
746/// For `Option<HashMap<K,V>>` / `Option<BTreeMap<K,V>>`, returns `Some((key_ty, value_ty))`.
747fn extract_map_key_value_through_option(ty: &Type) -> Option<(Type, Type)> {
748 use syn::{GenericArgument, PathArguments};
749
750 if let Type::Path(tp) = ty {
751 if let Some(seg) = tp.path.segments.last() {
752 if seg.ident == "Option" {
753 if let PathArguments::AngleBracketed(ab) = &seg.arguments {
754 if let Some(GenericArgument::Type(inner)) = ab.args.first() {
755 return extract_map_key_value(inner);
756 }
757 }
758 }
759 }
760 }
761 None
762}
763
764fn to_snake_case(name: &str) -> String {
765 let mut out = String::new();
766 for (i, c) in name.chars().enumerate() {
767 if c.is_uppercase() {
768 if i != 0 {
769 out.push('_');
770 }
771 out.push(c.to_ascii_lowercase());
772 } else {
773 out.push(c);
774 }
775 }
776 out
777}
778
779// Full `SyncKp<…>` return types: borrow slots use `&'static` / `&'static mut`; closure slots use
780// elided references in `impl Fn(…)`. Still paired with `fn …<'b>()` in generated code.
781// HRTB on `G` / `S` uses `for<'c> fn(…)` so it does not clash with reference lifetimes in `SyncKp`.
782
783fn kp_lock_ty_arc_mutex(
784 root: &impl ToTokens,
785 lock: &impl ToTokens,
786 inner: &impl ToTokens,
787) -> proc_macro2::TokenStream {
788 quote! {
789 rust_key_paths::sync_kp::SyncKp<
790 #root,
791 #lock,
792 #inner,
793 #inner,
794 &'static #root,
795 &'static #lock,
796 &'static #inner,
797 &'static #inner,
798 &'static mut #root,
799 &'static mut #lock,
800 &'static mut #inner,
801 &'static mut #inner,
802 impl Fn(& #root) -> Option<& #lock>,
803 impl Fn(&mut #root) -> Option<&mut #lock>,
804 rust_key_paths::sync_kp::ArcMutexAccess<#inner>,
805 impl Fn(& #inner) -> Option<& #inner>,
806 impl Fn(&mut #inner) -> Option<&mut #inner>,
807 >
808 }
809}
810
811fn kp_lock_ty_arc_mutex_option(
812 root: &impl ToTokens,
813 lock: &impl ToTokens,
814 inner: &impl ToTokens,
815) -> proc_macro2::TokenStream {
816 quote! {
817 rust_key_paths::sync_kp::SyncKp<
818 #root,
819 #lock,
820 Option<#inner>,
821 #inner,
822 &'static #root,
823 &'static #lock,
824 &'static Option<#inner>,
825 &'static #inner,
826 &'static mut #root,
827 &'static mut #lock,
828 &'static mut Option<#inner>,
829 &'static mut #inner,
830 impl Fn(& #root) -> Option<& #lock>,
831 impl Fn(&mut #root) -> Option<&mut #lock>,
832 rust_key_paths::sync_kp::ArcMutexAccess<Option<#inner>>,
833 impl Fn(& Option<#inner>) -> Option<& #inner>,
834 impl Fn(&mut Option<#inner>) -> Option<&mut #inner>,
835 >
836 }
837}
838
839fn kp_lock_ty_arc_rw_lock(
840 root: &impl ToTokens,
841 lock: &impl ToTokens,
842 inner: &impl ToTokens,
843) -> proc_macro2::TokenStream {
844 quote! {
845 rust_key_paths::sync_kp::SyncKp<
846 #root,
847 #lock,
848 #inner,
849 #inner,
850 &'static #root,
851 &'static #lock,
852 &'static #inner,
853 &'static #inner,
854 &'static mut #root,
855 &'static mut #lock,
856 &'static mut #inner,
857 &'static mut #inner,
858 impl Fn(& #root) -> Option<& #lock>,
859 impl Fn(&mut #root) -> Option<&mut #lock>,
860 rust_key_paths::sync_kp::ArcRwLockAccess<#inner>,
861 impl Fn(& #inner) -> Option<& #inner>,
862 impl Fn(&mut #inner) -> Option<&mut #inner>,
863 >
864 }
865}
866
867fn kp_lock_ty_arc_rw_lock_option(
868 root: &impl ToTokens,
869 lock: &impl ToTokens,
870 inner: &impl ToTokens,
871) -> proc_macro2::TokenStream {
872 quote! {
873 rust_key_paths::sync_kp::SyncKp<
874 #root,
875 #lock,
876 Option<#inner>,
877 #inner,
878 &'static #root,
879 &'static #lock,
880 &'static Option<#inner>,
881 &'static #inner,
882 &'static mut #root,
883 &'static mut #lock,
884 &'static mut Option<#inner>,
885 &'static mut #inner,
886 impl Fn(& #root) -> Option<& #lock>,
887 impl Fn(&mut #root) -> Option<&mut #lock>,
888 rust_key_paths::sync_kp::ArcRwLockAccess<Option<#inner>>,
889 impl Fn(& Option<#inner>) -> Option<& #inner>,
890 impl Fn(&mut Option<#inner>) -> Option<&mut #inner>,
891 >
892 }
893}
894
895fn kp_lock_ty_arc_arc_swap(
896 root: &impl ToTokens,
897 lock: &impl ToTokens,
898 inner: &impl ToTokens,
899) -> proc_macro2::TokenStream {
900 quote! {
901 rust_key_paths::sync_kp::SyncKp<
902 #root,
903 #lock,
904 #inner,
905 #inner,
906 &'static #root,
907 &'static #lock,
908 &'static #inner,
909 &'static #inner,
910 &'static mut #root,
911 &'static mut #lock,
912 &'static mut #inner,
913 &'static mut #inner,
914 impl Fn(& #root) -> Option<& #lock>,
915 impl Fn(&mut #root) -> Option<&mut #lock>,
916 rust_key_paths::sync_kp::ArcArcSwapAccess<#inner>,
917 impl Fn(& #inner) -> Option<& #inner>,
918 impl Fn(&mut #inner) -> Option<&mut #inner>,
919 >
920 }
921}
922
923fn kp_lock_ty_arc_arc_swap_option(
924 root: &impl ToTokens,
925 lock: &impl ToTokens,
926 inner: &impl ToTokens,
927) -> proc_macro2::TokenStream {
928 quote! {
929 rust_key_paths::sync_kp::SyncKp<
930 #root,
931 #lock,
932 ::std::option::Option<::std::sync::Arc<#inner>>,
933 #inner,
934 &'static #root,
935 &'static #lock,
936 &'static ::std::option::Option<::std::sync::Arc<#inner>>,
937 &'static #inner,
938 &'static mut #root,
939 &'static mut #lock,
940 &'static mut ::std::option::Option<::std::sync::Arc<#inner>>,
941 &'static mut #inner,
942 impl Fn(& #root) -> Option<& #lock>,
943 impl Fn(&mut #root) -> Option<&mut #lock>,
944 rust_key_paths::sync_kp::ArcArcSwapOptionAccess<#inner>,
945 impl Fn(& ::std::option::Option<::std::sync::Arc<#inner>>) -> Option<& #inner>,
946 impl Fn(&mut ::std::option::Option<::std::sync::Arc<#inner>>) -> Option<&mut #inner>,
947 >
948 }
949}
950
951fn kp_lock_ty_parking_lot_mutex(
952 root: &impl ToTokens,
953 lock: &impl ToTokens,
954 inner: &impl ToTokens,
955) -> proc_macro2::TokenStream {
956 quote! {
957 rust_key_paths::sync_kp::SyncKp<
958 #root,
959 #lock,
960 #inner,
961 #inner,
962 &'static #root,
963 &'static #lock,
964 &'static #inner,
965 &'static #inner,
966 &'static mut #root,
967 &'static mut #lock,
968 &'static mut #inner,
969 &'static mut #inner,
970 impl Fn(& #root) -> Option<& #lock>,
971 impl Fn(&mut #root) -> Option<&mut #lock>,
972 rust_key_paths::sync_kp::ParkingLotMutexAccess<#inner>,
973 impl Fn(& #inner) -> Option<& #inner>,
974 impl Fn(&mut #inner) -> Option<&mut #inner>,
975 >
976 }
977}
978
979fn kp_lock_ty_parking_lot_mutex_option(
980 root: &impl ToTokens,
981 lock: &impl ToTokens,
982 inner: &impl ToTokens,
983) -> proc_macro2::TokenStream {
984 quote! {
985 rust_key_paths::sync_kp::SyncKp<
986 #root,
987 #lock,
988 Option<#inner>,
989 #inner,
990 &'static #root,
991 &'static #lock,
992 &'static Option<#inner>,
993 &'static #inner,
994 &'static mut #root,
995 &'static mut #lock,
996 &'static mut Option<#inner>,
997 &'static mut #inner,
998 impl Fn(& #root) -> Option<& #lock>,
999 impl Fn(&mut #root) -> Option<&mut #lock>,
1000 rust_key_paths::sync_kp::ParkingLotMutexAccess<Option<#inner>>,
1001 impl Fn(& Option<#inner>) -> Option<& #inner>,
1002 impl Fn(&mut Option<#inner>) -> Option<&mut #inner>,
1003 >
1004 }
1005}
1006
1007fn kp_lock_ty_parking_lot_rw_lock(
1008 root: &impl ToTokens,
1009 lock: &impl ToTokens,
1010 inner: &impl ToTokens,
1011) -> proc_macro2::TokenStream {
1012 quote! {
1013 rust_key_paths::sync_kp::SyncKp<
1014 #root,
1015 #lock,
1016 #inner,
1017 #inner,
1018 &'static #root,
1019 &'static #lock,
1020 &'static #inner,
1021 &'static #inner,
1022 &'static mut #root,
1023 &'static mut #lock,
1024 &'static mut #inner,
1025 &'static mut #inner,
1026 impl Fn(& #root) -> Option<& #lock>,
1027 impl Fn(&mut #root) -> Option<&mut #lock>,
1028 rust_key_paths::sync_kp::ParkingLotRwLockAccess<#inner>,
1029 impl Fn(& #inner) -> Option<& #inner>,
1030 impl Fn(&mut #inner) -> Option<&mut #inner>,
1031 >
1032 }
1033}
1034
1035fn kp_lock_ty_parking_lot_rw_lock_option(
1036 root: &impl ToTokens,
1037 lock: &impl ToTokens,
1038 inner: &impl ToTokens,
1039) -> proc_macro2::TokenStream {
1040 quote! {
1041 rust_key_paths::sync_kp::SyncKp<
1042 #root,
1043 #lock,
1044 Option<#inner>,
1045 #inner,
1046 &'static #root,
1047 &'static #lock,
1048 &'static Option<#inner>,
1049 &'static #inner,
1050 &'static mut #root,
1051 &'static mut #lock,
1052 &'static mut Option<#inner>,
1053 &'static mut #inner,
1054 impl Fn(& #root) -> Option<& #lock>,
1055 impl Fn(&mut #root) -> Option<&mut #lock>,
1056 rust_key_paths::sync_kp::ParkingLotRwLockAccess<Option<#inner>>,
1057 impl Fn(& Option<#inner>) -> Option<& #inner>,
1058 impl Fn(&mut Option<#inner>) -> Option<&mut #inner>,
1059 >
1060 }
1061}
1062
1063/// Derive macro for generating simple keypath methods.
1064///
1065/// Generates one method per field: `StructName::field_name()` that returns a `Kp`.
1066/// Intelligently handles wrapper types (Option, Vec, Box, Arc, etc.) to generate appropriate keypaths.
1067///
1068/// # Example
1069///
1070/// ```ignore
1071/// #[derive(Kp)]
1072/// struct Person {
1073/// name: String,
1074/// age: i32,
1075/// email: Option<String>,
1076/// addresses: Vec<String>,
1077/// }
1078///
1079/// // Generates:
1080/// // impl Person {
1081/// // pub fn name() -> Kp<...> { ... }
1082/// // pub fn age() -> Kp<...> { ... }
1083/// // pub fn email() -> Kp<...> { ... } // unwraps Option
1084/// // pub fn addresses() -> Kp<...> { ... } // accesses first element
1085/// // }
1086/// ```
1087#[proc_macro_derive(Kp)]
1088pub fn derive_keypaths(input: TokenStream) -> TokenStream {
1089 let input = parse_macro_input!(input as DeriveInput);
1090 let name = &input.ident;
1091 let input_span = input.span();
1092
1093 let methods = match input.data {
1094 Data::Struct(data_struct) => match data_struct.fields {
1095 Fields::Named(fields_named) => {
1096 let mut tokens = proc_macro2::TokenStream::new();
1097
1098 // Generate identity methods for the struct
1099 tokens.extend(quote! {
1100 /// Returns a generic identity keypath for this type
1101 #[inline(always)]
1102 pub fn _identity<'a, Root, MutRoot>() -> rust_key_paths::Kp<
1103 #name,
1104 #name,
1105 Root,
1106 Root,
1107 MutRoot,
1108 MutRoot,
1109 fn(Root) -> Option<Root>,
1110 fn(MutRoot) -> Option<MutRoot>,
1111 >
1112 where
1113 Root: std::borrow::Borrow<#name>,
1114 MutRoot: std::borrow::BorrowMut<#name>,
1115 {
1116 rust_key_paths::Kp::new(
1117 |r: Root| Some(r),
1118 |r: MutRoot| Some(r)
1119 )
1120 }
1121
1122 // /// Returns a simple identity keypath for this type
1123 // #[inline(always)]
1124 // pub fn identity() -> rust_key_paths::Kp<#name, #name, &'static #name, &'static #name, &'static mut #name, &'static mut #name, impl Fn(&#name) -> Option<&#name>, impl Fn(&mut #name) -> Option<&mut #name>,> {
1125 // rust_key_paths::Kp::new(
1126 // |r: &#name| Some(r),
1127 // |r: &mut #name| Some(r)
1128 // )
1129 // }
1130 });
1131
1132 // When struct has #[pin] fields, generated code calls this.project() which must
1133 // be provided by #[pin_project]. If missing, user gets: no method named `project`.
1134
1135 for field in fields_named.named.iter() {
1136 let field_ident = field.ident.as_ref().unwrap();
1137 let ty = &field.ty;
1138 // Centralized keypath method names – change here to adjust for all types
1139 let kp_fn = format_ident!("{}", field_ident);
1140 let kp_at_fn = format_ident!("{}_at", field_ident);
1141
1142 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
1143
1144 // Override kind when field has #[pin] (pin_project pattern)
1145 let (kind, inner_ty) = if field_has_pin_attr(field) {
1146 let pinned_kind = if let Some(output_ty) = extract_future_output(ty) {
1147 if matches!(kind, WrapperKind::Box) {
1148 (WrapperKind::PinnedBoxFuture, Some(output_ty))
1149 } else {
1150 (WrapperKind::PinnedFuture, Some(output_ty))
1151 }
1152 } else if is_future_type(ty) {
1153 (WrapperKind::PinnedFuture, inner_ty.clone())
1154 } else {
1155 (WrapperKind::PinnedField, inner_ty.clone())
1156 };
1157 pinned_kind
1158 } else {
1159 (kind, inner_ty.clone())
1160 };
1161
1162 match (kind, inner_ty) {
1163 (WrapperKind::Option, Some(inner_ty)) => {
1164 // For Option<T>, unwrap and access inner type
1165 tokens.extend(quote! {
1166 #[inline(always)]
1167 pub fn #kp_fn() -> rust_key_paths::Kp<
1168 #name,
1169 #inner_ty,
1170 &'static #name,
1171 &'static #inner_ty,
1172 &'static mut #name,
1173 &'static mut #inner_ty,
1174 impl Fn(&#name) -> Option<&#inner_ty>,
1175 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1176 > {
1177 rust_key_paths::Kp::new(
1178 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
1179 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
1180 )
1181 }
1182 });
1183 }
1184 (WrapperKind::OptionBox, Some(inner_ty)) => {
1185 // For Option<Box<T>>, keypath to T: get returns Option<&T> via as_deref()
1186 tokens.extend(quote! {
1187 #[inline(always)]
1188 pub fn #kp_fn() -> rust_key_paths::Kp<
1189 #name,
1190 #inner_ty,
1191 &'static #name,
1192 &'static #inner_ty,
1193 &'static mut #name,
1194 &'static mut #inner_ty,
1195 impl Fn(&#name) -> Option<&#inner_ty>,
1196 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1197 > {
1198 rust_key_paths::Kp::new(
1199 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_deref()),
1200 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_deref_mut()),
1201 )
1202 }
1203 });
1204 }
1205 (WrapperKind::OptionRc, Some(inner_ty)) => {
1206 // For Option<Rc<T>>, keypath to T: get returns Option<&T> via as_deref()
1207 // Setter: as_mut() gives Option<&mut Rc<T>>, and_then(Rc::get_mut) gives Option<&mut T>
1208 tokens.extend(quote! {
1209 #[inline(always)]
1210 pub fn #kp_fn() -> rust_key_paths::Kp<
1211 #name,
1212 #inner_ty,
1213 &'static #name,
1214 &'static #inner_ty,
1215 &'static mut #name,
1216 &'static mut #inner_ty,
1217 impl Fn(&#name) -> Option<&#inner_ty>,
1218 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1219 > {
1220 rust_key_paths::Kp::new(
1221 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_deref()),
1222 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut().and_then(std::rc::Rc::get_mut)),
1223 )
1224 }
1225 });
1226 }
1227 (WrapperKind::OptionArc, Some(inner_ty)) => {
1228 // For Option<Arc<T>>, keypath to T: get returns Option<&T> via as_deref()
1229 // Setter: as_mut() gives Option<&mut Arc<T>>, and_then(Arc::get_mut) gives Option<&mut T>
1230 tokens.extend(quote! {
1231 #[inline(always)]
1232 pub fn #kp_fn() -> rust_key_paths::Kp<
1233 #name,
1234 #inner_ty,
1235 &'static #name,
1236 &'static #inner_ty,
1237 &'static mut #name,
1238 &'static mut #inner_ty,
1239 impl Fn(&#name) -> Option<&#inner_ty>,
1240 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1241 > {
1242 rust_key_paths::Kp::new(
1243 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_deref()),
1244 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut().and_then(std::sync::Arc::get_mut)),
1245 )
1246 }
1247 });
1248 }
1249 (WrapperKind::OptionHashMap, Some(inner_ty)) => {
1250 if let Some((key_ty, _)) = extract_map_key_value_through_option(ty) {
1251 let type_name = name.to_string();
1252 let whole_fn = kp_fn.to_string();
1253 let at_fn = kp_at_fn.to_string();
1254 let whole_doc = format!(
1255 "Keypath to the whole optional `HashMap` (`{type_name}::{whole_fn}`). For a value at one key when the map is `Some`, use `{type_name}::{at_fn}(key)`."
1256 );
1257 let at_doc = format!(
1258 "Keyed access into the inner `HashMap` (`{type_name}::{at_fn}`). `get`/`get_mut` return `None` if the field is `None` or the key is missing. See also `{type_name}::{whole_fn}` for the full optional map."
1259 );
1260 tokens.extend(quote! {
1261 #[doc = #whole_doc]
1262 #[inline(always)]
1263 pub fn #kp_fn() -> rust_key_paths::Kp<
1264 #name,
1265 #ty,
1266 &'static #name,
1267 &'static #ty,
1268 &'static mut #name,
1269 &'static mut #ty,
1270 impl Fn(&#name) -> Option<&#ty>,
1271 impl Fn(&mut #name) -> Option<&mut #ty>,
1272 > {
1273 rust_key_paths::Kp::new(
1274 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1275 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1276 )
1277 }
1278 #[doc = #at_doc]
1279 #[inline(always)]
1280 pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
1281 where
1282 #key_ty: Clone + std::hash::Hash + Eq + 'static,
1283 {
1284 let key2 = key.clone();
1285 rust_key_paths::Kp::new(
1286 Box::new(move |root: &#name| root.#field_ident.as_ref().and_then(|m| m.get(&key))),
1287 Box::new(move |root: &mut #name| root.#field_ident.as_mut().and_then(|m| m.get_mut(&key2))),
1288 )
1289 }
1290 });
1291 } else {
1292 tokens.extend(quote! {
1293 #[inline(always)]
1294 pub fn #kp_fn() -> rust_key_paths::Kp<
1295 #name,
1296 #ty,
1297 &'static #name,
1298 &'static #ty,
1299 &'static mut #name,
1300 &'static mut #ty,
1301 impl Fn(&#name) -> Option<&#ty>,
1302 impl Fn(&mut #name) -> Option<&mut #ty>,
1303 > {
1304 rust_key_paths::Kp::new(
1305 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1306 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1307 )
1308 }
1309 });
1310 }
1311 }
1312 (WrapperKind::OptionBTreeMap, Some(inner_ty)) => {
1313 if let Some((key_ty, _)) = extract_map_key_value_through_option(ty) {
1314 let type_name = name.to_string();
1315 let whole_fn = kp_fn.to_string();
1316 let at_fn = kp_at_fn.to_string();
1317 let whole_doc = format!(
1318 "Keypath to the whole optional `BTreeMap` (`{type_name}::{whole_fn}`). For a value at one key when the map is `Some`, use `{type_name}::{at_fn}(key)`."
1319 );
1320 let at_doc = format!(
1321 "Keyed access into the inner `BTreeMap` (`{type_name}::{at_fn}`). `get`/`get_mut` return `None` if the field is `None` or the key is missing. See also `{type_name}::{whole_fn}` for the full optional map."
1322 );
1323 tokens.extend(quote! {
1324 #[doc = #whole_doc]
1325 #[inline(always)]
1326 pub fn #kp_fn() -> rust_key_paths::Kp<
1327 #name,
1328 #ty,
1329 &'static #name,
1330 &'static #ty,
1331 &'static mut #name,
1332 &'static mut #ty,
1333 impl Fn(&#name) -> Option<&#ty>,
1334 impl Fn(&mut #name) -> Option<&mut #ty>,
1335 > {
1336 rust_key_paths::Kp::new(
1337 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1338 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1339 )
1340 }
1341 #[doc = #at_doc]
1342 #[inline(always)]
1343 pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
1344 where
1345 #key_ty: Clone + Ord + 'static,
1346 {
1347 let key2 = key.clone();
1348 rust_key_paths::Kp::new(
1349 Box::new(move |root: &#name| root.#field_ident.as_ref().and_then(|m| m.get(&key))),
1350 Box::new(move |root: &mut #name| root.#field_ident.as_mut().and_then(|m| m.get_mut(&key2))),
1351 )
1352 }
1353 });
1354 } else {
1355 tokens.extend(quote! {
1356 #[inline(always)]
1357 pub fn #kp_fn() -> rust_key_paths::Kp<
1358 #name,
1359 #ty,
1360 &'static #name,
1361 &'static #ty,
1362 &'static mut #name,
1363 &'static mut #ty,
1364 impl Fn(&#name) -> Option<&#ty>,
1365 impl Fn(&mut #name) -> Option<&mut #ty>,
1366 > {
1367 rust_key_paths::Kp::new(
1368 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1369 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1370 )
1371 }
1372 });
1373 }
1374 }
1375 (WrapperKind::OptionHashSet, Some(inner_ty)) => {
1376 tokens.extend(quote! {
1377 #[inline(always)]
1378 pub fn #kp_fn() -> rust_key_paths::Kp<
1379 #name,
1380 #ty,
1381 &'static #name,
1382 &'static #ty,
1383 &'static mut #name,
1384 &'static mut #ty,
1385 impl Fn(&#name) -> Option<&#ty>,
1386 impl Fn(&mut #name) -> Option<&mut #ty>,
1387 > {
1388 rust_key_paths::Kp::new(
1389 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1390 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1391 )
1392 }
1393
1394 /// _at: check if element exists and get reference.
1395 /// HashSet does not allow mutable element access (would break hash invariant).
1396 #[inline(always)]
1397 pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
1398 where
1399 #inner_ty: Clone + std::hash::Hash + Eq + 'static,
1400 {
1401 rust_key_paths::Kp::new(
1402 Box::new(move |root: &#name| root.#field_ident.as_ref().and_then(|s| s.get(&key))),
1403 Box::new(move |_root: &mut #name| None),
1404 )
1405 }
1406 });
1407 }
1408 (WrapperKind::OptionBTreeSet, Some(inner_ty)) => {
1409 tokens.extend(quote! {
1410 #[inline(always)]
1411 pub fn #kp_fn() -> rust_key_paths::Kp<
1412 #name,
1413 #ty,
1414 &'static #name,
1415 &'static #ty,
1416 &'static mut #name,
1417 &'static mut #ty,
1418 impl Fn(&#name) -> Option<&#ty>,
1419 impl Fn(&mut #name) -> Option<&mut #ty>,
1420 > {
1421 rust_key_paths::Kp::new(
1422 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1423 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1424 )
1425 }
1426
1427 /// _at: check if element exists and get reference.
1428 /// BTreeSet does not allow mutable element access (would break ordering invariant).
1429 #[inline(always)]
1430 pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
1431 where
1432 #inner_ty: Clone + Ord + 'static,
1433 {
1434 rust_key_paths::Kp::new(
1435 Box::new(move |root: &#name| root.#field_ident.as_ref().and_then(|s| s.get(&key))),
1436 Box::new(move |_root: &mut #name| None),
1437 )
1438 }
1439 });
1440 }
1441 (WrapperKind::OptionVec, Some(inner_ty)) => {
1442 tokens.extend(quote! {
1443 #[inline(always)]
1444 pub fn #kp_fn() -> rust_key_paths::Kp<
1445 #name,
1446 #ty,
1447 &'static #name,
1448 &'static #ty,
1449 &'static mut #name,
1450 &'static mut #ty,
1451 impl Fn(&#name) -> Option<&#ty>,
1452 impl Fn(&mut #name) -> Option<&mut #ty>,
1453 > {
1454 rust_key_paths::Kp::new(
1455 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1456 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1457 )
1458 }
1459 #[inline(always)]
1460 pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
1461 rust_key_paths::Kp::new(
1462 Box::new(move |root: &#name| root.#field_ident.as_ref().and_then(|v| v.get(index))),
1463 Box::new(move |root: &mut #name| root.#field_ident.as_mut().and_then(|v| v.get_mut(index))),
1464 )
1465 }
1466 });
1467 }
1468 (WrapperKind::OptionVecDeque, Some(inner_ty)) => {
1469 tokens.extend(quote! {
1470 #[inline(always)]
1471 pub fn #kp_fn() -> rust_key_paths::Kp<
1472 #name,
1473 #ty,
1474 &'static #name,
1475 &'static #ty,
1476 &'static mut #name,
1477 &'static mut #ty,
1478 impl Fn(&#name) -> Option<&#ty>,
1479 impl Fn(&mut #name) -> Option<&mut #ty>,
1480 > {
1481 rust_key_paths::Kp::new(
1482 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1483 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1484 )
1485 }
1486 #[inline(always)]
1487 pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
1488 rust_key_paths::Kp::new(
1489 Box::new(move |root: &#name| root.#field_ident.as_ref().and_then(|v| v.get(index))),
1490 Box::new(move |root: &mut #name| root.#field_ident.as_mut().and_then(|v| v.get_mut(index))),
1491 )
1492 }
1493 });
1494 }
1495 (WrapperKind::OptionLinkedList, Some(_inner_ty))
1496 | (WrapperKind::OptionBinaryHeap, Some(_inner_ty))
1497 | (WrapperKind::OptionResult, Some(_inner_ty)) => {
1498 // Keypath to the Option container (reference), like Vec/HashSet
1499 tokens.extend(quote! {
1500 #[inline(always)]
1501 pub fn #kp_fn() -> rust_key_paths::Kp<
1502 #name,
1503 #ty,
1504 &'static #name,
1505 &'static #ty,
1506 &'static mut #name,
1507 &'static mut #ty,
1508 impl Fn(&#name) -> Option<&#ty>,
1509 impl Fn(&mut #name) -> Option<&mut #ty>,
1510 > {
1511 rust_key_paths::Kp::new(
1512 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1513 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1514 )
1515 }
1516 });
1517 }
1518 (WrapperKind::Vec, Some(inner_ty)) => {
1519 tokens.extend(quote! {
1520 #[inline(always)]
1521 pub fn #kp_fn() -> rust_key_paths::Kp<
1522 #name,
1523 #ty,
1524 &'static #name,
1525 &'static #ty,
1526 &'static mut #name,
1527 &'static mut #ty,
1528 impl Fn(&#name) -> Option<&#ty>,
1529 impl Fn(&mut #name) -> Option<&mut #ty>,
1530 > {
1531 rust_key_paths::Kp::new(
1532 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1533 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1534 )
1535 }
1536 #[inline(always)]
1537 pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
1538 rust_key_paths::Kp::new(
1539 Box::new(move |root: &#name| root.#field_ident.get(index)),
1540 Box::new(move |root: &mut #name| root.#field_ident.get_mut(index)),
1541 )
1542 }
1543 });
1544 }
1545 (WrapperKind::HashMap, Some(inner_ty)) => {
1546 if let Some((key_ty, _)) = extract_map_key_value(ty) {
1547 tokens.extend(quote! {
1548 #[inline(always)]
1549 pub fn #kp_fn() -> rust_key_paths::Kp<
1550 #name,
1551 #ty,
1552 &'static #name,
1553 &'static #ty,
1554 &'static mut #name,
1555 &'static mut #ty,
1556 impl Fn(&#name) -> Option<&#ty>,
1557 impl Fn(&mut #name) -> Option<&mut #ty>,
1558 > {
1559 rust_key_paths::Kp::new(
1560 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1561 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1562 )
1563 }
1564 #[inline(always)]
1565 pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
1566 where
1567 #key_ty: Clone + std::hash::Hash + Eq + 'static,
1568 {
1569 let key2 = key.clone();
1570 rust_key_paths::Kp::new(
1571 Box::new(move |root: &#name| root.#field_ident.get(&key)),
1572 Box::new(move |root: &mut #name| root.#field_ident.get_mut(&key2)),
1573 )
1574 }
1575 });
1576 } else {
1577 tokens.extend(quote! {
1578 #[inline(always)]
1579 pub fn #kp_fn() -> rust_key_paths::Kp<
1580 #name,
1581 #ty,
1582 &'static #name,
1583 &'static #ty,
1584 &'static mut #name,
1585 &'static mut #ty,
1586 impl Fn(&#name) -> Option<&#ty>,
1587 impl Fn(&mut #name) -> Option<&mut #ty>,
1588 > {
1589 rust_key_paths::Kp::new(
1590 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1591 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1592 )
1593 }
1594 });
1595 }
1596 }
1597 (WrapperKind::BTreeMap, Some(inner_ty))
1598 | (WrapperKind::BTreeMapOption, Some(inner_ty)) => {
1599 if let Some((key_ty, _)) = extract_map_key_value(ty) {
1600 tokens.extend(quote! {
1601 #[inline(always)]
1602 pub fn #kp_fn() -> rust_key_paths::Kp<
1603 #name,
1604 #ty,
1605 &'static #name,
1606 &'static #ty,
1607 &'static mut #name,
1608 &'static mut #ty,
1609 impl Fn(&#name) -> Option<&#ty>,
1610 impl Fn(&mut #name) -> Option<&mut #ty>,
1611 > {
1612 rust_key_paths::Kp::new(
1613 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1614 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1615 )
1616 }
1617 #[inline(always)]
1618 pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
1619 where
1620 #key_ty: Clone + Ord + 'static,
1621 {
1622 let key2 = key.clone();
1623 rust_key_paths::Kp::new(
1624 Box::new(move |root: &#name| root.#field_ident.get(&key)),
1625 Box::new(move |root: &mut #name| root.#field_ident.get_mut(&key2)),
1626 )
1627 }
1628 });
1629 } else {
1630 tokens.extend(quote! {
1631 #[inline(always)]
1632 pub fn #kp_fn() -> rust_key_paths::Kp<
1633 #name,
1634 #ty,
1635 &'static #name,
1636 &'static #ty,
1637 &'static mut #name,
1638 &'static mut #ty,
1639 impl Fn(&#name) -> Option<&#ty>,
1640 impl Fn(&mut #name) -> Option<&mut #ty>,
1641 > {
1642 rust_key_paths::Kp::new(
1643 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1644 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1645 )
1646 }
1647 });
1648 }
1649 }
1650 (WrapperKind::Box, Some(inner_ty)) => {
1651 // For Box<T>, deref to inner type (returns &T / &mut T, not &Box<T>)
1652 tokens.extend(quote! {
1653 #[inline(always)]
1654 pub fn #kp_fn() -> rust_key_paths::Kp<
1655 #name,
1656 #inner_ty,
1657 &'static #name,
1658 &'static #inner_ty,
1659 &'static mut #name,
1660 &'static mut #inner_ty,
1661 impl Fn(&#name) -> Option<&#inner_ty>,
1662 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1663 > {
1664 rust_key_paths::Kp::new(
1665 rust_key_paths::constrain_get(|root: &#name| Some(&*root.#field_ident)),
1666 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut *root.#field_ident)),
1667 )
1668 }
1669 });
1670 }
1671 (WrapperKind::BoxOption, Some(inner_ty)) => {
1672 // For Box<Option<T>>, keypath to T: deref Box to Option<T>, then Option::as_ref/as_mut
1673 tokens.extend(quote! {
1674 #[inline(always)]
1675 pub fn #kp_fn() -> rust_key_paths::Kp<
1676 #name,
1677 #inner_ty,
1678 &'static #name,
1679 &'static #inner_ty,
1680 &'static mut #name,
1681 &'static mut #inner_ty,
1682 impl Fn(&#name) -> Option<&#inner_ty>,
1683 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1684 > {
1685 rust_key_paths::Kp::new(
1686 rust_key_paths::constrain_get(|root: &#name| (&*root.#field_ident).as_ref()),
1687 rust_key_paths::constrain_set(|root: &mut #name| (&mut *root.#field_ident).as_mut()),
1688 )
1689 }
1690 });
1691 }
1692 (WrapperKind::RcOption, Some(inner_ty)) => {
1693 // For Rc<Option<T>>, keypath to T: deref Rc to &Option<T>, then Option::as_ref; set = Rc::get_mut then as_mut
1694 tokens.extend(quote! {
1695 #[inline(always)]
1696 pub fn #kp_fn() -> rust_key_paths::Kp<
1697 #name,
1698 #inner_ty,
1699 &'static #name,
1700 &'static #inner_ty,
1701 &'static mut #name,
1702 &'static mut #inner_ty,
1703 impl Fn(&#name) -> Option<&#inner_ty>,
1704 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1705 > {
1706 rust_key_paths::Kp::new(
1707 rust_key_paths::constrain_get(|root: &#name| (&*root.#field_ident).as_ref()),
1708 rust_key_paths::constrain_set(|root: &mut #name| std::rc::Rc::get_mut(&mut root.#field_ident).and_then(std::option::Option::as_mut)),
1709 )
1710 }
1711 });
1712 }
1713 (WrapperKind::ArcOption, Some(inner_ty)) => {
1714 // For Arc<Option<T>>, keypath to T: deref Arc to &Option<T>, then Option::as_ref; set = Arc::get_mut then as_mut
1715 tokens.extend(quote! {
1716 #[inline(always)]
1717 pub fn #kp_fn() -> rust_key_paths::Kp<
1718 #name,
1719 #inner_ty,
1720 &'static #name,
1721 &'static #inner_ty,
1722 &'static mut #name,
1723 &'static mut #inner_ty,
1724 impl Fn(&#name) -> Option<&#inner_ty>,
1725 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1726 > {
1727 rust_key_paths::Kp::new(
1728 rust_key_paths::constrain_get(|root: &#name| (&*root.#field_ident).as_ref()),
1729 rust_key_paths::constrain_set(|root: &mut #name| std::sync::Arc::get_mut(&mut root.#field_ident).and_then(std::option::Option::as_mut)),
1730 )
1731 }
1732 });
1733 }
1734 (WrapperKind::Pin, Some(inner_ty)) => {
1735 let kp_inner_fn = format_ident!("{}_inner", field_ident);
1736 tokens.extend(quote! {
1737 #[inline(always)]
1738 pub fn #kp_fn() -> rust_key_paths::Kp<
1739 #name,
1740 #ty,
1741 &'static #name,
1742 &'static #ty,
1743 &'static mut #name,
1744 &'static mut #ty,
1745 impl Fn(&#name) -> Option<&#ty>,
1746 impl Fn(&mut #name) -> Option<&mut #ty>,
1747 > {
1748 rust_key_paths::Kp::new(
1749 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1750 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1751 )
1752 }
1753 #[inline(always)]
1754 pub fn #kp_inner_fn() -> rust_key_paths::Kp<
1755 #name,
1756 #inner_ty,
1757 &'static #name,
1758 &'static #inner_ty,
1759 &'static mut #name,
1760 &'static mut #inner_ty,
1761 impl Fn(&#name) -> Option<&#inner_ty>,
1762 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1763>
1764>
1765 where #inner_ty: std::marker::Unpin
1766 {
1767 rust_key_paths::Kp::new(
1768 rust_key_paths::constrain_get(|root: &#name| Some(std::pin::Pin::as_ref(&root.#field_ident).get_ref())),
1769 rust_key_paths::constrain_set(|root: &mut #name| Some(std::pin::Pin::as_mut(&mut root.#field_ident).get_mut())),
1770 )
1771 }
1772 });
1773 }
1774 (WrapperKind::PinBox, Some(inner_ty)) => {
1775 let kp_inner_fn = format_ident!("{}_inner", field_ident);
1776 tokens.extend(quote! {
1777 #[inline(always)]
1778 pub fn #kp_fn() -> rust_key_paths::Kp<
1779 #name,
1780 #ty,
1781 &'static #name,
1782 &'static #ty,
1783 &'static mut #name,
1784 &'static mut #ty,
1785 impl Fn(&#name) -> Option<&#ty>,
1786 impl Fn(&mut #name) -> Option<&mut #ty>,
1787 > {
1788 rust_key_paths::Kp::new(
1789 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1790 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1791 )
1792 }
1793 #[inline(always)]
1794 pub fn #kp_inner_fn() -> rust_key_paths::Kp<
1795 #name,
1796 #inner_ty,
1797 &'static #name,
1798 &'static #inner_ty,
1799 &'static mut #name,
1800 &'static mut #inner_ty,
1801 impl Fn(&#name) -> Option<&#inner_ty>,
1802 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1803>
1804>
1805 where #inner_ty: std::marker::Unpin
1806 {
1807 // Pin::as_ref on Pin<Box<T>> returns Pin<&T> (Box Deref target), so get_ref() already gives &T
1808 rust_key_paths::Kp::new(
1809 rust_key_paths::constrain_get(|root: &#name| Some(std::pin::Pin::as_ref(&root.#field_ident).get_ref())),
1810 rust_key_paths::constrain_set(|root: &mut #name| Some(std::pin::Pin::as_mut(&mut root.#field_ident).get_mut())),
1811 )
1812 }
1813 });
1814 }
1815 (WrapperKind::PinnedField, _) => {
1816 let kp_pinned_fn = format_ident!("{}_pinned", field_ident);
1817 tokens.extend(quote! {
1818 #[inline(always)]
1819 pub fn #kp_fn() -> rust_key_paths::Kp<
1820 #name,
1821 #ty,
1822 &'static #name,
1823 &'static #ty,
1824 &'static mut #name,
1825 &'static mut #ty,
1826 impl Fn(&#name) -> Option<&#ty>,
1827 impl Fn(&mut #name) -> Option<&mut #ty>,
1828 > {
1829 rust_key_paths::Kp::new(
1830 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1831 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1832 )
1833 }
1834 /// Pinned projection for #[pin] field. Requires #[pin_project] on struct.
1835 #[inline(always)]
1836 pub fn #kp_pinned_fn(this: std::pin::Pin<&mut #name>) -> std::pin::Pin<&mut #ty> {
1837 this.project().#field_ident
1838 }
1839 });
1840 }
1841 (WrapperKind::PinnedFuture, _) => {
1842 let kp_pinned_fn = format_ident!("{}_pinned", field_ident);
1843 let kp_await_fn = format_ident!("{}_await", field_ident);
1844 let kp_pin_future_fn = format_ident!("{}_pin_future_kp", field_ident);
1845 let output_ty = quote! { <#ty as std::future::Future>::Output };
1846 tokens.extend(quote! {
1847 #[inline(always)]
1848 pub fn #kp_fn() -> rust_key_paths::Kp<
1849 #name,
1850 #ty,
1851 &'static #name,
1852 &'static #ty,
1853 &'static mut #name,
1854 &'static mut #ty,
1855 impl Fn(&#name) -> Option<&#ty>,
1856 impl Fn(&mut #name) -> Option<&mut #ty>,
1857 > {
1858 rust_key_paths::Kp::new(
1859 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1860 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1861 )
1862 }
1863 /// Pinned projection for #[pin] Future field. Requires #[pin_project] on struct.
1864 #[inline(always)]
1865 pub fn #kp_pinned_fn(this: std::pin::Pin<&mut #name>) -> std::pin::Pin<&mut #ty> {
1866 this.project().#field_ident
1867 }
1868 /// Poll the pinned future. Requires #[pin_project] on struct.
1869 pub async fn #kp_await_fn(this: std::pin::Pin<&mut #name>) -> Option<#output_ty>
1870 where #ty: std::future::Future
1871 {
1872 use std::future::Future;
1873 Some(this.project().#field_ident.await)
1874 }
1875 /// Keypath for [rust_key_paths::Kp::then_pin_future]. Composable pin future await.
1876 #[inline(always)]
1877 pub fn #kp_pin_future_fn() -> impl rust_key_paths::pin::PinFutureAwaitLike<#name, #output_ty> {
1878 rust_key_paths::pin_future_await_kp!(#name, #kp_await_fn -> #output_ty)
1879 }
1880 });
1881 }
1882 (WrapperKind::PinnedBoxFuture, Some(output_ty)) => {
1883 let kp_pinned_fn = format_ident!("{}_pinned", field_ident);
1884 let kp_await_fn = format_ident!("{}_await", field_ident);
1885 let kp_pin_future_fn = format_ident!("{}_pin_future_kp", field_ident);
1886 tokens.extend(quote! {
1887 #[inline(always)]
1888 pub fn #kp_fn() -> rust_key_paths::Kp<
1889 #name,
1890 #ty,
1891 &'static #name,
1892 &'static #ty,
1893 &'static mut #name,
1894 &'static mut #ty,
1895 impl Fn(&#name) -> Option<&#ty>,
1896 impl Fn(&mut #name) -> Option<&mut #ty>,
1897 > {
1898 rust_key_paths::Kp::new(
1899 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
1900 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
1901 )
1902 }
1903 /// Pinned projection for #[pin] Box<dyn Future> field. Requires #[pin_project] on struct.
1904 #[inline(always)]
1905 pub fn #kp_pinned_fn(this: std::pin::Pin<&mut #name>) -> std::pin::Pin<&mut #ty> {
1906 this.project().#field_ident
1907 }
1908 /// Poll the pinned boxed future. Requires #[pin_project] on struct.
1909 pub async fn #kp_await_fn(this: std::pin::Pin<&mut #name>) -> Option<#output_ty> {
1910 Some(this.project().#field_ident.await)
1911 }
1912 /// Keypath for [rust_key_paths::Kp::then_pin_future]. Composable pin future await.
1913 #[inline(always)]
1914 pub fn #kp_pin_future_fn() -> impl rust_key_paths::pin::PinFutureAwaitLike<#name, #output_ty> {
1915 rust_key_paths::pin_future_await_kp!(#name, #kp_await_fn -> #output_ty)
1916 }
1917 });
1918 }
1919 (WrapperKind::Rc, Some(inner_ty)) => {
1920 // For Rc<T>, deref to inner type (returns &T; get_mut when uniquely owned)
1921 tokens.extend(quote! {
1922 #[inline(always)]
1923 pub fn #kp_fn() -> rust_key_paths::Kp<
1924 #name,
1925 #inner_ty,
1926 &'static #name,
1927 &'static #inner_ty,
1928 &'static mut #name,
1929 &'static mut #inner_ty,
1930 impl Fn(&#name) -> Option<&#inner_ty>,
1931 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1932 > {
1933 rust_key_paths::Kp::new(
1934 rust_key_paths::constrain_get(|root: &#name| Some(root.#field_ident.as_ref())),
1935 rust_key_paths::constrain_set(|root: &mut #name| std::rc::Rc::get_mut(&mut root.#field_ident)),
1936 )
1937 }
1938 });
1939 }
1940 (WrapperKind::Arc, Some(inner_ty)) => {
1941 // For Arc<T>, deref to inner type (returns &T; get_mut when uniquely owned)
1942 tokens.extend(quote! {
1943 #[inline(always)]
1944 pub fn #kp_fn() -> rust_key_paths::Kp<
1945 #name,
1946 #inner_ty,
1947 &'static #name,
1948 &'static #inner_ty,
1949 &'static mut #name,
1950 &'static mut #inner_ty,
1951 impl Fn(&#name) -> Option<&#inner_ty>,
1952 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1953 > {
1954 rust_key_paths::Kp::new(
1955 rust_key_paths::constrain_get(|root: &#name| Some(root.#field_ident.as_ref())),
1956 rust_key_paths::constrain_set(|root: &mut #name| std::sync::Arc::get_mut(&mut root.#field_ident)),
1957 )
1958 }
1959 });
1960 }
1961 (WrapperKind::Cow, Some(inner_ty)) => {
1962 // For Cow<'_, B>, deref to inner type (as_ref/to_mut)
1963 tokens.extend(quote! {
1964 #[inline(always)]
1965 pub fn #kp_fn() -> rust_key_paths::Kp<
1966 #name,
1967 #inner_ty,
1968 &'static #name,
1969 &'static #inner_ty,
1970 &'static mut #name,
1971 &'static mut #inner_ty,
1972 impl Fn(&#name) -> Option<&#inner_ty>,
1973 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1974 > {
1975 rust_key_paths::Kp::new(
1976 rust_key_paths::constrain_get(|root: &#name| Some(root.#field_ident.as_ref())),
1977 rust_key_paths::constrain_set(|root: &mut #name| Some(root.#field_ident.to_mut())),
1978 )
1979 }
1980 });
1981 }
1982
1983 (WrapperKind::OptionCow, Some(inner_ty)) => {
1984 // For Option<Cow<'_, B>>
1985 tokens.extend(quote! {
1986 #[inline(always)]
1987 pub fn #kp_fn() -> rust_key_paths::Kp<
1988 #name,
1989 #inner_ty,
1990 &'static #name,
1991 &'static #inner_ty,
1992 &'static mut #name,
1993 &'static mut #inner_ty,
1994 impl Fn(&#name) -> Option<&#inner_ty>,
1995 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
1996 > {
1997 rust_key_paths::Kp::new(
1998 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref().map(|c| c.as_ref())),
1999 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut().map(|c| c.to_mut())),
2000 )
2001 }
2002 });
2003 }
2004 (WrapperKind::OptionTagged, Some(inner_ty)) => {
2005 // For Option<Tagged<Tag, T>> - Tagged implements Deref/DerefMut
2006 tokens.extend(quote! {
2007 #[inline(always)]
2008 pub fn #kp_fn() -> rust_key_paths::Kp<
2009 #name,
2010 #inner_ty,
2011 &'static #name,
2012 &'static #inner_ty,
2013 &'static mut #name,
2014 &'static mut #inner_ty,
2015 impl Fn(&#name) -> Option<&#inner_ty>,
2016 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
2017 > {
2018 rust_key_paths::Kp::new(
2019 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref().map(|t| std::ops::Deref::deref(t))),
2020 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut().map(|t| std::ops::DerefMut::deref_mut(t))),
2021 )
2022 }
2023 });
2024 }
2025 (WrapperKind::OptionReference, Some(inner_ty)) => {
2026 // For Option<&T>, Option<&str>, Option<&[T]> - read-only, setter returns None
2027 tokens.extend(quote! {
2028 #[inline(always)]
2029 pub fn #kp_fn() -> rust_key_paths::Kp<
2030 #name,
2031 #inner_ty,
2032 &'static #name,
2033 &'static #inner_ty,
2034 &'static mut #name,
2035 &'static mut #inner_ty,
2036 impl Fn(&#name) -> Option<&#inner_ty>,
2037 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
2038 > {
2039 rust_key_paths::Kp::new(
2040 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
2041 rust_key_paths::constrain_set(|_root: &mut #name| None),
2042 )
2043 }
2044 });
2045 }
2046 (WrapperKind::HashSet, Some(inner_ty))
2047 | (WrapperKind::HashSetOption, Some(inner_ty)) => {
2048 let kp_at_fn = format_ident!("{}_at", field_ident);
2049
2050 tokens.extend(quote! {
2051 #[inline(always)]
2052 pub fn #kp_fn() -> rust_key_paths::Kp<
2053 #name,
2054 #ty,
2055 &'static #name,
2056 &'static #ty,
2057 &'static mut #name,
2058 &'static mut #ty,
2059 impl Fn(&#name) -> Option<&#ty>,
2060 impl Fn(&mut #name) -> Option<&mut #ty>,
2061 > {
2062 rust_key_paths::Kp::new(
2063 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2064 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2065 )
2066 }
2067
2068 /// _at: check if element exists and get reference.
2069 /// HashSet does not allow mutable element access (would break hash invariant).
2070 #[inline(always)]
2071 pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
2072 where
2073 #inner_ty: Clone + std::hash::Hash + Eq + 'static,
2074 {
2075 rust_key_paths::Kp::new(
2076 Box::new(move |root: &#name| root.#field_ident.get(&key)),
2077 Box::new(move |_root: &mut #name| None),
2078 )
2079 }
2080 });
2081 }
2082 (WrapperKind::BTreeSet, Some(inner_ty))
2083 | (WrapperKind::BTreeSetOption, Some(inner_ty)) => {
2084 let kp_at_fn = format_ident!("{}_at", field_ident);
2085
2086 tokens.extend(quote! {
2087 #[inline(always)]
2088 pub fn #kp_fn() -> rust_key_paths::Kp<
2089 #name,
2090 #ty,
2091 &'static #name,
2092 &'static #ty,
2093 &'static mut #name,
2094 &'static mut #ty,
2095 impl Fn(&#name) -> Option<&#ty>,
2096 impl Fn(&mut #name) -> Option<&mut #ty>,
2097 > {
2098 rust_key_paths::Kp::new(
2099 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2100 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2101 )
2102 }
2103
2104 /// _at: check if element exists and get reference.
2105 /// BTreeSet does not allow mutable element access (would break ordering invariant).
2106 #[inline(always)]
2107 pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
2108 where
2109 #inner_ty: Clone + Ord + 'static,
2110 {
2111 rust_key_paths::Kp::new(
2112 Box::new(move |root: &#name| root.#field_ident.get(&key)),
2113 Box::new(move |_root: &mut #name| None),
2114 )
2115 }
2116 });
2117 }
2118 (WrapperKind::VecDeque, Some(inner_ty))
2119 | (WrapperKind::VecDequeOption, Some(inner_ty)) => {
2120 tokens.extend(quote! {
2121 #[inline(always)]
2122 pub fn #kp_fn() -> rust_key_paths::Kp<
2123 #name,
2124 #ty,
2125 &'static #name,
2126 &'static #ty,
2127 &'static mut #name,
2128 &'static mut #ty,
2129 impl Fn(&#name) -> Option<&#ty>,
2130 impl Fn(&mut #name) -> Option<&mut #ty>,
2131 > {
2132 rust_key_paths::Kp::new(
2133 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2134 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2135 )
2136 }
2137 #[inline(always)]
2138 pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
2139 rust_key_paths::Kp::new(
2140 Box::new(move |root: &#name| root.#field_ident.get(index)),
2141 Box::new(move |root: &mut #name| root.#field_ident.get_mut(index)),
2142 )
2143 }
2144 });
2145 }
2146 (WrapperKind::LinkedList, Some(_inner_ty))
2147 | (WrapperKind::LinkedListOption, Some(_inner_ty)) => {
2148 tokens.extend(quote! {
2149 #[inline(always)]
2150 pub fn #kp_fn() -> rust_key_paths::Kp<
2151 #name,
2152 #ty,
2153 &'static #name,
2154 &'static #ty,
2155 &'static mut #name,
2156 &'static mut #ty,
2157 impl Fn(&#name) -> Option<&#ty>,
2158 impl Fn(&mut #name) -> Option<&mut #ty>,
2159 > {
2160 rust_key_paths::Kp::new(
2161 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2162 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2163 )
2164 }
2165 });
2166 }
2167 (WrapperKind::BinaryHeap, Some(_inner_ty))
2168 | (WrapperKind::BinaryHeapOption, Some(_inner_ty)) => {
2169 tokens.extend(quote! {
2170 #[inline(always)]
2171 pub fn #kp_fn() -> rust_key_paths::Kp<
2172 #name,
2173 #ty,
2174 &'static #name,
2175 &'static #ty,
2176 &'static mut #name,
2177 &'static mut #ty,
2178 impl Fn(&#name) -> Option<&#ty>,
2179 impl Fn(&mut #name) -> Option<&mut #ty>,
2180 > {
2181 rust_key_paths::Kp::new(
2182 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2183 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2184 )
2185 }
2186 });
2187 }
2188 (WrapperKind::Result, Some(inner_ty)) => {
2189 // For Result<T, E>, access Ok value
2190 tokens.extend(quote! {
2191 #[inline(always)]
2192 pub fn #kp_fn() -> rust_key_paths::Kp<
2193 #name,
2194 #inner_ty,
2195 &'static #name,
2196 &'static #inner_ty,
2197 &'static mut #name,
2198 &'static mut #inner_ty,
2199 impl Fn(&#name) -> Option<&#inner_ty>,
2200 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
2201 > {
2202 rust_key_paths::Kp::new(
2203 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref().ok()),
2204 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut().ok()),
2205 )
2206 }
2207 });
2208 }
2209 (WrapperKind::StdArcMutex, Some(inner_ty)) => {
2210 // For Arc<std::sync::Mutex<T>>
2211 let lock_kp_return_ty = kp_lock_ty_arc_mutex(name, ty, &inner_ty);
2212 tokens.extend(quote! {
2213 #[inline(always)]
2214 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2215 rust_key_paths::sync_kp::SyncKp::new(
2216 rust_key_paths::Kp::new(
2217 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2218 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2219 ),
2220 rust_key_paths::sync_kp::ArcMutexAccess::new(),
2221 rust_key_paths::Kp::new(
2222 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2223 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2224 ),
2225 )
2226 }
2227 });
2228 }
2229 (WrapperKind::StdArcRwLock, Some(inner_ty)) => {
2230 // For Arc<std::sync::RwLock<T>>
2231 let lock_kp_return_ty = kp_lock_ty_arc_rw_lock(name, ty, &inner_ty);
2232 tokens.extend(quote! {
2233 #[inline(always)]
2234 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2235 rust_key_paths::sync_kp::SyncKp::new(
2236 rust_key_paths::Kp::new(
2237 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2238 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2239 ),
2240 rust_key_paths::sync_kp::ArcRwLockAccess::new(),
2241 rust_key_paths::Kp::new(
2242 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2243 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2244 ),
2245 )
2246 }
2247 });
2248 }
2249 (WrapperKind::StdArcMutexOption, Some(inner_ty)) => {
2250 // For Arc<std::sync::Mutex<Option<T>>> — SyncKp value T (extract from Option); guard gives &Option<T>
2251 let lock_kp_return_ty =
2252 kp_lock_ty_arc_mutex_option(name, ty, &inner_ty);
2253 tokens.extend(quote! {
2254 #[inline(always)]
2255 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2256 rust_key_paths::sync_kp::SyncKp::new(
2257 rust_key_paths::Kp::new(
2258 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2259 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2260 ),
2261 rust_key_paths::sync_kp::ArcMutexAccess::<Option<#inner_ty>>::new(),
2262 rust_key_paths::Kp::new(
2263 Option::<#inner_ty>::as_ref,
2264 Option::<#inner_ty>::as_mut,
2265 ),
2266 )
2267 }
2268 });
2269 }
2270 (WrapperKind::StdArcRwLockOption, Some(inner_ty)) => {
2271 // For Arc<std::sync::RwLock<Option<T>>> — SyncKp value T (extract from Option); guard gives &Option<T>
2272 let lock_kp_return_ty =
2273 kp_lock_ty_arc_rw_lock_option(name, ty, &inner_ty);
2274 tokens.extend(quote! {
2275 #[inline(always)]
2276 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2277 rust_key_paths::sync_kp::SyncKp::new(
2278 rust_key_paths::Kp::new(
2279 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2280 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2281 ),
2282 rust_key_paths::sync_kp::ArcRwLockAccess::<Option<#inner_ty>>::new(),
2283 rust_key_paths::Kp::new(
2284 Option::<#inner_ty>::as_ref,
2285 Option::<#inner_ty>::as_mut,
2286 ),
2287 )
2288 }
2289 });
2290 }
2291 (WrapperKind::BareArcSwap, Some(inner_ty)) => {
2292 // `arc_swap::ArcSwap<T>` owned on the struct — `field()` is `SyncKp` only (no `field_kp()`).
2293 let lock_kp_return_ty = kp_lock_ty_arc_arc_swap(name, ty, &inner_ty);
2294 tokens.extend(quote! {
2295 #[inline(always)]
2296 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2297 rust_key_paths::sync_kp::SyncKp::new(
2298 rust_key_paths::Kp::new(
2299 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2300 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2301 ),
2302 rust_key_paths::sync_kp::ArcArcSwapAccess::new(),
2303 rust_key_paths::Kp::new(
2304 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2305 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2306 ),
2307 )
2308 }
2309 });
2310 }
2311 (WrapperKind::BareArcSwapOption, Some(inner_ty)) => {
2312 let lock_kp_return_ty =
2313 kp_lock_ty_arc_arc_swap_option(name, ty, &inner_ty);
2314 tokens.extend(quote! {
2315 #[inline(always)]
2316 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2317 rust_key_paths::sync_kp::SyncKp::new(
2318 rust_key_paths::Kp::new(
2319 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2320 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2321 ),
2322 rust_key_paths::sync_kp::ArcArcSwapOptionAccess::<#inner_ty>::new(),
2323 rust_key_paths::Kp::new(
2324 |o: &::std::option::Option<::std::sync::Arc<#inner_ty>>| {
2325 o.as_ref().map(|a| a.as_ref())
2326 },
2327 |o: &mut ::std::option::Option<::std::sync::Arc<#inner_ty>>| {
2328 o.as_mut().and_then(::std::sync::Arc::get_mut)
2329 },
2330 ),
2331 )
2332 }
2333 });
2334 }
2335 (WrapperKind::ArcArcSwap, Some(inner_ty)) => {
2336 let lock_kp_return_ty = kp_lock_ty_arc_arc_swap(name, ty, &inner_ty);
2337 tokens.extend(quote! {
2338 #[inline(always)]
2339 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2340 rust_key_paths::sync_kp::SyncKp::new(
2341 rust_key_paths::Kp::new(
2342 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2343 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2344 ),
2345 rust_key_paths::sync_kp::ArcArcSwapAccess::new(),
2346 rust_key_paths::Kp::new(
2347 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2348 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2349 ),
2350 )
2351 }
2352 });
2353 }
2354 (WrapperKind::ArcArcSwapOption, Some(inner_ty)) => {
2355 let lock_kp_return_ty =
2356 kp_lock_ty_arc_arc_swap_option(name, ty, &inner_ty);
2357 tokens.extend(quote! {
2358 #[inline(always)]
2359 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2360 rust_key_paths::sync_kp::SyncKp::new(
2361 rust_key_paths::Kp::new(
2362 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2363 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2364 ),
2365 rust_key_paths::sync_kp::ArcArcSwapOptionAccess::<#inner_ty>::new(),
2366 rust_key_paths::Kp::new(
2367 |o: &::std::option::Option<::std::sync::Arc<#inner_ty>>| {
2368 o.as_ref().map(|a| a.as_ref())
2369 },
2370 |o: &mut ::std::option::Option<::std::sync::Arc<#inner_ty>>| {
2371 o.as_mut().and_then(::std::sync::Arc::get_mut)
2372 },
2373 ),
2374 )
2375 }
2376 });
2377 }
2378 (WrapperKind::ArcRwLock, Some(inner_ty)) => {
2379 // For Arc<parking_lot::RwLock<T>> (requires rust-key-paths "parking_lot" feature)
2380 let lock_kp_return_ty =
2381 kp_lock_ty_parking_lot_rw_lock(name, ty, &inner_ty);
2382 tokens.extend(quote! {
2383 #[inline(always)]
2384 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2385 rust_key_paths::sync_kp::SyncKp::new(
2386 rust_key_paths::Kp::new(
2387 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2388 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2389 ),
2390 rust_key_paths::sync_kp::ParkingLotRwLockAccess::new(),
2391 rust_key_paths::Kp::new(
2392 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2393 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2394 ),
2395 )
2396 }
2397 });
2398 }
2399 (WrapperKind::ArcMutex, Some(inner_ty)) => {
2400 // For Arc<parking_lot::Mutex<T>> (requires rust-key-paths "parking_lot" feature)
2401 let lock_kp_return_ty =
2402 kp_lock_ty_parking_lot_mutex(name, ty, &inner_ty);
2403 tokens.extend(quote! {
2404 #[inline(always)]
2405 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2406 rust_key_paths::sync_kp::SyncKp::new(
2407 rust_key_paths::Kp::new(
2408 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2409 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2410 ),
2411 rust_key_paths::sync_kp::ParkingLotMutexAccess::new(),
2412 rust_key_paths::Kp::new(
2413 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2414 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2415 ),
2416 )
2417 }
2418 });
2419 }
2420 (WrapperKind::ArcMutexOption, Some(inner_ty)) => {
2421 // For Arc<parking_lot::Mutex<Option<T>>> — SyncKp value T (extract from Option); guard gives &Option<T>
2422 let lock_kp_return_ty =
2423 kp_lock_ty_parking_lot_mutex_option(name, ty, &inner_ty);
2424 tokens.extend(quote! {
2425 #[inline(always)]
2426 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2427 rust_key_paths::sync_kp::SyncKp::new(
2428 rust_key_paths::Kp::new(
2429 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2430 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2431 ),
2432 rust_key_paths::sync_kp::ParkingLotMutexAccess::<Option<#inner_ty>>::new(),
2433 rust_key_paths::Kp::new(
2434 Option::<#inner_ty>::as_ref,
2435 Option::<#inner_ty>::as_mut,
2436 ),
2437 )
2438 }
2439 });
2440 }
2441 (WrapperKind::ArcRwLockOption, Some(inner_ty)) => {
2442 // For Arc<parking_lot::RwLock<Option<T>>> — SyncKp value T (extract from Option); guard gives &Option<T>
2443 let lock_kp_return_ty =
2444 kp_lock_ty_parking_lot_rw_lock_option(name, ty, &inner_ty);
2445 tokens.extend(quote! {
2446 #[inline(always)]
2447 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2448 rust_key_paths::sync_kp::SyncKp::new(
2449 rust_key_paths::Kp::new(
2450 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2451 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2452 ),
2453 rust_key_paths::sync_kp::ParkingLotRwLockAccess::<Option<#inner_ty>>::new(),
2454 rust_key_paths::Kp::new(
2455 Option::<#inner_ty>::as_ref,
2456 Option::<#inner_ty>::as_mut,
2457 ),
2458 )
2459 }
2460 });
2461 }
2462 (WrapperKind::Mutex, Some(_inner_ty))
2463 | (WrapperKind::StdMutex, Some(_inner_ty)) => {
2464 // For Mutex<T>, return keypath to container
2465 tokens.extend(quote! {
2466 #[inline(always)]
2467 pub fn #kp_fn() -> rust_key_paths::Kp<
2468 #name,
2469 #ty,
2470 &'static #name,
2471 &'static #ty,
2472 &'static mut #name,
2473 &'static mut #ty,
2474 impl Fn(&#name) -> Option<&#ty>,
2475 impl Fn(&mut #name) -> Option<&mut #ty>,
2476 > {
2477 rust_key_paths::Kp::new(
2478 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2479 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2480 )
2481 }
2482 });
2483 }
2484 (WrapperKind::RwLock, Some(_inner_ty))
2485 | (WrapperKind::StdRwLock, Some(_inner_ty)) => {
2486 // For RwLock<T>, return keypath to container
2487 tokens.extend(quote! {
2488 #[inline(always)]
2489 pub fn #kp_fn() -> rust_key_paths::Kp<
2490 #name,
2491 #ty,
2492 &'static #name,
2493 &'static #ty,
2494 &'static mut #name,
2495 &'static mut #ty,
2496 impl Fn(&#name) -> Option<&#ty>,
2497 impl Fn(&mut #name) -> Option<&mut #ty>,
2498 > {
2499 rust_key_paths::Kp::new(
2500 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2501 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2502 )
2503 }
2504 });
2505 }
2506 (WrapperKind::TokioArcMutex, Some(inner_ty)) => {
2507 let kp_async_fn = format_ident!("{}_kp", field_ident);
2508 tokens.extend(quote! {
2509 #[inline(always)]
2510 pub fn #kp_async_fn() -> rust_key_paths::Kp<
2511 #name,
2512 #ty,
2513 &'static #name,
2514 &'static #ty,
2515 &'static mut #name,
2516 &'static mut #ty,
2517 impl Fn(&#name) -> Option<&#ty>,
2518 impl Fn(&mut #name) -> Option<&mut #ty>,
2519 > {
2520 rust_key_paths::Kp::new(
2521 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2522 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2523 )
2524 }
2525 pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, #ty, #inner_ty> {
2526 rust_key_paths::async_lock::AsyncLockKp::new(
2527 rust_key_paths::Kp::new(
2528 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2529 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2530 ),
2531 rust_key_paths::async_lock::TokioMutexAccess::new(),
2532 rust_key_paths::Kp::new(
2533 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2534 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2535 ),
2536 )
2537 }
2538 });
2539 }
2540 (WrapperKind::TokioArcRwLock, Some(inner_ty)) => {
2541 let kp_async_fn = format_ident!("{}_kp", field_ident);
2542 tokens.extend(quote! {
2543 #[inline(always)]
2544 pub fn #kp_async_fn() -> rust_key_paths::Kp<
2545 #name,
2546 #ty,
2547 &'static #name,
2548 &'static #ty,
2549 &'static mut #name,
2550 &'static mut #ty,
2551 impl Fn(&#name) -> Option<&#ty>,
2552 impl Fn(&mut #name) -> Option<&mut #ty>,
2553 > {
2554 rust_key_paths::Kp::new(
2555 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2556 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2557 )
2558 }
2559 pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, #ty, #inner_ty> {
2560 rust_key_paths::async_lock::AsyncLockKp::new(
2561 rust_key_paths::Kp::new(
2562 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2563 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2564 ),
2565 rust_key_paths::async_lock::TokioRwLockAccess::new(),
2566 rust_key_paths::Kp::new(
2567 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2568 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2569 ),
2570 )
2571 }
2572 });
2573 }
2574 (WrapperKind::OptionTokioArcMutex, Some(inner_ty)) => {
2575 let kp_async_fn = format_ident!("{}_kp", field_ident);
2576 tokens.extend(quote! {
2577 #[inline(always)]
2578 pub fn #kp_async_fn() -> rust_key_paths::Kp<
2579 #name,
2580 #ty,
2581 &'static #name,
2582 &'static #ty,
2583 &'static mut #name,
2584 &'static mut #ty,
2585 impl Fn(&#name) -> Option<&#ty>,
2586 impl Fn(&mut #name) -> Option<&mut #ty>,
2587 > {
2588 rust_key_paths::Kp::new(
2589 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2590 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2591 )
2592 }
2593 pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, std::sync::Arc<tokio::sync::Mutex<#inner_ty>>, #inner_ty> {
2594 rust_key_paths::async_lock::AsyncLockKp::new(
2595 rust_key_paths::Kp::new(
2596 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
2597 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
2598 ),
2599 rust_key_paths::async_lock::TokioMutexAccess::new(),
2600 rust_key_paths::Kp::new(
2601 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2602 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2603 ),
2604 )
2605 }
2606 });
2607 }
2608 (WrapperKind::OptionTokioArcRwLock, Some(inner_ty)) => {
2609 let kp_async_fn = format_ident!("{}_kp", field_ident);
2610 tokens.extend(quote! {
2611 #[inline(always)]
2612 pub fn #kp_async_fn() -> rust_key_paths::Kp<
2613 #name,
2614 #ty,
2615 &'static #name,
2616 &'static #ty,
2617 &'static mut #name,
2618 &'static mut #ty,
2619 impl Fn(&#name) -> Option<&#ty>,
2620 impl Fn(&mut #name) -> Option<&mut #ty>,
2621 > {
2622 rust_key_paths::Kp::new(
2623 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2624 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2625 )
2626 }
2627 pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, std::sync::Arc<tokio::sync::RwLock<#inner_ty>>, #inner_ty> {
2628 rust_key_paths::async_lock::AsyncLockKp::new(
2629 rust_key_paths::Kp::new(
2630 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
2631 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
2632 ),
2633 rust_key_paths::async_lock::TokioRwLockAccess::new(),
2634 rust_key_paths::Kp::new(
2635 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2636 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2637 ),
2638 )
2639 }
2640 });
2641 }
2642 (WrapperKind::OptionStdArcMutex, Some(inner_ty)) => {
2643 // let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
2644 let lock_ty = quote! { std::sync::Arc<std::sync::Mutex<#inner_ty>> };
2645 let lock_kp_return_ty = kp_lock_ty_arc_mutex(name, &lock_ty, &inner_ty);
2646 tokens.extend(quote! {
2647 #[inline(always)]
2648 // pub fn #kp_unlocked_fn() -> rust_key_paths::Kp<#name, std::sync::Arc<std::sync::Mutex<#inner_ty>>, &'static #name, &'static std::sync::Arc<std::sync::Mutex<#inner_ty>>, &'static mut #name, &'static mut std::sync::Arc<std::sync::Mutex<#inner_ty>>, impl Fn(&#name) -> Option<&std::sync::Arc<std::sync::Mutex<#inner_ty>>>, impl Fn(&mut #name) -> Option<&mut std::sync::Arc<std::sync::Mutex<#inner_ty>>>,> {
2649 // rust_key_paths::Kp::new(
2650 // |root: &#name| root.#field_ident.as_ref(),
2651 // |root: &mut #name| root.#field_ident.as_mut(),
2652 // )
2653 // }
2654 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2655 rust_key_paths::sync_kp::SyncKp::new(
2656 rust_key_paths::Kp::new(
2657 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
2658 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
2659 ),
2660 rust_key_paths::sync_kp::ArcMutexAccess::new(),
2661 rust_key_paths::Kp::new(
2662 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2663 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2664 ),
2665 )
2666 }
2667 });
2668 }
2669 (WrapperKind::OptionArcMutex, Some(inner_ty)) => {
2670 // let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
2671 let lock_ty = quote! { std::sync::Arc<parking_lot::Mutex<#inner_ty>> };
2672 let lock_kp_return_ty =
2673 kp_lock_ty_parking_lot_mutex(name, &lock_ty, &inner_ty);
2674 tokens.extend(quote! {
2675 #[inline(always)]
2676 // pub fn #kp_unlocked_fn() -> rust_key_paths::Kp<#name, std::sync::Arc<parking_lot::Mutex<#inner_ty>>, &'static #name, &'static std::sync::Arc<parking_lot::Mutex<#inner_ty>>, &'static mut #name, &'static mut std::sync::Arc<parking_lot::Mutex<#inner_ty>>, impl Fn(&#name) -> Option<&std::sync::Arc<parking_lot::Mutex<#inner_ty>>>, impl Fn(&mut #name) -> Option<&mut std::sync::Arc<parking_lot::Mutex<#inner_ty>>>,> {
2677 // rust_key_paths::Kp::new(
2678 // |root: &#name| root.#field_ident.as_ref(),
2679 // |root: &mut #name| root.#field_ident.as_mut(),
2680 // )
2681 // }
2682 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2683 rust_key_paths::sync_kp::SyncKp::new(
2684 rust_key_paths::Kp::new(
2685 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
2686 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
2687 ),
2688 rust_key_paths::sync_kp::ParkingLotMutexAccess::new(),
2689 rust_key_paths::Kp::new(
2690 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2691 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2692 ),
2693 )
2694 }
2695 });
2696 }
2697 (WrapperKind::OptionStdArcRwLock, Some(inner_ty)) => {
2698 // let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
2699 let lock_ty = quote! { std::sync::Arc<std::sync::RwLock<#inner_ty>> };
2700 let lock_kp_return_ty =
2701 kp_lock_ty_arc_rw_lock(name, &lock_ty, &inner_ty);
2702 tokens.extend(quote! {
2703 #[inline(always)]
2704 // pub fn #kp_unlocked_fn() -> rust_key_paths::Kp<#name, std::sync::Arc<std::sync::RwLock<#inner_ty>>, &'static #name, &'static std::sync::Arc<std::sync::RwLock<#inner_ty>>, &'static mut #name, &'static mut std::sync::Arc<std::sync::RwLock<#inner_ty>>, impl Fn(&#name) -> Option<&std::sync::Arc<std::sync::RwLock<#inner_ty>>>, impl Fn(&mut #name) -> Option<&mut std::sync::Arc<std::sync::RwLock<#inner_ty>>>,> {
2705 // rust_key_paths::Kp::new(
2706 // |root: &#name| root.#field_ident.as_ref(),
2707 // |root: &mut #name| root.#field_ident.as_mut(),
2708 // )
2709 // }
2710 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2711 rust_key_paths::sync_kp::SyncKp::new(
2712 rust_key_paths::Kp::new(
2713 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
2714 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
2715 ),
2716 rust_key_paths::sync_kp::ArcRwLockAccess::new(),
2717 rust_key_paths::Kp::new(
2718 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2719 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2720 ),
2721 )
2722 }
2723 });
2724 }
2725 (WrapperKind::OptionArcArcSwap, Some(inner_ty)) => {
2726 let arc_mod = arc_swap_crate_ident_from_container_ty(ty);
2727 let lock_ty =
2728 quote! { ::std::sync::Arc<#arc_mod::ArcSwap<#inner_ty>> };
2729 let lock_kp_return_ty = kp_lock_ty_arc_arc_swap(name, &lock_ty, &inner_ty);
2730 tokens.extend(quote! {
2731 #[inline(always)]
2732 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2733 rust_key_paths::sync_kp::SyncKp::new(
2734 rust_key_paths::Kp::new(
2735 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
2736 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
2737 ),
2738 rust_key_paths::sync_kp::ArcArcSwapAccess::new(),
2739 rust_key_paths::Kp::new(
2740 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2741 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2742 ),
2743 )
2744 }
2745 });
2746 }
2747 (WrapperKind::OptionArcArcSwapOption, Some(inner_ty)) => {
2748 let arc_mod = arc_swap_crate_ident_from_container_ty(ty);
2749 let lock_ty =
2750 quote! { ::std::sync::Arc<#arc_mod::ArcSwapOption<#inner_ty>> };
2751 let lock_kp_return_ty =
2752 kp_lock_ty_arc_arc_swap_option(name, &lock_ty, &inner_ty);
2753 tokens.extend(quote! {
2754 #[inline(always)]
2755 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2756 rust_key_paths::sync_kp::SyncKp::new(
2757 rust_key_paths::Kp::new(
2758 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
2759 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
2760 ),
2761 rust_key_paths::sync_kp::ArcArcSwapOptionAccess::<#inner_ty>::new(),
2762 rust_key_paths::Kp::new(
2763 |o: &::std::option::Option<::std::sync::Arc<#inner_ty>>| {
2764 o.as_ref().map(|a| a.as_ref())
2765 },
2766 |o: &mut ::std::option::Option<::std::sync::Arc<#inner_ty>>| {
2767 o.as_mut().and_then(::std::sync::Arc::get_mut)
2768 },
2769 ),
2770 )
2771 }
2772 });
2773 }
2774 (WrapperKind::OptionArcRwLock, Some(inner_ty)) => {
2775 // let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
2776 let lock_ty = quote! { std::sync::Arc<parking_lot::RwLock<#inner_ty>> };
2777 let lock_kp_return_ty =
2778 kp_lock_ty_parking_lot_rw_lock(name, &lock_ty, &inner_ty);
2779 tokens.extend(quote! {
2780 #[inline(always)]
2781 // pub fn #kp_unlocked_fn() -> rust_key_paths::Kp<#name, std::sync::Arc<parking_lot::RwLock<#inner_ty>>, &'static #name, &'static std::sync::Arc<parking_lot::RwLock<#inner_ty>>, &'static mut #name, &'static mut std::sync::Arc<parking_lot::RwLock<#inner_ty>>, impl Fn(&#name) -> Option<&std::sync::Arc<parking_lot::RwLock<#inner_ty>>>, impl Fn(&mut #name) -> Option<&mut std::sync::Arc<parking_lot::RwLock<#inner_ty>>>,> {
2782 // rust_key_paths::Kp::new(
2783 // |root: &#name| root.#field_ident.as_ref(),
2784 // |root: &mut #name| root.#field_ident.as_mut(),
2785 // )
2786 // }
2787 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
2788 rust_key_paths::sync_kp::SyncKp::new(
2789 rust_key_paths::Kp::new(
2790 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
2791 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
2792 ),
2793 rust_key_paths::sync_kp::ParkingLotRwLockAccess::new(),
2794 rust_key_paths::Kp::new(
2795 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
2796 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
2797 ),
2798 )
2799 }
2800 });
2801 }
2802 (WrapperKind::OptionStdMutex, Some(inner_ty)) => {
2803 let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
2804 tokens.extend(quote! {
2805 #[inline(always)]
2806 pub fn #kp_fn() -> rust_key_paths::Kp<
2807 #name,
2808 #ty,
2809 &'static #name,
2810 &'static #ty,
2811 &'static mut #name,
2812 &'static mut #ty,
2813 impl Fn(&#name) -> Option<&#ty>,
2814 impl Fn(&mut #name) -> Option<&mut #ty>,
2815 > {
2816 rust_key_paths::Kp::new(
2817 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2818 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2819 )
2820 }
2821 pub fn #kp_unlocked_fn() -> rust_key_paths::Kp<
2822 #name,
2823 std::sync::Mutex<#inner_ty>,
2824 &'static #name,
2825 &'static std::sync::Mutex<#inner_ty>,
2826 &'static mut #name,
2827 &'static mut std::sync::Mutex<#inner_ty>,
2828 impl Fn(&#name) -> Option<&std::sync::Mutex<#inner_ty>>,
2829 impl Fn(&mut #name) -> Option<&mut std::sync::Mutex<#inner_ty>>,
2830> {
2831 rust_key_paths::Kp::new(
2832 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
2833 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
2834 )
2835 }
2836 });
2837 }
2838 (WrapperKind::OptionMutex, Some(inner_ty)) => {
2839 let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
2840 tokens.extend(quote! {
2841 #[inline(always)]
2842 pub fn #kp_fn() -> rust_key_paths::Kp<
2843 #name,
2844 #ty,
2845 &'static #name,
2846 &'static #ty,
2847 &'static mut #name,
2848 &'static mut #ty,
2849 impl Fn(&#name) -> Option<&#ty>,
2850 impl Fn(&mut #name) -> Option<&mut #ty>,
2851 > {
2852 rust_key_paths::Kp::new(
2853 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2854 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2855 )
2856 }
2857 pub fn #kp_unlocked_fn() -> rust_key_paths::Kp<
2858 #name,
2859 parking_lot::Mutex<#inner_ty>,
2860 &'static #name,
2861 &'static parking_lot::Mutex<#inner_ty>,
2862 &'static mut #name,
2863 &'static mut parking_lot::Mutex<#inner_ty>,
2864 impl Fn(&#name) -> Option<&parking_lot::Mutex<#inner_ty>>,
2865 impl Fn(&mut #name) -> Option<&mut parking_lot::Mutex<#inner_ty>>,
2866> {
2867 rust_key_paths::Kp::new(
2868 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
2869 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
2870 )
2871 }
2872 });
2873 }
2874 (WrapperKind::OptionStdRwLock, Some(inner_ty)) => {
2875 let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
2876 tokens.extend(quote! {
2877 #[inline(always)]
2878 pub fn #kp_fn() -> rust_key_paths::Kp<
2879 #name,
2880 #ty,
2881 &'static #name,
2882 &'static #ty,
2883 &'static mut #name,
2884 &'static mut #ty,
2885 impl Fn(&#name) -> Option<&#ty>,
2886 impl Fn(&mut #name) -> Option<&mut #ty>,
2887 > {
2888 rust_key_paths::Kp::new(
2889 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2890 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2891 )
2892 }
2893 pub fn #kp_unlocked_fn() -> rust_key_paths::Kp<
2894 #name,
2895 std::sync::RwLock<#inner_ty>,
2896 &'static #name,
2897 &'static std::sync::RwLock<#inner_ty>,
2898 &'static mut #name,
2899 &'static mut std::sync::RwLock<#inner_ty>,
2900 impl Fn(&#name) -> Option<&std::sync::RwLock<#inner_ty>>,
2901 impl Fn(&mut #name) -> Option<&mut std::sync::RwLock<#inner_ty>>,
2902> {
2903 rust_key_paths::Kp::new(
2904 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
2905 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
2906 )
2907 }
2908 });
2909 }
2910 (WrapperKind::OptionRwLock, Some(inner_ty)) => {
2911 let kp_unlocked_fn = format_ident!("{}_unlocked", field_ident);
2912 tokens.extend(quote! {
2913 #[inline(always)]
2914 pub fn #kp_fn() -> rust_key_paths::Kp<
2915 #name,
2916 #ty,
2917 &'static #name,
2918 &'static #ty,
2919 &'static mut #name,
2920 &'static mut #ty,
2921 impl Fn(&#name) -> Option<&#ty>,
2922 impl Fn(&mut #name) -> Option<&mut #ty>,
2923 > {
2924 rust_key_paths::Kp::new(
2925 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2926 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2927 )
2928 }
2929 pub fn #kp_unlocked_fn() -> rust_key_paths::Kp<
2930 #name,
2931 parking_lot::RwLock<#inner_ty>,
2932 &'static #name,
2933 &'static parking_lot::RwLock<#inner_ty>,
2934 &'static mut #name,
2935 &'static mut parking_lot::RwLock<#inner_ty>,
2936 impl Fn(&#name) -> Option<&parking_lot::RwLock<#inner_ty>>,
2937 impl Fn(&mut #name) -> Option<&mut parking_lot::RwLock<#inner_ty>>,
2938> {
2939 rust_key_paths::Kp::new(
2940 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
2941 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
2942 )
2943 }
2944 });
2945 }
2946 (WrapperKind::Weak, Some(_inner_ty)) => {
2947 // For Weak<T>, return keypath to container
2948 tokens.extend(quote! {
2949 #[inline(always)]
2950 pub fn #kp_fn() -> rust_key_paths::Kp<
2951 #name,
2952 #ty,
2953 &'static #name,
2954 &'static #ty,
2955 &'static mut #name,
2956 &'static mut #ty,
2957 impl Fn(&#name) -> Option<&#ty>,
2958 impl Fn(&mut #name) -> Option<&mut #ty>,
2959 > {
2960 rust_key_paths::Kp::new(
2961 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2962 rust_key_paths::constrain_set(|_root: &mut #name| None), // Weak doesn't support mutable access
2963 )
2964 }
2965 });
2966 }
2967 (WrapperKind::Atomic, None | Some(_)) => {
2968 // For atomic types: return keypath to the atomic (user calls .load()/.store())
2969 tokens.extend(quote! {
2970 #[inline(always)]
2971 pub fn #kp_fn() -> rust_key_paths::Kp<
2972 #name,
2973 #ty,
2974 &'static #name,
2975 &'static #ty,
2976 &'static mut #name,
2977 &'static mut #ty,
2978 impl Fn(&#name) -> Option<&#ty>,
2979 impl Fn(&mut #name) -> Option<&mut #ty>,
2980 > {
2981 rust_key_paths::Kp::new(
2982 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
2983 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
2984 )
2985 }
2986 });
2987 }
2988 (WrapperKind::OptionAtomic, Some(inner_ty)) => {
2989 tokens.extend(quote! {
2990 #[inline(always)]
2991 pub fn #kp_fn() -> rust_key_paths::Kp<
2992 #name,
2993 #inner_ty,
2994 &'static #name,
2995 &'static #inner_ty,
2996 &'static mut #name,
2997 &'static mut #inner_ty,
2998 impl Fn(&#name) -> Option<&#inner_ty>,
2999 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3000 > {
3001 rust_key_paths::Kp::new(
3002 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
3003 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
3004 )
3005 }
3006 });
3007 }
3008 (WrapperKind::String, None) => {
3009 tokens.extend(quote! {
3010 #[inline(always)]
3011 pub fn #kp_fn() -> rust_key_paths::Kp<
3012 #name,
3013 #ty,
3014 &'static #name,
3015 &'static #ty,
3016 &'static mut #name,
3017 &'static mut #ty,
3018 impl Fn(&#name) -> Option<&#ty>,
3019 impl Fn(&mut #name) -> Option<&mut #ty>,
3020 > {
3021 rust_key_paths::Kp::new(
3022 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
3023 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
3024 )
3025 }
3026 });
3027 }
3028 (WrapperKind::OptionString, None) => {
3029 tokens.extend(quote! {
3030 #[inline(always)]
3031 pub fn #kp_fn() -> rust_key_paths::Kp<#name, std::string::String, &'static #name, &'static std::string::String, &'static mut #name, &'static mut std::string::String, impl Fn(&#name) -> Option<&std::string::String>, impl Fn(&mut #name) -> Option<&mut std::string::String>,> {
3032 rust_key_paths::Kp::new(
3033 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref()),
3034 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_mut()),
3035 )
3036 }
3037 });
3038 }
3039 (WrapperKind::Cell, Some(_inner_ty)) => {
3040 tokens.extend(quote! {
3041 #[inline(always)]
3042 pub fn #kp_fn() -> rust_key_paths::Kp<
3043 #name,
3044 #ty,
3045 &'static #name,
3046 &'static #ty,
3047 &'static mut #name,
3048 &'static mut #ty,
3049 impl Fn(&#name) -> Option<&#ty>,
3050 impl Fn(&mut #name) -> Option<&mut #ty>,
3051 > {
3052 rust_key_paths::Kp::new(
3053 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
3054 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
3055 )
3056 }
3057 });
3058 }
3059 (WrapperKind::RefCell, Some(_inner_ty)) => {
3060 tokens.extend(quote! {
3061 #[inline(always)]
3062 pub fn #kp_fn() -> rust_key_paths::Kp<
3063 #name,
3064 #ty,
3065 &'static #name,
3066 &'static #ty,
3067 &'static mut #name,
3068 &'static mut #ty,
3069 impl Fn(&#name) -> Option<&#ty>,
3070 impl Fn(&mut #name) -> Option<&mut #ty>,
3071 > {
3072 rust_key_paths::Kp::new(
3073 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
3074 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
3075 )
3076 }
3077 });
3078 }
3079 (WrapperKind::OnceCell, Some(inner_ty)) => {
3080 // OnceLock/OnceCell: keypath to inner value; get = .get() -> Option<&T>, set = None
3081 tokens.extend(quote! {
3082 #[inline(always)]
3083 pub fn #kp_fn() -> rust_key_paths::Kp<
3084 #name,
3085 #inner_ty,
3086 &'static #name,
3087 &'static #inner_ty,
3088 &'static mut #name,
3089 &'static mut #inner_ty,
3090 impl Fn(&#name) -> Option<&#inner_ty>,
3091 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3092 > {
3093 rust_key_paths::Kp::new(
3094 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.get()),
3095 rust_key_paths::constrain_set(|_root: &mut #name| None),
3096 )
3097 }
3098 });
3099 }
3100 (WrapperKind::Lazy, Some(inner_ty)) => {
3101 // Lazy/LazyLock: keypath to inner value; get = .get() -> &T wrapped in Some, set = None
3102 tokens.extend(quote! {
3103 #[inline(always)]
3104 pub fn #kp_fn() -> rust_key_paths::Kp<
3105 #name,
3106 #inner_ty,
3107 &'static #name,
3108 &'static #inner_ty,
3109 &'static mut #name,
3110 &'static mut #inner_ty,
3111 impl Fn(&#name) -> Option<&#inner_ty>,
3112 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3113 > {
3114 rust_key_paths::Kp::new(
3115 rust_key_paths::constrain_get(|root: &#name| Some(root.#field_ident.get())),
3116 rust_key_paths::constrain_set(|_root: &mut #name| None),
3117 )
3118 }
3119 });
3120 }
3121 (WrapperKind::PhantomData, Some(_inner_ty)) => {
3122 tokens.extend(quote! {
3123 #[inline(always)]
3124 pub fn #kp_fn() -> rust_key_paths::Kp<
3125 #name,
3126 #ty,
3127 &'static #name,
3128 &'static #ty,
3129 &'static mut #name,
3130 &'static mut #ty,
3131 impl Fn(&#name) -> Option<&#ty>,
3132 impl Fn(&mut #name) -> Option<&mut #ty>,
3133 > {
3134 rust_key_paths::Kp::new(
3135 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
3136 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
3137 )
3138 }
3139 });
3140 }
3141 (WrapperKind::Range, Some(_inner_ty)) => {
3142 tokens.extend(quote! {
3143 #[inline(always)]
3144 pub fn #kp_fn() -> rust_key_paths::Kp<
3145 #name,
3146 #ty,
3147 &'static #name,
3148 &'static #ty,
3149 &'static mut #name,
3150 &'static mut #ty,
3151 impl Fn(&#name) -> Option<&#ty>,
3152 impl Fn(&mut #name) -> Option<&mut #ty>,
3153 > {
3154 rust_key_paths::Kp::new(
3155 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
3156 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
3157 )
3158 }
3159 });
3160 }
3161 (WrapperKind::OptionCell, Some(_inner_ty)) => {
3162 tokens.extend(quote! {
3163 #[inline(always)]
3164 pub fn #kp_fn() -> rust_key_paths::Kp<
3165 #name,
3166 #ty,
3167 &'static #name,
3168 &'static #ty,
3169 &'static mut #name,
3170 &'static mut #ty,
3171 impl Fn(&#name) -> Option<&#ty>,
3172 impl Fn(&mut #name) -> Option<&mut #ty>,
3173 > {
3174 rust_key_paths::Kp::new(
3175 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
3176 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
3177 )
3178 }
3179 });
3180 }
3181 (WrapperKind::OptionRefCell, Some(inner_ty)) => {
3182 // Option<RefCell<T>>: keypath to T via borrow()/borrow_mut(); get returns Option<Ref<V>> so caller holds guard (deref for &V)
3183 tokens.extend(quote! {
3184 #[inline(always)]
3185 pub fn #kp_fn() -> rust_key_paths::KpOptionRefCellType<'_, #name, #inner_ty> {
3186 rust_key_paths::Kp::new(
3187 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref().map(|r| r.borrow())),
3188 rust_key_paths::constrain_set(|root: &mut #name| root.#field_ident.as_ref().map(|r| r.borrow_mut())),
3189 )
3190 }
3191 });
3192 }
3193 (WrapperKind::OptionOnceCell, Some(inner_ty)) => {
3194 tokens.extend(quote! {
3195 #[inline(always)]
3196 pub fn #kp_fn() -> rust_key_paths::Kp<
3197 #name,
3198 #inner_ty,
3199 &'static #name,
3200 &'static #inner_ty,
3201 &'static mut #name,
3202 &'static mut #inner_ty,
3203 impl Fn(&#name) -> Option<&#inner_ty>,
3204 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3205 > {
3206 rust_key_paths::Kp::new(
3207 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref().and_then(|c| c.get())),
3208 rust_key_paths::constrain_set(|_root: &mut #name| None),
3209 )
3210 }
3211 });
3212 }
3213 (WrapperKind::OptionLazy, Some(inner_ty)) => {
3214 tokens.extend(quote! {
3215 #[inline(always)]
3216 pub fn #kp_fn() -> rust_key_paths::Kp<
3217 #name,
3218 #inner_ty,
3219 &'static #name,
3220 &'static #inner_ty,
3221 &'static mut #name,
3222 &'static mut #inner_ty,
3223 impl Fn(&#name) -> Option<&#inner_ty>,
3224 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3225 > {
3226 rust_key_paths::Kp::new(
3227 rust_key_paths::constrain_get(|root: &#name| root.#field_ident.as_ref().map(|c| c.get())),
3228 rust_key_paths::constrain_set(|_root: &mut #name| None),
3229 )
3230 }
3231 });
3232 }
3233 (WrapperKind::OptionPhantomData, Some(_inner_ty)) => {
3234 tokens.extend(quote! {
3235 #[inline(always)]
3236 pub fn #kp_fn() -> rust_key_paths::Kp<
3237 #name,
3238 #ty,
3239 &'static #name,
3240 &'static #ty,
3241 &'static mut #name,
3242 &'static mut #ty,
3243 impl Fn(&#name) -> Option<&#ty>,
3244 impl Fn(&mut #name) -> Option<&mut #ty>,
3245 > {
3246 rust_key_paths::Kp::new(
3247 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
3248 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
3249 )
3250 }
3251 });
3252 }
3253 (WrapperKind::OptionRange, Some(_inner_ty)) => {
3254 tokens.extend(quote! {
3255 #[inline(always)]
3256 pub fn #kp_fn() -> rust_key_paths::Kp<
3257 #name,
3258 #ty,
3259 &'static #name,
3260 &'static #ty,
3261 &'static mut #name,
3262 &'static mut #ty,
3263 impl Fn(&#name) -> Option<&#ty>,
3264 impl Fn(&mut #name) -> Option<&mut #ty>,
3265 > {
3266 rust_key_paths::Kp::new(
3267 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
3268 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
3269 )
3270 }
3271 });
3272 }
3273 (WrapperKind::Reference, Some(_inner_ty)) => {
3274 // For reference types (&T, &str, &[T]): read-only, setter returns None
3275 tokens.extend(quote! {
3276 #[inline(always)]
3277 pub fn #kp_fn() -> rust_key_paths::Kp<
3278 #name,
3279 #ty,
3280 &'static #name,
3281 &'static #ty,
3282 &'static mut #name,
3283 &'static mut #ty,
3284 impl Fn(&#name) -> Option<&#ty>,
3285 impl Fn(&mut #name) -> Option<&mut #ty>,
3286 > {
3287 rust_key_paths::Kp::new(
3288 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
3289 rust_key_paths::constrain_set(|_root: &mut #name| None), // references: read-only
3290 )
3291 }
3292 });
3293 }
3294 (WrapperKind::None, None) => {
3295 // For basic types, direct access
3296 tokens.extend(quote! {
3297 #[inline(always)]
3298 pub fn #kp_fn() -> rust_key_paths::Kp<
3299 #name,
3300 #ty,
3301 &'static #name,
3302 &'static #ty,
3303 &'static mut #name,
3304 &'static mut #ty,
3305 impl Fn(&#name) -> Option<&#ty>,
3306 impl Fn(&mut #name) -> Option<&mut #ty>,
3307 > {
3308 rust_key_paths::Kp::new(
3309 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
3310 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
3311 )
3312 }
3313 });
3314 }
3315 _ => {
3316 // For unknown/complex nested types, return keypath to field itself
3317 tokens.extend(quote! {
3318 #[inline(always)]
3319 pub fn #kp_fn() -> rust_key_paths::Kp<
3320 #name,
3321 #ty,
3322 &'static #name,
3323 &'static #ty,
3324 &'static mut #name,
3325 &'static mut #ty,
3326 impl Fn(&#name) -> Option<&#ty>,
3327 impl Fn(&mut #name) -> Option<&mut #ty>,
3328 > {
3329 rust_key_paths::Kp::new(
3330 rust_key_paths::constrain_get(|root: &#name| Some(&root.#field_ident)),
3331 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#field_ident)),
3332 )
3333 }
3334 });
3335 }
3336 }
3337 }
3338
3339 tokens
3340 }
3341 Fields::Unnamed(unnamed) => {
3342 let mut tokens = proc_macro2::TokenStream::new();
3343
3344 // Generate identity methods for the tuple struct
3345 tokens.extend(quote! {
3346 /// Returns a generic identity keypath for this type
3347 #[inline(always)]
3348 pub fn identity_typed<'a, Root, MutRoot>() -> rust_key_paths::Kp<
3349 #name,
3350 #name,
3351 Root,
3352 Root,
3353 MutRoot,
3354 MutRoot,
3355 fn(Root) -> Option<Root>,
3356 fn(MutRoot) -> Option<MutRoot>,
3357 >
3358 where
3359 Root: std::borrow::Borrow<#name>,
3360 MutRoot: std::borrow::BorrowMut<#name>,
3361 {
3362 rust_key_paths::Kp::new(
3363 |r: Root| Some(r),
3364 |r: MutRoot| Some(r)
3365 )
3366 }
3367
3368 /// Returns a simple identity keypath for this type
3369 #[inline(always)]
3370 pub fn identity() -> rust_key_paths::Kp<#name, #name, &'static #name, &'static #name, &'static mut #name, &'static mut #name, impl Fn(&#name) -> Option<&#name>, impl Fn(&mut #name) -> Option<&mut #name>,> {
3371 rust_key_paths::Kp::new(
3372 rust_key_paths::constrain_get(|r: &#name| Some(r)),
3373 rust_key_paths::constrain_set(|r: &mut #name| Some(r))
3374 )
3375 }
3376 });
3377
3378 for (idx, field) in unnamed.unnamed.iter().enumerate() {
3379 let idx_lit = syn::Index::from(idx);
3380 let ty = &field.ty;
3381 // Centralized keypath method names for tuple fields – change here to adjust for all types
3382 let kp_fn = format_ident!("f{}", idx);
3383 let kp_at_fn = format_ident!("f{}_at", idx);
3384
3385 let (kind, inner_ty) = extract_wrapper_inner_type(ty);
3386
3387 match (kind, inner_ty.clone()) {
3388 (WrapperKind::Option, Some(inner_ty)) => {
3389 tokens.extend(quote! {
3390 #[inline(always)]
3391 pub fn #kp_fn() -> rust_key_paths::Kp<
3392 #name,
3393 #inner_ty,
3394 &'static #name,
3395 &'static #inner_ty,
3396 &'static mut #name,
3397 &'static mut #inner_ty,
3398 impl Fn(&#name) -> Option<&#inner_ty>,
3399 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3400 > {
3401 rust_key_paths::Kp::new(
3402 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
3403 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut()),
3404 )
3405 }
3406 });
3407 }
3408 (WrapperKind::OptionBox, Some(inner_ty)) => {
3409 tokens.extend(quote! {
3410 #[inline(always)]
3411 pub fn #kp_fn() -> rust_key_paths::Kp<
3412 #name,
3413 #inner_ty,
3414 &'static #name,
3415 &'static #inner_ty,
3416 &'static mut #name,
3417 &'static mut #inner_ty,
3418 impl Fn(&#name) -> Option<&#inner_ty>,
3419 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3420 > {
3421 rust_key_paths::Kp::new(
3422 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_deref()),
3423 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_deref_mut()),
3424 )
3425 }
3426 });
3427 }
3428 (WrapperKind::OptionRc, Some(inner_ty)) => {
3429 tokens.extend(quote! {
3430 #[inline(always)]
3431 pub fn #kp_fn() -> rust_key_paths::Kp<
3432 #name,
3433 #inner_ty,
3434 &'static #name,
3435 &'static #inner_ty,
3436 &'static mut #name,
3437 &'static mut #inner_ty,
3438 impl Fn(&#name) -> Option<&#inner_ty>,
3439 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3440 > {
3441 rust_key_paths::Kp::new(
3442 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_deref()),
3443 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut().and_then(std::rc::Rc::get_mut)),
3444 )
3445 }
3446 });
3447 }
3448 (WrapperKind::OptionArc, Some(inner_ty)) => {
3449 tokens.extend(quote! {
3450 #[inline(always)]
3451 pub fn #kp_fn() -> rust_key_paths::Kp<
3452 #name,
3453 #inner_ty,
3454 &'static #name,
3455 &'static #inner_ty,
3456 &'static mut #name,
3457 &'static mut #inner_ty,
3458 impl Fn(&#name) -> Option<&#inner_ty>,
3459 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3460 > {
3461 rust_key_paths::Kp::new(
3462 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_deref()),
3463 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut().and_then(std::sync::Arc::get_mut)),
3464 )
3465 }
3466 });
3467 }
3468 (WrapperKind::OptionHashMap, Some(inner_ty)) => {
3469 if let Some((key_ty, _)) = extract_map_key_value_through_option(ty) {
3470 let type_name = name.to_string();
3471 let whole_fn = kp_fn.to_string();
3472 let at_fn = kp_at_fn.to_string();
3473 let whole_doc = format!(
3474 "Keypath to the whole optional `HashMap` (`{type_name}::{whole_fn}`). For a value at one key when the map is `Some`, use `{type_name}::{at_fn}(key)`."
3475 );
3476 let at_doc = format!(
3477 "Keyed access into the inner `HashMap` (`{type_name}::{at_fn}`). `get`/`get_mut` return `None` if the field is `None` or the key is missing. See also `{type_name}::{whole_fn}` for the full optional map."
3478 );
3479 tokens.extend(quote! {
3480 #[doc = #whole_doc]
3481 #[inline(always)]
3482 pub fn #kp_fn() -> rust_key_paths::Kp<
3483 #name,
3484 #ty,
3485 &'static #name,
3486 &'static #ty,
3487 &'static mut #name,
3488 &'static mut #ty,
3489 impl Fn(&#name) -> Option<&#ty>,
3490 impl Fn(&mut #name) -> Option<&mut #ty>,
3491 > {
3492 rust_key_paths::Kp::new(
3493 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3494 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3495 )
3496 }
3497 #[doc = #at_doc]
3498 #[inline(always)]
3499 pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
3500 where
3501 #key_ty: Clone + std::hash::Hash + Eq + 'static,
3502 {
3503 let key2 = key.clone();
3504 rust_key_paths::Kp::new(
3505 Box::new(move |root: &#name| root.#idx_lit.as_ref().and_then(|m| m.get(&key))),
3506 Box::new(move |root: &mut #name| root.#idx_lit.as_mut().and_then(|m| m.get_mut(&key2))),
3507 )
3508 }
3509 });
3510 } else {
3511 tokens.extend(quote! {
3512 #[inline(always)]
3513 pub fn #kp_fn() -> rust_key_paths::Kp<
3514 #name,
3515 #ty,
3516 &'static #name,
3517 &'static #ty,
3518 &'static mut #name,
3519 &'static mut #ty,
3520 impl Fn(&#name) -> Option<&#ty>,
3521 impl Fn(&mut #name) -> Option<&mut #ty>,
3522 > {
3523 rust_key_paths::Kp::new(
3524 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3525 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3526 )
3527 }
3528 });
3529 }
3530 }
3531 (WrapperKind::OptionBTreeMap, Some(inner_ty)) => {
3532 if let Some((key_ty, _)) = extract_map_key_value_through_option(ty) {
3533 let type_name = name.to_string();
3534 let whole_fn = kp_fn.to_string();
3535 let at_fn = kp_at_fn.to_string();
3536 let whole_doc = format!(
3537 "Keypath to the whole optional `BTreeMap` (`{type_name}::{whole_fn}`). For a value at one key when the map is `Some`, use `{type_name}::{at_fn}(key)`."
3538 );
3539 let at_doc = format!(
3540 "Keyed access into the inner `BTreeMap` (`{type_name}::{at_fn}`). `get`/`get_mut` return `None` if the field is `None` or the key is missing. See also `{type_name}::{whole_fn}` for the full optional map."
3541 );
3542 tokens.extend(quote! {
3543 #[doc = #whole_doc]
3544 #[inline(always)]
3545 pub fn #kp_fn() -> rust_key_paths::Kp<
3546 #name,
3547 #ty,
3548 &'static #name,
3549 &'static #ty,
3550 &'static mut #name,
3551 &'static mut #ty,
3552 impl Fn(&#name) -> Option<&#ty>,
3553 impl Fn(&mut #name) -> Option<&mut #ty>,
3554 > {
3555 rust_key_paths::Kp::new(
3556 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3557 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3558 )
3559 }
3560 #[doc = #at_doc]
3561 #[inline(always)]
3562 pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
3563 where
3564 #key_ty: Clone + Ord + 'static,
3565 {
3566 let key2 = key.clone();
3567 rust_key_paths::Kp::new(
3568 Box::new(move |root: &#name| root.#idx_lit.as_ref().and_then(|m| m.get(&key))),
3569 Box::new(move |root: &mut #name| root.#idx_lit.as_mut().and_then(|m| m.get_mut(&key2))),
3570 )
3571 }
3572 });
3573 } else {
3574 tokens.extend(quote! {
3575 #[inline(always)]
3576 pub fn #kp_fn() -> rust_key_paths::Kp<
3577 #name,
3578 #ty,
3579 &'static #name,
3580 &'static #ty,
3581 &'static mut #name,
3582 &'static mut #ty,
3583 impl Fn(&#name) -> Option<&#ty>,
3584 impl Fn(&mut #name) -> Option<&mut #ty>,
3585 > {
3586 rust_key_paths::Kp::new(
3587 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3588 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3589 )
3590 }
3591 });
3592 }
3593 }
3594 (WrapperKind::OptionHashSet, Some(inner_ty)) => {
3595 tokens.extend(quote! {
3596 #[inline(always)]
3597 pub fn #kp_fn() -> rust_key_paths::Kp<
3598 #name,
3599 #ty,
3600 &'static #name,
3601 &'static #ty,
3602 &'static mut #name,
3603 &'static mut #ty,
3604 impl Fn(&#name) -> Option<&#ty>,
3605 impl Fn(&mut #name) -> Option<&mut #ty>,
3606 > {
3607 rust_key_paths::Kp::new(
3608 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3609 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3610 )
3611 }
3612
3613 /// _at: check if element exists and get reference.
3614 /// HashSet does not allow mutable element access (would break hash invariant).
3615 #[inline(always)]
3616 pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
3617 where
3618 #inner_ty: Clone + std::hash::Hash + Eq + 'static,
3619 {
3620 rust_key_paths::Kp::new(
3621 Box::new(move |root: &#name| root.#idx_lit.as_ref().and_then(|s| s.get(&key))),
3622 Box::new(move |_root: &mut #name| None),
3623 )
3624 }
3625 });
3626 }
3627 (WrapperKind::OptionBTreeSet, Some(inner_ty)) => {
3628 tokens.extend(quote! {
3629 #[inline(always)]
3630 pub fn #kp_fn() -> rust_key_paths::Kp<
3631 #name,
3632 #ty,
3633 &'static #name,
3634 &'static #ty,
3635 &'static mut #name,
3636 &'static mut #ty,
3637 impl Fn(&#name) -> Option<&#ty>,
3638 impl Fn(&mut #name) -> Option<&mut #ty>,
3639 > {
3640 rust_key_paths::Kp::new(
3641 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3642 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3643 )
3644 }
3645
3646 /// _at: check if element exists and get reference.
3647 /// BTreeSet does not allow mutable element access (would break ordering invariant).
3648 #[inline(always)]
3649 pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
3650 where
3651 #inner_ty: Clone + Ord + 'static,
3652 {
3653 rust_key_paths::Kp::new(
3654 Box::new(move |root: &#name| root.#idx_lit.as_ref().and_then(|s| s.get(&key))),
3655 Box::new(move |_root: &mut #name| None),
3656 )
3657 }
3658 });
3659 }
3660 (WrapperKind::OptionVec, Some(inner_ty)) => {
3661 tokens.extend(quote! {
3662 #[inline(always)]
3663 pub fn #kp_fn() -> rust_key_paths::Kp<
3664 #name,
3665 #ty,
3666 &'static #name,
3667 &'static #ty,
3668 &'static mut #name,
3669 &'static mut #ty,
3670 impl Fn(&#name) -> Option<&#ty>,
3671 impl Fn(&mut #name) -> Option<&mut #ty>,
3672 > {
3673 rust_key_paths::Kp::new(
3674 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3675 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3676 )
3677 }
3678 #[inline(always)]
3679 pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
3680 rust_key_paths::Kp::new(
3681 Box::new(move |root: &#name| root.#idx_lit.as_ref().and_then(|v| v.get(index))),
3682 Box::new(move |root: &mut #name| root.#idx_lit.as_mut().and_then(|v| v.get_mut(index))),
3683 )
3684 }
3685 });
3686 }
3687 (WrapperKind::OptionVecDeque, Some(inner_ty)) => {
3688 tokens.extend(quote! {
3689 #[inline(always)]
3690 pub fn #kp_fn() -> rust_key_paths::Kp<
3691 #name,
3692 #ty,
3693 &'static #name,
3694 &'static #ty,
3695 &'static mut #name,
3696 &'static mut #ty,
3697 impl Fn(&#name) -> Option<&#ty>,
3698 impl Fn(&mut #name) -> Option<&mut #ty>,
3699 > {
3700 rust_key_paths::Kp::new(
3701 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3702 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3703 )
3704 }
3705 #[inline(always)]
3706 pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
3707 rust_key_paths::Kp::new(
3708 Box::new(move |root: &#name| root.#idx_lit.as_ref().and_then(|v| v.get(index))),
3709 Box::new(move |root: &mut #name| root.#idx_lit.as_mut().and_then(|v| v.get_mut(index))),
3710 )
3711 }
3712 });
3713 }
3714 (WrapperKind::OptionLinkedList, Some(_inner_ty))
3715 | (WrapperKind::OptionBinaryHeap, Some(_inner_ty))
3716 | (WrapperKind::OptionResult, Some(_inner_ty)) => {
3717 tokens.extend(quote! {
3718 #[inline(always)]
3719 pub fn #kp_fn() -> rust_key_paths::Kp<
3720 #name,
3721 #ty,
3722 &'static #name,
3723 &'static #ty,
3724 &'static mut #name,
3725 &'static mut #ty,
3726 impl Fn(&#name) -> Option<&#ty>,
3727 impl Fn(&mut #name) -> Option<&mut #ty>,
3728 > {
3729 rust_key_paths::Kp::new(
3730 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3731 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3732 )
3733 }
3734 });
3735 }
3736 (WrapperKind::Vec, Some(inner_ty)) => {
3737 tokens.extend(quote! {
3738 #[inline(always)]
3739 pub fn #kp_fn() -> rust_key_paths::Kp<
3740 #name,
3741 #ty,
3742 &'static #name,
3743 &'static #ty,
3744 &'static mut #name,
3745 &'static mut #ty,
3746 impl Fn(&#name) -> Option<&#ty>,
3747 impl Fn(&mut #name) -> Option<&mut #ty>,
3748 > {
3749 rust_key_paths::Kp::new(
3750 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3751 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3752 )
3753 }
3754 #[inline(always)]
3755 pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
3756 rust_key_paths::Kp::new(
3757 Box::new(move |root: &#name| root.#idx_lit.get(index)),
3758 Box::new(move |root: &mut #name| root.#idx_lit.get_mut(index)),
3759 )
3760 }
3761 });
3762 }
3763 (WrapperKind::HashMap, Some(inner_ty)) => {
3764 if let Some((key_ty, _)) = extract_map_key_value(ty) {
3765 tokens.extend(quote! {
3766 #[inline(always)]
3767 pub fn #kp_fn() -> rust_key_paths::Kp<
3768 #name,
3769 #ty,
3770 &'static #name,
3771 &'static #ty,
3772 &'static mut #name,
3773 &'static mut #ty,
3774 impl Fn(&#name) -> Option<&#ty>,
3775 impl Fn(&mut #name) -> Option<&mut #ty>,
3776 > {
3777 rust_key_paths::Kp::new(
3778 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3779 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3780 )
3781 }
3782 #[inline(always)]
3783 pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
3784 where
3785 #key_ty: Clone + std::hash::Hash + Eq + 'static,
3786 {
3787 let key2 = key.clone();
3788 rust_key_paths::Kp::new(
3789 Box::new(move |root: &#name| root.#idx_lit.get(&key)),
3790 Box::new(move |root: &mut #name| root.#idx_lit.get_mut(&key2)),
3791 )
3792 }
3793 });
3794 } else {
3795 tokens.extend(quote! {
3796 #[inline(always)]
3797 pub fn #kp_fn() -> rust_key_paths::Kp<
3798 #name,
3799 #ty,
3800 &'static #name,
3801 &'static #ty,
3802 &'static mut #name,
3803 &'static mut #ty,
3804 impl Fn(&#name) -> Option<&#ty>,
3805 impl Fn(&mut #name) -> Option<&mut #ty>,
3806 > {
3807 rust_key_paths::Kp::new(
3808 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3809 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3810 )
3811 }
3812 });
3813 }
3814 }
3815 (WrapperKind::BTreeMap, Some(inner_ty))
3816 | (WrapperKind::BTreeMapOption, Some(inner_ty)) => {
3817 if let Some((key_ty, _)) = extract_map_key_value(ty) {
3818 tokens.extend(quote! {
3819 #[inline(always)]
3820 pub fn #kp_fn() -> rust_key_paths::Kp<
3821 #name,
3822 #ty,
3823 &'static #name,
3824 &'static #ty,
3825 &'static mut #name,
3826 &'static mut #ty,
3827 impl Fn(&#name) -> Option<&#ty>,
3828 impl Fn(&mut #name) -> Option<&mut #ty>,
3829 > {
3830 rust_key_paths::Kp::new(
3831 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3832 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3833 )
3834 }
3835 #[inline(always)]
3836 pub fn #kp_at_fn(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
3837 where
3838 #key_ty: Clone + Ord + 'static,
3839 {
3840 let key2 = key.clone();
3841 rust_key_paths::Kp::new(
3842 Box::new(move |root: &#name| root.#idx_lit.get(&key)),
3843 Box::new(move |root: &mut #name| root.#idx_lit.get_mut(&key2)),
3844 )
3845 }
3846 });
3847 } else {
3848 tokens.extend(quote! {
3849 #[inline(always)]
3850 pub fn #kp_fn() -> rust_key_paths::Kp<
3851 #name,
3852 #ty,
3853 &'static #name,
3854 &'static #ty,
3855 &'static mut #name,
3856 &'static mut #ty,
3857 impl Fn(&#name) -> Option<&#ty>,
3858 impl Fn(&mut #name) -> Option<&mut #ty>,
3859 > {
3860 rust_key_paths::Kp::new(
3861 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3862 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3863 )
3864 }
3865 });
3866 }
3867 }
3868 (WrapperKind::Box, Some(inner_ty)) => {
3869 // Box: deref to inner (returns &T / &mut T)
3870 tokens.extend(quote! {
3871 #[inline(always)]
3872 pub fn #kp_fn() -> rust_key_paths::Kp<
3873 #name,
3874 #inner_ty,
3875 &'static #name,
3876 &'static #inner_ty,
3877 &'static mut #name,
3878 &'static mut #inner_ty,
3879 impl Fn(&#name) -> Option<&#inner_ty>,
3880 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3881 > {
3882 rust_key_paths::Kp::new(
3883 rust_key_paths::constrain_get(|root: &#name| Some(&*root.#idx_lit)),
3884 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut *root.#idx_lit)),
3885 )
3886 }
3887 });
3888 }
3889 (WrapperKind::BoxOption, Some(inner_ty)) => {
3890 tokens.extend(quote! {
3891 #[inline(always)]
3892 pub fn #kp_fn() -> rust_key_paths::Kp<
3893 #name,
3894 #inner_ty,
3895 &'static #name,
3896 &'static #inner_ty,
3897 &'static mut #name,
3898 &'static mut #inner_ty,
3899 impl Fn(&#name) -> Option<&#inner_ty>,
3900 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3901 > {
3902 rust_key_paths::Kp::new(
3903 rust_key_paths::constrain_get(|root: &#name| (&*root.#idx_lit).as_ref()),
3904 rust_key_paths::constrain_set(|root: &mut #name| (&mut *root.#idx_lit).as_mut()),
3905 )
3906 }
3907 });
3908 }
3909 (WrapperKind::RcOption, Some(inner_ty)) => {
3910 tokens.extend(quote! {
3911 #[inline(always)]
3912 pub fn #kp_fn() -> rust_key_paths::Kp<
3913 #name,
3914 #inner_ty,
3915 &'static #name,
3916 &'static #inner_ty,
3917 &'static mut #name,
3918 &'static mut #inner_ty,
3919 impl Fn(&#name) -> Option<&#inner_ty>,
3920 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3921 > {
3922 rust_key_paths::Kp::new(
3923 rust_key_paths::constrain_get(|root: &#name| (&*root.#idx_lit).as_ref()),
3924 rust_key_paths::constrain_set(|root: &mut #name| std::rc::Rc::get_mut(&mut root.#idx_lit).and_then(std::option::Option::as_mut)),
3925 )
3926 }
3927 });
3928 }
3929 (WrapperKind::ArcOption, Some(inner_ty)) => {
3930 tokens.extend(quote! {
3931 #[inline(always)]
3932 pub fn #kp_fn() -> rust_key_paths::Kp<
3933 #name,
3934 #inner_ty,
3935 &'static #name,
3936 &'static #inner_ty,
3937 &'static mut #name,
3938 &'static mut #inner_ty,
3939 impl Fn(&#name) -> Option<&#inner_ty>,
3940 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3941 > {
3942 rust_key_paths::Kp::new(
3943 rust_key_paths::constrain_get(|root: &#name| (&*root.#idx_lit).as_ref()),
3944 rust_key_paths::constrain_set(|root: &mut #name| std::sync::Arc::get_mut(&mut root.#idx_lit).and_then(std::option::Option::as_mut)),
3945 )
3946 }
3947 });
3948 }
3949 (WrapperKind::Pin, Some(inner_ty)) => {
3950 let kp_inner_fn = format_ident!("{}_inner", kp_fn);
3951 tokens.extend(quote! {
3952 #[inline(always)]
3953 pub fn #kp_fn() -> rust_key_paths::Kp<
3954 #name,
3955 #ty,
3956 &'static #name,
3957 &'static #ty,
3958 &'static mut #name,
3959 &'static mut #ty,
3960 impl Fn(&#name) -> Option<&#ty>,
3961 impl Fn(&mut #name) -> Option<&mut #ty>,
3962 > {
3963 rust_key_paths::Kp::new(
3964 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
3965 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
3966 )
3967 }
3968 #[inline(always)]
3969 pub fn #kp_inner_fn() -> rust_key_paths::Kp<
3970 #name,
3971 #inner_ty,
3972 &'static #name,
3973 &'static #inner_ty,
3974 &'static mut #name,
3975 &'static mut #inner_ty,
3976 impl Fn(&#name) -> Option<&#inner_ty>,
3977 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
3978>
3979>
3980 where #inner_ty: std::marker::Unpin
3981 {
3982 rust_key_paths::Kp::new(
3983 rust_key_paths::constrain_get(|root: &#name| Some(std::pin::Pin::as_ref(&root.#idx_lit).get_ref())),
3984 rust_key_paths::constrain_set(|root: &mut #name| Some(std::pin::Pin::as_mut(&mut root.#idx_lit).get_mut())),
3985 )
3986 }
3987 });
3988 }
3989 (WrapperKind::PinBox, Some(inner_ty)) => {
3990 let kp_inner_fn = format_ident!("{}_inner", kp_fn);
3991 tokens.extend(quote! {
3992 #[inline(always)]
3993 pub fn #kp_fn() -> rust_key_paths::Kp<
3994 #name,
3995 #ty,
3996 &'static #name,
3997 &'static #ty,
3998 &'static mut #name,
3999 &'static mut #ty,
4000 impl Fn(&#name) -> Option<&#ty>,
4001 impl Fn(&mut #name) -> Option<&mut #ty>,
4002 > {
4003 rust_key_paths::Kp::new(
4004 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4005 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4006 )
4007 }
4008 #[inline(always)]
4009 pub fn #kp_inner_fn() -> rust_key_paths::Kp<
4010 #name,
4011 #inner_ty,
4012 &'static #name,
4013 &'static #inner_ty,
4014 &'static mut #name,
4015 &'static mut #inner_ty,
4016 impl Fn(&#name) -> Option<&#inner_ty>,
4017 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
4018>
4019>
4020 where #inner_ty: std::marker::Unpin
4021 {
4022 rust_key_paths::Kp::new(
4023 rust_key_paths::constrain_get(|root: &#name| Some(std::pin::Pin::as_ref(&root.#idx_lit).get_ref())),
4024 rust_key_paths::constrain_set(|root: &mut #name| Some(std::pin::Pin::as_mut(&mut root.#idx_lit).get_mut())),
4025 )
4026 }
4027 });
4028 }
4029 (WrapperKind::Rc, Some(inner_ty)) => {
4030 tokens.extend(quote! {
4031 #[inline(always)]
4032 pub fn #kp_fn() -> rust_key_paths::Kp<
4033 #name,
4034 #inner_ty,
4035 &'static #name,
4036 &'static #inner_ty,
4037 &'static mut #name,
4038 &'static mut #inner_ty,
4039 impl Fn(&#name) -> Option<&#inner_ty>,
4040 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
4041 > {
4042 rust_key_paths::Kp::new(
4043 rust_key_paths::constrain_get(|root: &#name| Some(root.#idx_lit.as_ref())),
4044 rust_key_paths::constrain_set(|root: &mut #name| std::rc::Rc::get_mut(&mut root.#idx_lit)),
4045 )
4046 }
4047 });
4048 }
4049 (WrapperKind::Arc, Some(inner_ty)) => {
4050 tokens.extend(quote! {
4051 #[inline(always)]
4052 pub fn #kp_fn() -> rust_key_paths::Kp<
4053 #name,
4054 #inner_ty,
4055 &'static #name,
4056 &'static #inner_ty,
4057 &'static mut #name,
4058 &'static mut #inner_ty,
4059 impl Fn(&#name) -> Option<&#inner_ty>,
4060 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
4061 > {
4062 rust_key_paths::Kp::new(
4063 rust_key_paths::constrain_get(|root: &#name| Some(root.#idx_lit.as_ref())),
4064 rust_key_paths::constrain_set(|root: &mut #name| std::sync::Arc::get_mut(&mut root.#idx_lit)),
4065 )
4066 }
4067 });
4068 }
4069
4070 (WrapperKind::Cow, Some(inner_ty)) => {
4071 tokens.extend(quote! {
4072 #[inline(always)]
4073 pub fn #kp_fn() -> rust_key_paths::Kp<
4074 #name,
4075 #inner_ty,
4076 &'static #name,
4077 &'static #inner_ty,
4078 &'static mut #name,
4079 &'static mut #inner_ty,
4080 impl Fn(&#name) -> Option<&#inner_ty>,
4081 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
4082 > {
4083 rust_key_paths::Kp::new(
4084 rust_key_paths::constrain_get(|root: &#name| Some(root.#idx_lit.as_ref())),
4085 rust_key_paths::constrain_set(|root: &mut #name| Some(root.#idx_lit.to_mut())),
4086 )
4087 }
4088 });
4089 }
4090
4091 (WrapperKind::OptionCow, Some(inner_ty)) => {
4092 tokens.extend(quote! {
4093 #[inline(always)]
4094 pub fn #kp_fn() -> rust_key_paths::Kp<
4095 #name,
4096 #inner_ty,
4097 &'static #name,
4098 &'static #inner_ty,
4099 &'static mut #name,
4100 &'static mut #inner_ty,
4101 impl Fn(&#name) -> Option<&#inner_ty>,
4102 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
4103 > {
4104 rust_key_paths::Kp::new(
4105 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref().map(|c| c.as_ref())),
4106 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut().map(|c| c.to_mut())),
4107 )
4108 }
4109 });
4110 }
4111 (WrapperKind::OptionTagged, Some(inner_ty)) => {
4112 tokens.extend(quote! {
4113 #[inline(always)]
4114 pub fn #kp_fn() -> rust_key_paths::Kp<
4115 #name,
4116 #inner_ty,
4117 &'static #name,
4118 &'static #inner_ty,
4119 &'static mut #name,
4120 &'static mut #inner_ty,
4121 impl Fn(&#name) -> Option<&#inner_ty>,
4122 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
4123 > {
4124 rust_key_paths::Kp::new(
4125 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref().map(|t| std::ops::Deref::deref(t))),
4126 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut().map(|t| std::ops::DerefMut::deref_mut(t))),
4127 )
4128 }
4129 });
4130 }
4131 (WrapperKind::OptionReference, Some(inner_ty)) => {
4132 tokens.extend(quote! {
4133 #[inline(always)]
4134 pub fn #kp_fn() -> rust_key_paths::Kp<
4135 #name,
4136 #inner_ty,
4137 &'static #name,
4138 &'static #inner_ty,
4139 &'static mut #name,
4140 &'static mut #inner_ty,
4141 impl Fn(&#name) -> Option<&#inner_ty>,
4142 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
4143 > {
4144 rust_key_paths::Kp::new(
4145 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
4146 rust_key_paths::constrain_set(|_root: &mut #name| None),
4147 )
4148 }
4149 });
4150 }
4151 (WrapperKind::HashSet, Some(inner_ty))
4152 | (WrapperKind::HashSetOption, Some(inner_ty)) => {
4153 let kp_at_fn = format_ident!("f{}_at", idx);
4154
4155 tokens.extend(quote! {
4156 #[inline(always)]
4157 pub fn #kp_fn() -> rust_key_paths::Kp<
4158 #name,
4159 #ty,
4160 &'static #name,
4161 &'static #ty,
4162 &'static mut #name,
4163 &'static mut #ty,
4164 impl Fn(&#name) -> Option<&#ty>,
4165 impl Fn(&mut #name) -> Option<&mut #ty>,
4166 > {
4167 rust_key_paths::Kp::new(
4168 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4169 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4170 )
4171 }
4172
4173 /// _at: check if element exists and get reference.
4174 /// HashSet does not allow mutable element access (would break hash invariant).
4175 #[inline(always)]
4176 pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
4177 where
4178 #inner_ty: Clone + std::hash::Hash + Eq + 'static,
4179 {
4180 rust_key_paths::Kp::new(
4181 Box::new(move |root: &#name| root.#idx_lit.get(&key)),
4182 Box::new(move |_root: &mut #name| None),
4183 )
4184 }
4185 });
4186 }
4187 (WrapperKind::BTreeSet, Some(inner_ty))
4188 | (WrapperKind::BTreeSetOption, Some(inner_ty)) => {
4189 let kp_at_fn = format_ident!("f{}_at", idx);
4190
4191 tokens.extend(quote! {
4192 #[inline(always)]
4193 pub fn #kp_fn() -> rust_key_paths::Kp<
4194 #name,
4195 #ty,
4196 &'static #name,
4197 &'static #ty,
4198 &'static mut #name,
4199 &'static mut #ty,
4200 impl Fn(&#name) -> Option<&#ty>,
4201 impl Fn(&mut #name) -> Option<&mut #ty>,
4202 > {
4203 rust_key_paths::Kp::new(
4204 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4205 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4206 )
4207 }
4208
4209 /// _at: check if element exists and get reference.
4210 /// BTreeSet does not allow mutable element access (would break ordering invariant).
4211 #[inline(always)]
4212 pub fn #kp_at_fn(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
4213 where
4214 #inner_ty: Clone + Ord + 'static,
4215 {
4216 rust_key_paths::Kp::new(
4217 Box::new(move |root: &#name| root.#idx_lit.get(&key)),
4218 Box::new(move |_root: &mut #name| None),
4219 )
4220 }
4221 });
4222 }
4223 (WrapperKind::VecDeque, Some(inner_ty))
4224 | (WrapperKind::VecDequeOption, Some(inner_ty)) => {
4225 tokens.extend(quote! {
4226 #[inline(always)]
4227 pub fn #kp_fn() -> rust_key_paths::Kp<
4228 #name,
4229 #ty,
4230 &'static #name,
4231 &'static #ty,
4232 &'static mut #name,
4233 &'static mut #ty,
4234 impl Fn(&#name) -> Option<&#ty>,
4235 impl Fn(&mut #name) -> Option<&mut #ty>,
4236 > {
4237 rust_key_paths::Kp::new(
4238 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4239 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4240 )
4241 }
4242 #[inline(always)]
4243 pub fn #kp_at_fn(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
4244 rust_key_paths::Kp::new(
4245 Box::new(move |root: &#name| root.#idx_lit.get(index)),
4246 Box::new(move |root: &mut #name| root.#idx_lit.get_mut(index)),
4247 )
4248 }
4249 });
4250 }
4251 (WrapperKind::LinkedList, Some(_inner_ty))
4252 | (WrapperKind::LinkedListOption, Some(_inner_ty)) => {
4253 tokens.extend(quote! {
4254 #[inline(always)]
4255 pub fn #kp_fn() -> rust_key_paths::Kp<
4256 #name,
4257 #ty,
4258 &'static #name,
4259 &'static #ty,
4260 &'static mut #name,
4261 &'static mut #ty,
4262 impl Fn(&#name) -> Option<&#ty>,
4263 impl Fn(&mut #name) -> Option<&mut #ty>,
4264 > {
4265 rust_key_paths::Kp::new(
4266 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4267 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4268 )
4269 }
4270 });
4271 }
4272 (WrapperKind::BinaryHeap, Some(_inner_ty))
4273 | (WrapperKind::BinaryHeapOption, Some(_inner_ty)) => {
4274 tokens.extend(quote! {
4275 #[inline(always)]
4276 pub fn #kp_fn() -> rust_key_paths::Kp<
4277 #name,
4278 #ty,
4279 &'static #name,
4280 &'static #ty,
4281 &'static mut #name,
4282 &'static mut #ty,
4283 impl Fn(&#name) -> Option<&#ty>,
4284 impl Fn(&mut #name) -> Option<&mut #ty>,
4285 > {
4286 rust_key_paths::Kp::new(
4287 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4288 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4289 )
4290 }
4291 });
4292 }
4293 (WrapperKind::Result, Some(inner_ty)) => {
4294 tokens.extend(quote! {
4295 #[inline(always)]
4296 pub fn #kp_fn() -> rust_key_paths::Kp<
4297 #name,
4298 #inner_ty,
4299 &'static #name,
4300 &'static #inner_ty,
4301 &'static mut #name,
4302 &'static mut #inner_ty,
4303 impl Fn(&#name) -> Option<&#inner_ty>,
4304 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
4305 > {
4306 rust_key_paths::Kp::new(
4307 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref().ok()),
4308 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut().ok()),
4309 )
4310 }
4311 });
4312 }
4313 (WrapperKind::Mutex, Some(_inner_ty))
4314 | (WrapperKind::StdMutex, Some(_inner_ty)) => {
4315 tokens.extend(quote! {
4316 #[inline(always)]
4317 pub fn #kp_fn() -> rust_key_paths::Kp<
4318 #name,
4319 #ty,
4320 &'static #name,
4321 &'static #ty,
4322 &'static mut #name,
4323 &'static mut #ty,
4324 impl Fn(&#name) -> Option<&#ty>,
4325 impl Fn(&mut #name) -> Option<&mut #ty>,
4326 > {
4327 rust_key_paths::Kp::new(
4328 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4329 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4330 )
4331 }
4332 });
4333 }
4334 (WrapperKind::RwLock, Some(_inner_ty))
4335 | (WrapperKind::StdRwLock, Some(_inner_ty)) => {
4336 tokens.extend(quote! {
4337 #[inline(always)]
4338 pub fn #kp_fn() -> rust_key_paths::Kp<
4339 #name,
4340 #ty,
4341 &'static #name,
4342 &'static #ty,
4343 &'static mut #name,
4344 &'static mut #ty,
4345 impl Fn(&#name) -> Option<&#ty>,
4346 impl Fn(&mut #name) -> Option<&mut #ty>,
4347 > {
4348 rust_key_paths::Kp::new(
4349 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4350 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4351 )
4352 }
4353 });
4354 }
4355 (WrapperKind::TokioArcMutex, Some(inner_ty)) => {
4356 let kp_async_fn = format_ident!("f{}_kp", idx);
4357 tokens.extend(quote! {
4358 #[inline(always)]
4359 pub fn #kp_async_fn() -> rust_key_paths::Kp<
4360 #name,
4361 #ty,
4362 &'static #name,
4363 &'static #ty,
4364 &'static mut #name,
4365 &'static mut #ty,
4366 impl Fn(&#name) -> Option<&#ty>,
4367 impl Fn(&mut #name) -> Option<&mut #ty>,
4368 > {
4369 rust_key_paths::Kp::new(
4370 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4371 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4372 )
4373 }
4374 pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, #ty, #inner_ty> {
4375 rust_key_paths::async_lock::AsyncLockKp::new(
4376 rust_key_paths::Kp::new(
4377 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4378 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4379 ),
4380 rust_key_paths::async_lock::TokioMutexAccess::new(),
4381 rust_key_paths::Kp::new(
4382 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
4383 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
4384 ),
4385 )
4386 }
4387 });
4388 }
4389 (WrapperKind::TokioArcRwLock, Some(inner_ty)) => {
4390 let kp_async_fn = format_ident!("f{}_kp", idx);
4391 tokens.extend(quote! {
4392 #[inline(always)]
4393 pub fn #kp_async_fn() -> rust_key_paths::Kp<
4394 #name,
4395 #ty,
4396 &'static #name,
4397 &'static #ty,
4398 &'static mut #name,
4399 &'static mut #ty,
4400 impl Fn(&#name) -> Option<&#ty>,
4401 impl Fn(&mut #name) -> Option<&mut #ty>,
4402 > {
4403 rust_key_paths::Kp::new(
4404 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4405 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4406 )
4407 }
4408 pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, #ty, #inner_ty> {
4409 rust_key_paths::async_lock::AsyncLockKp::new(
4410 rust_key_paths::Kp::new(
4411 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4412 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4413 ),
4414 rust_key_paths::async_lock::TokioRwLockAccess::new(),
4415 rust_key_paths::Kp::new(
4416 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
4417 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
4418 ),
4419 )
4420 }
4421 });
4422 }
4423 (WrapperKind::OptionTokioArcMutex, Some(inner_ty)) => {
4424 let kp_async_fn = format_ident!("f{}_kp", idx);
4425 tokens.extend(quote! {
4426 #[inline(always)]
4427 pub fn #kp_async_fn() -> rust_key_paths::Kp<
4428 #name,
4429 #ty,
4430 &'static #name,
4431 &'static #ty,
4432 &'static mut #name,
4433 &'static mut #ty,
4434 impl Fn(&#name) -> Option<&#ty>,
4435 impl Fn(&mut #name) -> Option<&mut #ty>,
4436 > {
4437 rust_key_paths::Kp::new(
4438 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4439 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4440 )
4441 }
4442 pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, std::sync::Arc<tokio::sync::Mutex<#inner_ty>>, #inner_ty> {
4443 rust_key_paths::async_lock::AsyncLockKp::new(
4444 rust_key_paths::Kp::new(
4445 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
4446 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut()),
4447 ),
4448 rust_key_paths::async_lock::TokioMutexAccess::new(),
4449 rust_key_paths::Kp::new(
4450 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
4451 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
4452 ),
4453 )
4454 }
4455 });
4456 }
4457 (WrapperKind::OptionTokioArcRwLock, Some(inner_ty)) => {
4458 let kp_async_fn = format_ident!("f{}_kp", idx);
4459 tokens.extend(quote! {
4460 #[inline(always)]
4461 pub fn #kp_async_fn() -> rust_key_paths::Kp<
4462 #name,
4463 #ty,
4464 &'static #name,
4465 &'static #ty,
4466 &'static mut #name,
4467 &'static mut #ty,
4468 impl Fn(&#name) -> Option<&#ty>,
4469 impl Fn(&mut #name) -> Option<&mut #ty>,
4470 > {
4471 rust_key_paths::Kp::new(
4472 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4473 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4474 )
4475 }
4476 pub fn #kp_fn() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, std::sync::Arc<tokio::sync::RwLock<#inner_ty>>, #inner_ty> {
4477 rust_key_paths::async_lock::AsyncLockKp::new(
4478 rust_key_paths::Kp::new(
4479 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
4480 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut()),
4481 ),
4482 rust_key_paths::async_lock::TokioRwLockAccess::new(),
4483 rust_key_paths::Kp::new(
4484 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
4485 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
4486 ),
4487 )
4488 }
4489 });
4490 }
4491 (WrapperKind::OptionStdArcMutex, Some(inner_ty)) => {
4492 let lock_ty = quote! { std::sync::Arc<std::sync::Mutex<#inner_ty>> };
4493 let lock_kp_return_ty = kp_lock_ty_arc_mutex(name, &lock_ty, &inner_ty);
4494 tokens.extend(quote! {
4495 #[inline(always)]
4496 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
4497 rust_key_paths::sync_kp::SyncKp::new(
4498 rust_key_paths::Kp::new(
4499 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
4500 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut()),
4501 ),
4502 rust_key_paths::sync_kp::ArcMutexAccess::new(),
4503 rust_key_paths::Kp::new(
4504 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
4505 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
4506 ),
4507 )
4508 }
4509 });
4510 }
4511 (WrapperKind::OptionArcMutex, Some(inner_ty)) => {
4512 let lock_ty = quote! { std::sync::Arc<parking_lot::Mutex<#inner_ty>> };
4513 let lock_kp_return_ty =
4514 kp_lock_ty_parking_lot_mutex(name, &lock_ty, &inner_ty);
4515 tokens.extend(quote! {
4516 #[inline(always)]
4517 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
4518 rust_key_paths::sync_kp::SyncKp::new(
4519 rust_key_paths::Kp::new(
4520 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
4521 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut()),
4522 ),
4523 rust_key_paths::sync_kp::ParkingLotMutexAccess::new(),
4524 rust_key_paths::Kp::new(
4525 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
4526 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
4527 ),
4528 )
4529 }
4530 });
4531 }
4532 (WrapperKind::OptionStdArcRwLock, Some(inner_ty)) => {
4533 let lock_ty = quote! { std::sync::Arc<std::sync::RwLock<#inner_ty>> };
4534 let lock_kp_return_ty =
4535 kp_lock_ty_arc_rw_lock(name, &lock_ty, &inner_ty);
4536 tokens.extend(quote! {
4537 #[inline(always)]
4538 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
4539 rust_key_paths::sync_kp::SyncKp::new(
4540 rust_key_paths::Kp::new(
4541 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
4542 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut()),
4543 ),
4544 rust_key_paths::sync_kp::ArcRwLockAccess::new(),
4545 rust_key_paths::Kp::new(
4546 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
4547 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
4548 ),
4549 )
4550 }
4551 });
4552 }
4553 (WrapperKind::OptionArcRwLock, Some(inner_ty)) => {
4554 let lock_ty = quote! { std::sync::Arc<parking_lot::RwLock<#inner_ty>> };
4555 let lock_kp_return_ty =
4556 kp_lock_ty_parking_lot_rw_lock(name, &lock_ty, &inner_ty);
4557 tokens.extend(quote! {
4558 #[inline(always)]
4559 pub fn #kp_fn<'b>() -> #lock_kp_return_ty {
4560 rust_key_paths::sync_kp::SyncKp::new(
4561 rust_key_paths::Kp::new(
4562 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
4563 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut()),
4564 ),
4565 rust_key_paths::sync_kp::ParkingLotRwLockAccess::new(),
4566 rust_key_paths::Kp::new(
4567 rust_key_paths::constrain_get(|v: &#inner_ty| Some(v)),
4568 rust_key_paths::constrain_set(|v: &mut #inner_ty| Some(v)),
4569 ),
4570 )
4571 }
4572 });
4573 }
4574 (WrapperKind::OptionStdMutex, Some(inner_ty)) => {
4575 let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
4576 tokens.extend(quote! {
4577 #[inline(always)]
4578 pub fn #kp_fn() -> rust_key_paths::Kp<
4579 #name,
4580 #ty,
4581 &'static #name,
4582 &'static #ty,
4583 &'static mut #name,
4584 &'static mut #ty,
4585 impl Fn(&#name) -> Option<&#ty>,
4586 impl Fn(&mut #name) -> Option<&mut #ty>,
4587 > {
4588 rust_key_paths::Kp::new(
4589 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4590 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4591 )
4592 }
4593 pub fn #kp_unlocked_fn() -> rust_key_paths::Kp<
4594 #name,
4595 std::sync::Mutex<#inner_ty>,
4596 &'static #name,
4597 &'static std::sync::Mutex<#inner_ty>,
4598 &'static mut #name,
4599 &'static mut std::sync::Mutex<#inner_ty>,
4600 impl Fn(&#name) -> Option<&std::sync::Mutex<#inner_ty>>,
4601 impl Fn(&mut #name) -> Option<&mut std::sync::Mutex<#inner_ty>>,
4602> {
4603 rust_key_paths::Kp::new(
4604 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
4605 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut()),
4606 )
4607 }
4608 });
4609 }
4610 (WrapperKind::OptionMutex, Some(inner_ty)) => {
4611 let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
4612 tokens.extend(quote! {
4613 #[inline(always)]
4614 pub fn #kp_fn() -> rust_key_paths::Kp<
4615 #name,
4616 #ty,
4617 &'static #name,
4618 &'static #ty,
4619 &'static mut #name,
4620 &'static mut #ty,
4621 impl Fn(&#name) -> Option<&#ty>,
4622 impl Fn(&mut #name) -> Option<&mut #ty>,
4623 > {
4624 rust_key_paths::Kp::new(
4625 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4626 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4627 )
4628 }
4629 pub fn #kp_unlocked_fn() -> rust_key_paths::Kp<
4630 #name,
4631 parking_lot::Mutex<#inner_ty>,
4632 &'static #name,
4633 &'static parking_lot::Mutex<#inner_ty>,
4634 &'static mut #name,
4635 &'static mut parking_lot::Mutex<#inner_ty>,
4636 impl Fn(&#name) -> Option<&parking_lot::Mutex<#inner_ty>>,
4637 impl Fn(&mut #name) -> Option<&mut parking_lot::Mutex<#inner_ty>>,
4638> {
4639 rust_key_paths::Kp::new(
4640 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
4641 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut()),
4642 )
4643 }
4644 });
4645 }
4646 (WrapperKind::OptionStdRwLock, Some(inner_ty)) => {
4647 let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
4648 tokens.extend(quote! {
4649 #[inline(always)]
4650 pub fn #kp_fn() -> rust_key_paths::Kp<
4651 #name,
4652 #ty,
4653 &'static #name,
4654 &'static #ty,
4655 &'static mut #name,
4656 &'static mut #ty,
4657 impl Fn(&#name) -> Option<&#ty>,
4658 impl Fn(&mut #name) -> Option<&mut #ty>,
4659 > {
4660 rust_key_paths::Kp::new(
4661 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4662 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4663 )
4664 }
4665 pub fn #kp_unlocked_fn() -> rust_key_paths::Kp<
4666 #name,
4667 std::sync::RwLock<#inner_ty>,
4668 &'static #name,
4669 &'static std::sync::RwLock<#inner_ty>,
4670 &'static mut #name,
4671 &'static mut std::sync::RwLock<#inner_ty>,
4672 impl Fn(&#name) -> Option<&std::sync::RwLock<#inner_ty>>,
4673 impl Fn(&mut #name) -> Option<&mut std::sync::RwLock<#inner_ty>>,
4674> {
4675 rust_key_paths::Kp::new(
4676 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
4677 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut()),
4678 )
4679 }
4680 });
4681 }
4682 (WrapperKind::OptionRwLock, Some(inner_ty)) => {
4683 let kp_unlocked_fn = format_ident!("f{}_unlocked", idx);
4684 tokens.extend(quote! {
4685 #[inline(always)]
4686 pub fn #kp_fn() -> rust_key_paths::Kp<
4687 #name,
4688 #ty,
4689 &'static #name,
4690 &'static #ty,
4691 &'static mut #name,
4692 &'static mut #ty,
4693 impl Fn(&#name) -> Option<&#ty>,
4694 impl Fn(&mut #name) -> Option<&mut #ty>,
4695 > {
4696 rust_key_paths::Kp::new(
4697 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4698 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4699 )
4700 }
4701 pub fn #kp_unlocked_fn() -> rust_key_paths::Kp<
4702 #name,
4703 parking_lot::RwLock<#inner_ty>,
4704 &'static #name,
4705 &'static parking_lot::RwLock<#inner_ty>,
4706 &'static mut #name,
4707 &'static mut parking_lot::RwLock<#inner_ty>,
4708 impl Fn(&#name) -> Option<&parking_lot::RwLock<#inner_ty>>,
4709 impl Fn(&mut #name) -> Option<&mut parking_lot::RwLock<#inner_ty>>,
4710> {
4711 rust_key_paths::Kp::new(
4712 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
4713 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut()),
4714 )
4715 }
4716 });
4717 }
4718 (WrapperKind::Weak, Some(_inner_ty)) => {
4719 tokens.extend(quote! {
4720 #[inline(always)]
4721 pub fn #kp_fn() -> rust_key_paths::Kp<
4722 #name,
4723 #ty,
4724 &'static #name,
4725 &'static #ty,
4726 &'static mut #name,
4727 &'static mut #ty,
4728 impl Fn(&#name) -> Option<&#ty>,
4729 impl Fn(&mut #name) -> Option<&mut #ty>,
4730 > {
4731 rust_key_paths::Kp::new(
4732 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4733 rust_key_paths::constrain_set(|_root: &mut #name| None),
4734 )
4735 }
4736 });
4737 }
4738 (WrapperKind::Atomic, None | Some(_)) => {
4739 tokens.extend(quote! {
4740 #[inline(always)]
4741 pub fn #kp_fn() -> rust_key_paths::Kp<
4742 #name,
4743 #ty,
4744 &'static #name,
4745 &'static #ty,
4746 &'static mut #name,
4747 &'static mut #ty,
4748 impl Fn(&#name) -> Option<&#ty>,
4749 impl Fn(&mut #name) -> Option<&mut #ty>,
4750 > {
4751 rust_key_paths::Kp::new(
4752 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4753 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4754 )
4755 }
4756 });
4757 }
4758 (WrapperKind::OptionAtomic, Some(inner_ty)) => {
4759 tokens.extend(quote! {
4760 #[inline(always)]
4761 pub fn #kp_fn() -> rust_key_paths::Kp<
4762 #name,
4763 #inner_ty,
4764 &'static #name,
4765 &'static #inner_ty,
4766 &'static mut #name,
4767 &'static mut #inner_ty,
4768 impl Fn(&#name) -> Option<&#inner_ty>,
4769 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
4770 > {
4771 rust_key_paths::Kp::new(
4772 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
4773 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut()),
4774 )
4775 }
4776 });
4777 }
4778 (WrapperKind::String, None) => {
4779 tokens.extend(quote! {
4780 #[inline(always)]
4781 pub fn #kp_fn() -> rust_key_paths::Kp<
4782 #name,
4783 #ty,
4784 &'static #name,
4785 &'static #ty,
4786 &'static mut #name,
4787 &'static mut #ty,
4788 impl Fn(&#name) -> Option<&#ty>,
4789 impl Fn(&mut #name) -> Option<&mut #ty>,
4790 > {
4791 rust_key_paths::Kp::new(
4792 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4793 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4794 )
4795 }
4796 });
4797 }
4798 (WrapperKind::OptionString, None) => {
4799 tokens.extend(quote! {
4800 #[inline(always)]
4801 pub fn #kp_fn() -> rust_key_paths::Kp<#name, std::string::String, &'static #name, &'static std::string::String, &'static mut #name, &'static mut std::string::String, impl Fn(&#name) -> Option<&std::string::String>, impl Fn(&mut #name) -> Option<&mut std::string::String>,> {
4802 rust_key_paths::Kp::new(
4803 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref()),
4804 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_mut()),
4805 )
4806 }
4807 });
4808 }
4809 (WrapperKind::OnceCell, Some(inner_ty)) => {
4810 tokens.extend(quote! {
4811 #[inline(always)]
4812 pub fn #kp_fn() -> rust_key_paths::Kp<
4813 #name,
4814 #inner_ty,
4815 &'static #name,
4816 &'static #inner_ty,
4817 &'static mut #name,
4818 &'static mut #inner_ty,
4819 impl Fn(&#name) -> Option<&#inner_ty>,
4820 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
4821 > {
4822 rust_key_paths::Kp::new(
4823 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.get()),
4824 rust_key_paths::constrain_set(|_root: &mut #name| None),
4825 )
4826 }
4827 });
4828 }
4829 (WrapperKind::Lazy, Some(inner_ty)) => {
4830 tokens.extend(quote! {
4831 #[inline(always)]
4832 pub fn #kp_fn() -> rust_key_paths::Kp<
4833 #name,
4834 #inner_ty,
4835 &'static #name,
4836 &'static #inner_ty,
4837 &'static mut #name,
4838 &'static mut #inner_ty,
4839 impl Fn(&#name) -> Option<&#inner_ty>,
4840 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
4841 > {
4842 rust_key_paths::Kp::new(
4843 rust_key_paths::constrain_get(|root: &#name| Some(root.#idx_lit.get())),
4844 rust_key_paths::constrain_set(|_root: &mut #name| None),
4845 )
4846 }
4847 });
4848 }
4849 (WrapperKind::OptionOnceCell, Some(inner_ty)) => {
4850 tokens.extend(quote! {
4851 #[inline(always)]
4852 pub fn #kp_fn() -> rust_key_paths::Kp<
4853 #name,
4854 #inner_ty,
4855 &'static #name,
4856 &'static #inner_ty,
4857 &'static mut #name,
4858 &'static mut #inner_ty,
4859 impl Fn(&#name) -> Option<&#inner_ty>,
4860 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
4861 > {
4862 rust_key_paths::Kp::new(
4863 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref().and_then(|c| c.get())),
4864 rust_key_paths::constrain_set(|_root: &mut #name| None),
4865 )
4866 }
4867 });
4868 }
4869 (WrapperKind::OptionLazy, Some(inner_ty)) => {
4870 tokens.extend(quote! {
4871 #[inline(always)]
4872 pub fn #kp_fn() -> rust_key_paths::Kp<
4873 #name,
4874 #inner_ty,
4875 &'static #name,
4876 &'static #inner_ty,
4877 &'static mut #name,
4878 &'static mut #inner_ty,
4879 impl Fn(&#name) -> Option<&#inner_ty>,
4880 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
4881 > {
4882 rust_key_paths::Kp::new(
4883 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref().map(|c| c.get())),
4884 rust_key_paths::constrain_set(|_root: &mut #name| None),
4885 )
4886 }
4887 });
4888 }
4889 (WrapperKind::Cell, Some(_inner_ty))
4890 | (WrapperKind::RefCell, Some(_inner_ty))
4891 | (WrapperKind::PhantomData, Some(_inner_ty))
4892 | (WrapperKind::Range, Some(_inner_ty))
4893 | (WrapperKind::OptionCell, Some(_inner_ty))
4894 | (WrapperKind::OptionPhantomData, Some(_inner_ty))
4895 | (WrapperKind::OptionRange, Some(_inner_ty)) => {
4896 tokens.extend(quote! {
4897 #[inline(always)]
4898 pub fn #kp_fn() -> rust_key_paths::Kp<
4899 #name,
4900 #ty,
4901 &'static #name,
4902 &'static #ty,
4903 &'static mut #name,
4904 &'static mut #ty,
4905 impl Fn(&#name) -> Option<&#ty>,
4906 impl Fn(&mut #name) -> Option<&mut #ty>,
4907 > {
4908 rust_key_paths::Kp::new(
4909 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4910 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4911 )
4912 }
4913 });
4914 }
4915 (WrapperKind::OptionRefCell, Some(inner_ty)) => {
4916 tokens.extend(quote! {
4917 #[inline(always)]
4918 pub fn #kp_fn() -> rust_key_paths::KpOptionRefCellType<'_, #name, #inner_ty> {
4919 rust_key_paths::Kp::new(
4920 rust_key_paths::constrain_get(|root: &#name| root.#idx_lit.as_ref().map(|r| r.borrow())),
4921 rust_key_paths::constrain_set(|root: &mut #name| root.#idx_lit.as_ref().map(|r| r.borrow_mut())),
4922 )
4923 }
4924 });
4925 }
4926 (WrapperKind::Reference, Some(_inner_ty)) => {
4927 tokens.extend(quote! {
4928 #[inline(always)]
4929 pub fn #kp_fn() -> rust_key_paths::Kp<
4930 #name,
4931 #ty,
4932 &'static #name,
4933 &'static #ty,
4934 &'static mut #name,
4935 &'static mut #ty,
4936 impl Fn(&#name) -> Option<&#ty>,
4937 impl Fn(&mut #name) -> Option<&mut #ty>,
4938 > {
4939 rust_key_paths::Kp::new(
4940 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4941 rust_key_paths::constrain_set(|_root: &mut #name| None),
4942 )
4943 }
4944 });
4945 }
4946 (WrapperKind::None, None) => {
4947 tokens.extend(quote! {
4948 #[inline(always)]
4949 pub fn #kp_fn() -> rust_key_paths::Kp<
4950 #name,
4951 #ty,
4952 &'static #name,
4953 &'static #ty,
4954 &'static mut #name,
4955 &'static mut #ty,
4956 impl Fn(&#name) -> Option<&#ty>,
4957 impl Fn(&mut #name) -> Option<&mut #ty>,
4958 > {
4959 rust_key_paths::Kp::new(
4960 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4961 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4962 )
4963 }
4964 });
4965 }
4966 _ => {
4967 tokens.extend(quote! {
4968 #[inline(always)]
4969 pub fn #kp_fn() -> rust_key_paths::Kp<
4970 #name,
4971 #ty,
4972 &'static #name,
4973 &'static #ty,
4974 &'static mut #name,
4975 &'static mut #ty,
4976 impl Fn(&#name) -> Option<&#ty>,
4977 impl Fn(&mut #name) -> Option<&mut #ty>,
4978 > {
4979 rust_key_paths::Kp::new(
4980 rust_key_paths::constrain_get(|root: &#name| Some(&root.#idx_lit)),
4981 rust_key_paths::constrain_set(|root: &mut #name| Some(&mut root.#idx_lit)),
4982 )
4983 }
4984 });
4985 }
4986 }
4987 }
4988
4989 tokens
4990 }
4991 Fields::Unit => {
4992 return syn::Error::new(input_span, "Kp derive does not support unit structs")
4993 .to_compile_error()
4994 .into();
4995 }
4996 },
4997 Data::Enum(data_enum) => {
4998 let mut tokens = proc_macro2::TokenStream::new();
4999
5000 // Generate identity methods for the enum
5001 tokens.extend(quote! {
5002 /// Returns a generic identity keypath for this type
5003 #[inline(always)]
5004 pub fn identity_typed<'a, Root, MutRoot>() -> rust_key_paths::Kp<
5005 #name,
5006 #name,
5007 Root,
5008 Root,
5009 MutRoot,
5010 MutRoot,
5011 fn(Root) -> Option<Root>,
5012 fn(MutRoot) -> Option<MutRoot>,
5013 >
5014 where
5015 Root: std::borrow::Borrow<#name>,
5016 MutRoot: std::borrow::BorrowMut<#name>,
5017 {
5018 rust_key_paths::Kp::new(
5019 |r: Root| Some(r),
5020 |r: MutRoot| Some(r)
5021 )
5022 }
5023
5024 /// Returns a simple identity keypath for this type
5025 #[inline(always)]
5026 pub fn identity() -> rust_key_paths::Kp<#name, #name, &'static #name, &'static #name, &'static mut #name, &'static mut #name, impl Fn(&#name) -> Option<&#name>, impl Fn(&mut #name) -> Option<&mut #name>,> {
5027 rust_key_paths::Kp::new(
5028 rust_key_paths::constrain_get(|r: &#name| Some(r)),
5029 rust_key_paths::constrain_set(|r: &mut #name| Some(r)
5030 ))
5031 }
5032 });
5033
5034 for variant in data_enum.variants.iter() {
5035 let v_ident = &variant.ident;
5036 let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
5037
5038 match &variant.fields {
5039 Fields::Unit => {
5040 // Unit variant - return keypath that checks if enum matches variant
5041 tokens.extend(quote! {
5042 #[inline(always)]
5043 pub fn #snake() -> rust_key_paths::Kp<#name, (), &'static #name, &'static (), &'static mut #name, &'static mut (), impl Fn(&#name) -> Option<&()>, impl Fn(&mut #name) -> Option<&mut ()>,> {
5044 rust_key_paths::Kp::new(
5045 rust_key_paths::constrain_get(|root: &#name| match root {
5046 #name::#v_ident => {
5047 static UNIT: () = ();
5048 Some(&UNIT)
5049 },
5050 _ => None,
5051 }),
5052 rust_key_paths::constrain_set(|_root: &mut #name| None), // Can't mutate unit variant
5053 )
5054 }
5055 });
5056 }
5057 Fields::Unnamed(unnamed) => {
5058 if unnamed.unnamed.len() == 1 {
5059 // Single-field tuple variant
5060 let field_ty = &unnamed.unnamed[0].ty;
5061 let (kind, inner_ty) = extract_wrapper_inner_type(field_ty);
5062
5063 match (kind, inner_ty.clone()) {
5064 (WrapperKind::Option, Some(inner_ty)) => {
5065 tokens.extend(quote! {
5066 #[inline(always)]
5067 pub fn #snake() -> rust_key_paths::Kp<
5068 #name,
5069 #inner_ty,
5070 &'static #name,
5071 &'static #inner_ty,
5072 &'static mut #name,
5073 &'static mut #inner_ty,
5074 impl Fn(&#name) -> Option<&#inner_ty>,
5075 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
5076 > {
5077 rust_key_paths::Kp::new(
5078 rust_key_paths::constrain_get(|root: &#name| match root {
5079 #name::#v_ident(inner) => inner.as_ref(),
5080 _ => None,
5081 }),
5082 rust_key_paths::constrain_set(|root: &mut #name| match root {
5083 #name::#v_ident(inner) => inner.as_mut(),
5084 _ => None,
5085 }),
5086 )
5087 }
5088 });
5089 }
5090 (WrapperKind::OptionHashMap, Some(inner_ty)) => {
5091 let snake_at = format_ident!("{}_at", snake);
5092 if let Some((key_ty, _)) =
5093 extract_map_key_value_through_option(field_ty)
5094 {
5095 tokens.extend(quote! {
5096 #[inline(always)]
5097 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5098 rust_key_paths::Kp::new(
5099 rust_key_paths::constrain_get(|root: &#name| match root {
5100 #name::#v_ident(inner) => Some(inner),
5101 _ => None,
5102 }),
5103 rust_key_paths::constrain_set(|root: &mut #name| match root {
5104 #name::#v_ident(inner) => Some(inner),
5105 _ => None,
5106 }),
5107 )
5108 }
5109 #[inline(always)]
5110 pub fn #snake_at(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
5111 where
5112 #key_ty: Clone + std::hash::Hash + Eq + 'static,
5113 {
5114 let key2 = key.clone();
5115 rust_key_paths::Kp::new(
5116 Box::new(move |root: &#name| match root {
5117 #name::#v_ident(inner) => inner.as_ref().and_then(|m| m.get(&key)),
5118 _ => None,
5119 }),
5120 Box::new(move |root: &mut #name| match root {
5121 #name::#v_ident(inner) => inner.as_mut().and_then(|m| m.get_mut(&key2)),
5122 _ => None,
5123 }),
5124 )
5125 }
5126 });
5127 } else {
5128 tokens.extend(quote! {
5129 #[inline(always)]
5130 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5131 rust_key_paths::Kp::new(
5132 rust_key_paths::constrain_get(|root: &#name| match root {
5133 #name::#v_ident(inner) => Some(inner),
5134 _ => None,
5135 }),
5136 rust_key_paths::constrain_set(|root: &mut #name| match root {
5137 #name::#v_ident(inner) => Some(inner),
5138 _ => None,
5139 }),
5140 )
5141 }
5142 });
5143 }
5144 }
5145 (WrapperKind::OptionBTreeMap, Some(inner_ty)) => {
5146 let snake_at = format_ident!("{}_at", snake);
5147 if let Some((key_ty, _)) =
5148 extract_map_key_value_through_option(field_ty)
5149 {
5150 tokens.extend(quote! {
5151 #[inline(always)]
5152 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5153 rust_key_paths::Kp::new(
5154 rust_key_paths::constrain_get(|root: &#name| match root {
5155 #name::#v_ident(inner) => Some(inner),
5156 _ => None,
5157 }),
5158 rust_key_paths::constrain_set(|root: &mut #name| match root {
5159 #name::#v_ident(inner) => Some(inner),
5160 _ => None,
5161 }),
5162 )
5163 }
5164 #[inline(always)]
5165 pub fn #snake_at(key: #key_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
5166 where
5167 #key_ty: Clone + Ord + 'static,
5168 {
5169 let key2 = key.clone();
5170 rust_key_paths::Kp::new(
5171 Box::new(move |root: &#name| match root {
5172 #name::#v_ident(inner) => inner.as_ref().and_then(|m| m.get(&key)),
5173 _ => None,
5174 }),
5175 Box::new(move |root: &mut #name| match root {
5176 #name::#v_ident(inner) => inner.as_mut().and_then(|m| m.get_mut(&key2)),
5177 _ => None,
5178 }),
5179 )
5180 }
5181 });
5182 } else {
5183 tokens.extend(quote! {
5184 #[inline(always)]
5185 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5186 rust_key_paths::Kp::new(
5187 rust_key_paths::constrain_get(|root: &#name| match root {
5188 #name::#v_ident(inner) => Some(inner),
5189 _ => None,
5190 }),
5191 rust_key_paths::constrain_set(|root: &mut #name| match root {
5192 #name::#v_ident(inner) => Some(inner),
5193 _ => None,
5194 }),
5195 )
5196 }
5197 });
5198 }
5199 }
5200 (WrapperKind::OptionHashSet, Some(inner_ty)) => {
5201 let snake_at = format_ident!("{}_at", snake);
5202 tokens.extend(quote! {
5203 #[inline(always)]
5204 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5205 rust_key_paths::Kp::new(
5206 rust_key_paths::constrain_get(|root: &#name| match root {
5207 #name::#v_ident(inner) => Some(inner),
5208 _ => None,
5209 }),
5210 rust_key_paths::constrain_set(|root: &mut #name| match root {
5211 #name::#v_ident(inner) => Some(inner),
5212 _ => None,
5213 }),
5214 )
5215 }
5216
5217 /// _at: check if element exists and get reference.
5218 /// HashSet does not allow mutable element access (would break hash invariant).
5219 #[inline(always)]
5220 pub fn #snake_at(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
5221 where
5222 #inner_ty: Clone + std::hash::Hash + Eq + 'static,
5223 {
5224 rust_key_paths::Kp::new(
5225 Box::new(move |root: &#name| match root {
5226 #name::#v_ident(inner) => inner.as_ref().and_then(|s| s.get(&key)),
5227 _ => None,
5228 }),
5229 Box::new(move |_root: &mut #name| None),
5230 )
5231 }
5232 });
5233 }
5234 (WrapperKind::OptionBTreeSet, Some(inner_ty)) => {
5235 let snake_at = format_ident!("{}_at", snake);
5236 tokens.extend(quote! {
5237 #[inline(always)]
5238 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5239 rust_key_paths::Kp::new(
5240 rust_key_paths::constrain_get(|root: &#name| match root {
5241 #name::#v_ident(inner) => Some(inner),
5242 _ => None,
5243 }),
5244 rust_key_paths::constrain_set(|root: &mut #name| match root {
5245 #name::#v_ident(inner) => Some(inner),
5246 _ => None,
5247 }),
5248 )
5249 }
5250
5251 /// _at: check if element exists and get reference.
5252 /// BTreeSet does not allow mutable element access (would break ordering invariant).
5253 #[inline(always)]
5254 pub fn #snake_at(key: #inner_ty) -> rust_key_paths::KpDynamic<#name, #inner_ty>
5255 where
5256 #inner_ty: Clone + Ord + 'static,
5257 {
5258 rust_key_paths::Kp::new(
5259 Box::new(move |root: &#name| match root {
5260 #name::#v_ident(inner) => inner.as_ref().and_then(|s| s.get(&key)),
5261 _ => None,
5262 }),
5263 Box::new(move |_root: &mut #name| None),
5264 )
5265 }
5266 });
5267 }
5268 (WrapperKind::OptionVec, Some(inner_ty)) => {
5269 let snake_at = format_ident!("{}_at", snake);
5270 tokens.extend(quote! {
5271 #[inline(always)]
5272 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5273 rust_key_paths::Kp::new(
5274 rust_key_paths::constrain_get(|root: &#name| match root {
5275 #name::#v_ident(inner) => Some(inner),
5276 _ => None,
5277 }),
5278 rust_key_paths::constrain_set(|root: &mut #name| match root {
5279 #name::#v_ident(inner) => Some(inner),
5280 _ => None,
5281 }),
5282 )
5283 }
5284 #[inline(always)]
5285 pub fn #snake_at(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
5286 rust_key_paths::Kp::new(
5287 Box::new(move |root: &#name| match root {
5288 #name::#v_ident(inner) => inner.as_ref().and_then(|v| v.get(index)),
5289 _ => None,
5290 }),
5291 Box::new(move |root: &mut #name| match root {
5292 #name::#v_ident(inner) => inner.as_mut().and_then(|v| v.get_mut(index)),
5293 _ => None,
5294 }),
5295 )
5296 }
5297 });
5298 }
5299 (WrapperKind::OptionVecDeque, Some(inner_ty)) => {
5300 let snake_at = format_ident!("{}_at", snake);
5301 tokens.extend(quote! {
5302 #[inline(always)]
5303 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5304 rust_key_paths::Kp::new(
5305 rust_key_paths::constrain_get(|root: &#name| match root {
5306 #name::#v_ident(inner) => Some(inner),
5307 _ => None,
5308 }),
5309 rust_key_paths::constrain_set(|root: &mut #name| match root {
5310 #name::#v_ident(inner) => Some(inner),
5311 _ => None,
5312 }),
5313 )
5314 }
5315 #[inline(always)]
5316 pub fn #snake_at(index: usize) -> rust_key_paths::KpDynamic<#name, #inner_ty> {
5317 rust_key_paths::Kp::new(
5318 Box::new(move |root: &#name| match root {
5319 #name::#v_ident(inner) => inner.as_ref().and_then(|v| v.get(index)),
5320 _ => None,
5321 }),
5322 Box::new(move |root: &mut #name| match root {
5323 #name::#v_ident(inner) => inner.as_mut().and_then(|v| v.get_mut(index)),
5324 _ => None,
5325 }),
5326 )
5327 }
5328 });
5329 }
5330 (WrapperKind::OptionLinkedList, Some(_inner_ty))
5331 | (WrapperKind::OptionBinaryHeap, Some(_inner_ty))
5332 | (WrapperKind::OptionResult, Some(_inner_ty)) => {
5333 tokens.extend(quote! {
5334 #[inline(always)]
5335 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5336 rust_key_paths::Kp::new(
5337 rust_key_paths::constrain_get(|root: &#name| match root {
5338 #name::#v_ident(inner) => Some(inner),
5339 _ => None,
5340 }),
5341 rust_key_paths::constrain_set(|root: &mut #name| match root {
5342 #name::#v_ident(inner) => Some(inner),
5343 _ => None,
5344 }),
5345 )
5346 }
5347 });
5348 }
5349 (WrapperKind::Vec, Some(inner_ty)) => {
5350 tokens.extend(quote! {
5351 #[inline(always)]
5352 pub fn #snake() -> rust_key_paths::Kp<
5353 #name,
5354 #inner_ty,
5355 &'static #name,
5356 &'static #inner_ty,
5357 &'static mut #name,
5358 &'static mut #inner_ty,
5359 impl Fn(&#name) -> Option<&#inner_ty>,
5360 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
5361 > {
5362 rust_key_paths::Kp::new(
5363 rust_key_paths::constrain_get(|root: &#name| match root {
5364 #name::#v_ident(inner) => inner.first(),
5365 _ => None,
5366 }),
5367 rust_key_paths::constrain_set(|root: &mut #name| match root {
5368 #name::#v_ident(inner) => inner.first_mut(),
5369 _ => None,
5370 }),
5371 )
5372 }
5373 });
5374 }
5375 (WrapperKind::Box, Some(inner_ty)) => {
5376 // Box in enum: deref to inner (&T / &mut T)
5377 tokens.extend(quote! {
5378 #[inline(always)]
5379 pub fn #snake() -> rust_key_paths::Kp<
5380 #name,
5381 #inner_ty,
5382 &'static #name,
5383 &'static #inner_ty,
5384 &'static mut #name,
5385 &'static mut #inner_ty,
5386 impl Fn(&#name) -> Option<&#inner_ty>,
5387 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
5388 > {
5389 rust_key_paths::Kp::new(
5390 rust_key_paths::constrain_get(|root: &#name| match root {
5391 #name::#v_ident(inner) => Some(&**inner),
5392 _ => None,
5393 }),
5394 rust_key_paths::constrain_set(|root: &mut #name| match root {
5395 #name::#v_ident(inner) => Some(&mut **inner),
5396 _ => None,
5397 }),
5398 )
5399 }
5400 });
5401 }
5402 (WrapperKind::Pin, Some(inner_ty)) => {
5403 let snake_inner = format_ident!("{}_inner", snake);
5404 tokens.extend(quote! {
5405 #[inline(always)]
5406 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5407 rust_key_paths::Kp::new(
5408 rust_key_paths::constrain_get(|root: &#name| match root {
5409 #name::#v_ident(inner) => Some(inner),
5410 _ => None,
5411 }),
5412 rust_key_paths::constrain_set(|root: &mut #name| match root {
5413 #name::#v_ident(inner) => Some(inner),
5414 _ => None,
5415 }),
5416 )
5417 }
5418 #[inline(always)]
5419 pub fn #snake_inner() -> rust_key_paths::Kp<
5420 #name,
5421 #inner_ty,
5422 &'static #name,
5423 &'static #inner_ty,
5424 &'static mut #name,
5425 &'static mut #inner_ty,
5426 impl Fn(&#name) -> Option<&#inner_ty>,
5427 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
5428>
5429>
5430 where #inner_ty: std::marker::Unpin
5431 {
5432 rust_key_paths::Kp::new(
5433 rust_key_paths::constrain_get(|root: &#name| match root {
5434 #name::#v_ident(inner) => Some(std::pin::Pin::as_ref(inner).get_ref()),
5435 _ => None,
5436 }),
5437 rust_key_paths::constrain_set(|root: &mut #name| match root {
5438 #name::#v_ident(inner) => Some(std::pin::Pin::as_mut(inner).get_mut()),
5439 _ => None,
5440 }),
5441 )
5442 }
5443 });
5444 }
5445 (WrapperKind::PinBox, Some(inner_ty)) => {
5446 let snake_inner = format_ident!("{}_inner", snake);
5447 tokens.extend(quote! {
5448 #[inline(always)]
5449 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5450 rust_key_paths::Kp::new(
5451 rust_key_paths::constrain_get(|root: &#name| match root {
5452 #name::#v_ident(inner) => Some(inner),
5453 _ => None,
5454 }),
5455 rust_key_paths::constrain_set(|root: &mut #name| match root {
5456 #name::#v_ident(inner) => Some(inner),
5457 _ => None,
5458 }),
5459 )
5460 }
5461 #[inline(always)]
5462 pub fn #snake_inner() -> rust_key_paths::Kp<
5463 #name,
5464 #inner_ty,
5465 &'static #name,
5466 &'static #inner_ty,
5467 &'static mut #name,
5468 &'static mut #inner_ty,
5469 impl Fn(&#name) -> Option<&#inner_ty>,
5470 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
5471>
5472>
5473 where #inner_ty: std::marker::Unpin
5474 {
5475 rust_key_paths::Kp::new(
5476 rust_key_paths::constrain_get(|root: &#name| match root {
5477 #name::#v_ident(inner) => Some(std::pin::Pin::as_ref(inner).get_ref()),
5478 _ => None,
5479 }),
5480 rust_key_paths::constrain_set(|root: &mut #name| match root {
5481 #name::#v_ident(inner) => Some(std::pin::Pin::as_mut(inner).get_mut()),
5482 _ => None,
5483 }),
5484 )
5485 }
5486 });
5487 }
5488 (WrapperKind::Rc, Some(inner_ty)) => {
5489 tokens.extend(quote! {
5490 #[inline(always)]
5491 pub fn #snake() -> rust_key_paths::Kp<
5492 #name,
5493 #inner_ty,
5494 &'static #name,
5495 &'static #inner_ty,
5496 &'static mut #name,
5497 &'static mut #inner_ty,
5498 impl Fn(&#name) -> Option<&#inner_ty>,
5499 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
5500 > {
5501 rust_key_paths::Kp::new(
5502 rust_key_paths::constrain_get(|root: &#name| match root {
5503 #name::#v_ident(inner) => Some(inner.as_ref()),
5504 _ => None,
5505 }),
5506 rust_key_paths::constrain_set(|root: &mut #name| match root {
5507 #name::#v_ident(inner) => std::rc::Rc::get_mut(inner),
5508 _ => None,
5509 }),
5510 )
5511 }
5512 });
5513 }
5514 (WrapperKind::Arc, Some(inner_ty)) => {
5515 tokens.extend(quote! {
5516 #[inline(always)]
5517 pub fn #snake() -> rust_key_paths::Kp<
5518 #name,
5519 #inner_ty,
5520 &'static #name,
5521 &'static #inner_ty,
5522 &'static mut #name,
5523 &'static mut #inner_ty,
5524 impl Fn(&#name) -> Option<&#inner_ty>,
5525 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
5526 > {
5527 rust_key_paths::Kp::new(
5528 rust_key_paths::constrain_get(|root: &#name| match root {
5529 #name::#v_ident(inner) => Some(inner.as_ref()),
5530 _ => None,
5531 }),
5532 rust_key_paths::constrain_set(|root: &mut #name| match root {
5533 #name::#v_ident(inner) => std::sync::Arc::get_mut(inner),
5534 _ => None,
5535 }),
5536 )
5537 }
5538 });
5539 }
5540 (WrapperKind::StdArcRwLock, Some(inner_ty)) => {
5541 let lock_kp_return_ty =
5542 kp_lock_ty_arc_rw_lock(name, field_ty, &inner_ty);
5543 tokens.extend(quote! {
5544 #[inline(always)]
5545 pub fn #snake<'b>() -> #lock_kp_return_ty {
5546 rust_key_paths::sync_kp::SyncKp::new(
5547 rust_key_paths::Kp::new(
5548 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5549 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5550 ),
5551 rust_key_paths::sync_kp::ArcRwLockAccess::new(),
5552 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5553 )
5554 }
5555 });
5556 }
5557 (WrapperKind::StdArcMutex, Some(inner_ty)) => {
5558 let lock_kp_return_ty =
5559 kp_lock_ty_arc_mutex(name, field_ty, &inner_ty);
5560 tokens.extend(quote! {
5561 #[inline(always)]
5562 pub fn #snake<'b>() -> #lock_kp_return_ty {
5563 rust_key_paths::sync_kp::SyncKp::new(
5564 rust_key_paths::Kp::new(
5565 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5566 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5567 ),
5568 rust_key_paths::sync_kp::ArcMutexAccess::new(),
5569 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5570 )
5571 }
5572 });
5573 }
5574 (WrapperKind::ArcRwLock, Some(inner_ty)) => {
5575 let lock_kp_return_ty =
5576 kp_lock_ty_parking_lot_rw_lock(name, field_ty, &inner_ty);
5577 tokens.extend(quote! {
5578 #[inline(always)]
5579 pub fn #snake<'b>() -> #lock_kp_return_ty {
5580 rust_key_paths::sync_kp::SyncKp::new(
5581 rust_key_paths::Kp::new(
5582 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5583 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5584 ),
5585 rust_key_paths::sync_kp::ParkingLotRwLockAccess::new(),
5586 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5587 )
5588 }
5589 });
5590 }
5591 (WrapperKind::ArcMutex, Some(inner_ty)) => {
5592 let lock_kp_return_ty =
5593 kp_lock_ty_parking_lot_mutex(name, field_ty, &inner_ty);
5594 tokens.extend(quote! {
5595 #[inline(always)]
5596 pub fn #snake<'b>() -> #lock_kp_return_ty {
5597 rust_key_paths::sync_kp::SyncKp::new(
5598 rust_key_paths::Kp::new(
5599 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5600 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5601 ),
5602 rust_key_paths::sync_kp::ParkingLotMutexAccess::new(),
5603 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5604 )
5605 }
5606 });
5607 }
5608 (WrapperKind::StdArcMutexOption, Some(inner_ty)) => {
5609 let lock_kp_return_ty =
5610 kp_lock_ty_arc_mutex_option(name, field_ty, &inner_ty);
5611 tokens.extend(quote! {
5612 #[inline(always)]
5613 pub fn #snake<'b>() -> #lock_kp_return_ty {
5614 rust_key_paths::sync_kp::SyncKp::new(
5615 rust_key_paths::Kp::new(
5616 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5617 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5618 ),
5619 rust_key_paths::sync_kp::ArcMutexAccess::<Option<#inner_ty>>::new(),
5620 rust_key_paths::Kp::new(Option::<#inner_ty>::as_ref, Option::<#inner_ty>::as_mut),
5621 )
5622 }
5623 });
5624 }
5625 (WrapperKind::StdArcRwLockOption, Some(inner_ty)) => {
5626 let lock_kp_return_ty =
5627 kp_lock_ty_arc_rw_lock_option(name, field_ty, &inner_ty);
5628 tokens.extend(quote! {
5629 #[inline(always)]
5630 pub fn #snake<'b>() -> #lock_kp_return_ty {
5631 rust_key_paths::sync_kp::SyncKp::new(
5632 rust_key_paths::Kp::new(
5633 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5634 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5635 ),
5636 rust_key_paths::sync_kp::ArcRwLockAccess::<Option<#inner_ty>>::new(),
5637 rust_key_paths::Kp::new(Option::<#inner_ty>::as_ref, Option::<#inner_ty>::as_mut),
5638 )
5639 }
5640 });
5641 }
5642 (WrapperKind::BareArcSwap, Some(inner_ty)) => {
5643 let lock_kp_return_ty =
5644 kp_lock_ty_arc_arc_swap(name, field_ty, &inner_ty);
5645 tokens.extend(quote! {
5646 #[inline(always)]
5647 pub fn #snake<'b>() -> #lock_kp_return_ty {
5648 rust_key_paths::sync_kp::SyncKp::new(
5649 rust_key_paths::Kp::new(
5650 rust_key_paths::constrain_get(|root: &#name| match root {
5651 #name::#v_ident(inner) => Some(inner),
5652 _ => None,
5653 }),
5654 rust_key_paths::constrain_set(|root: &mut #name| match root {
5655 #name::#v_ident(inner) => Some(inner),
5656 _ => None,
5657 }),
5658 ),
5659 rust_key_paths::sync_kp::ArcArcSwapAccess::new(),
5660 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5661 )
5662 }
5663 });
5664 }
5665 (WrapperKind::BareArcSwapOption, Some(inner_ty)) => {
5666 let lock_kp_return_ty =
5667 kp_lock_ty_arc_arc_swap_option(name, field_ty, &inner_ty);
5668 tokens.extend(quote! {
5669 #[inline(always)]
5670 pub fn #snake<'b>() -> #lock_kp_return_ty {
5671 rust_key_paths::sync_kp::SyncKp::new(
5672 rust_key_paths::Kp::new(
5673 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5674 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5675 ),
5676 rust_key_paths::sync_kp::ArcArcSwapOptionAccess::<#inner_ty>::new(),
5677 rust_key_paths::Kp::new(
5678 |o: &::std::option::Option<::std::sync::Arc<#inner_ty>>| {
5679 o.as_ref().map(|a| a.as_ref())
5680 },
5681 |o: &mut ::std::option::Option<::std::sync::Arc<#inner_ty>>| {
5682 o.as_mut().and_then(::std::sync::Arc::get_mut)
5683 },
5684 ),
5685 )
5686 }
5687 });
5688 }
5689 (WrapperKind::ArcArcSwap, Some(inner_ty)) => {
5690 let lock_kp_return_ty =
5691 kp_lock_ty_arc_arc_swap(name, field_ty, &inner_ty);
5692 tokens.extend(quote! {
5693 #[inline(always)]
5694 pub fn #snake<'b>() -> #lock_kp_return_ty {
5695 rust_key_paths::sync_kp::SyncKp::new(
5696 rust_key_paths::Kp::new(
5697 rust_key_paths::constrain_get(|root: &#name| match root {
5698 #name::#v_ident(inner) => Some(inner),
5699 _ => None,
5700 }),
5701 rust_key_paths::constrain_set(|root: &mut #name| match root {
5702 #name::#v_ident(inner) => Some(inner),
5703 _ => None,
5704 }),
5705 ),
5706 rust_key_paths::sync_kp::ArcArcSwapAccess::new(),
5707 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5708 )
5709 }
5710 });
5711 }
5712 (WrapperKind::ArcArcSwapOption, Some(inner_ty)) => {
5713 let lock_kp_return_ty =
5714 kp_lock_ty_arc_arc_swap_option(name, field_ty, &inner_ty);
5715 tokens.extend(quote! {
5716 #[inline(always)]
5717 pub fn #snake<'b>() -> #lock_kp_return_ty {
5718 rust_key_paths::sync_kp::SyncKp::new(
5719 rust_key_paths::Kp::new(
5720 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5721 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5722 ),
5723 rust_key_paths::sync_kp::ArcArcSwapOptionAccess::<#inner_ty>::new(),
5724 rust_key_paths::Kp::new(
5725 |o: &::std::option::Option<::std::sync::Arc<#inner_ty>>| {
5726 o.as_ref().map(|a| a.as_ref())
5727 },
5728 |o: &mut ::std::option::Option<::std::sync::Arc<#inner_ty>>| {
5729 o.as_mut().and_then(::std::sync::Arc::get_mut)
5730 },
5731 ),
5732 )
5733 }
5734 });
5735 }
5736 (WrapperKind::OptionArcArcSwap, Some(inner_ty)) => {
5737 let arc_mod = arc_swap_crate_ident_from_container_ty(field_ty);
5738 let lock_ty =
5739 quote! { ::std::sync::Arc<#arc_mod::ArcSwap<#inner_ty>> };
5740 let lock_kp_return_ty =
5741 kp_lock_ty_arc_arc_swap(name, &lock_ty, &inner_ty);
5742 tokens.extend(quote! {
5743 #[inline(always)]
5744 pub fn #snake<'b>() -> #lock_kp_return_ty {
5745 rust_key_paths::sync_kp::SyncKp::new(
5746 rust_key_paths::Kp::new(
5747 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None }),
5748 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None }),
5749 ),
5750 rust_key_paths::sync_kp::ArcArcSwapAccess::new(),
5751 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5752 )
5753 }
5754 });
5755 }
5756 (WrapperKind::OptionArcArcSwapOption, Some(inner_ty)) => {
5757 let arc_mod = arc_swap_crate_ident_from_container_ty(field_ty);
5758 let lock_ty =
5759 quote! { ::std::sync::Arc<#arc_mod::ArcSwapOption<#inner_ty>> };
5760 let lock_kp_return_ty =
5761 kp_lock_ty_arc_arc_swap_option(name, &lock_ty, &inner_ty);
5762 tokens.extend(quote! {
5763 #[inline(always)]
5764 pub fn #snake<'b>() -> #lock_kp_return_ty {
5765 rust_key_paths::sync_kp::SyncKp::new(
5766 rust_key_paths::Kp::new(
5767 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None }),
5768 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None }),
5769 ),
5770 rust_key_paths::sync_kp::ArcArcSwapOptionAccess::<#inner_ty>::new(),
5771 rust_key_paths::Kp::new(
5772 |o: &::std::option::Option<::std::sync::Arc<#inner_ty>>| {
5773 o.as_ref().map(|a| a.as_ref())
5774 },
5775 |o: &mut ::std::option::Option<::std::sync::Arc<#inner_ty>>| {
5776 o.as_mut().and_then(::std::sync::Arc::get_mut)
5777 },
5778 ),
5779 )
5780 }
5781 });
5782 }
5783 (WrapperKind::ArcMutexOption, Some(inner_ty)) => {
5784 let lock_kp_return_ty = kp_lock_ty_parking_lot_mutex_option(
5785 name, field_ty, &inner_ty,
5786 );
5787 tokens.extend(quote! {
5788 #[inline(always)]
5789 pub fn #snake<'b>() -> #lock_kp_return_ty {
5790 rust_key_paths::sync_kp::SyncKp::new(
5791 rust_key_paths::Kp::new(
5792 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5793 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5794 ),
5795 rust_key_paths::sync_kp::ParkingLotMutexAccess::<Option<#inner_ty>>::new(),
5796 rust_key_paths::Kp::new(Option::<#inner_ty>::as_ref, Option::<#inner_ty>::as_mut),
5797 )
5798 }
5799 });
5800 }
5801 (WrapperKind::ArcRwLockOption, Some(inner_ty)) => {
5802 let lock_kp_return_ty = kp_lock_ty_parking_lot_rw_lock_option(
5803 name, field_ty, &inner_ty,
5804 );
5805 tokens.extend(quote! {
5806 #[inline(always)]
5807 pub fn #snake<'b>() -> #lock_kp_return_ty {
5808 rust_key_paths::sync_kp::SyncKp::new(
5809 rust_key_paths::Kp::new(
5810 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5811 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5812 ),
5813 rust_key_paths::sync_kp::ParkingLotRwLockAccess::<Option<#inner_ty>>::new(),
5814 rust_key_paths::Kp::new(Option::<#inner_ty>::as_ref, Option::<#inner_ty>::as_mut),
5815 )
5816 }
5817 });
5818 }
5819 (WrapperKind::TokioArcMutex, Some(inner_ty)) => {
5820 let snake_async = format_ident!("{}_kp", snake);
5821 tokens.extend(quote! {
5822 #[inline(always)]
5823 pub fn #snake_async() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5824 rust_key_paths::Kp::new(
5825 rust_key_paths::constrain_get(|root: &#name| match root {
5826 #name::#v_ident(inner) => Some(inner),
5827 _ => None,
5828 }),
5829 rust_key_paths::constrain_set(|root: &mut #name| match root {
5830 #name::#v_ident(inner) => Some(inner),
5831 _ => None,
5832 }),
5833 )
5834 }
5835 pub fn #snake() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, #field_ty, #inner_ty> {
5836 rust_key_paths::async_lock::AsyncLockKp::new(
5837 rust_key_paths::Kp::new(
5838 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5839 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5840 ),
5841 rust_key_paths::async_lock::TokioMutexAccess::new(),
5842 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5843 )
5844 }
5845 });
5846 }
5847 (WrapperKind::TokioArcRwLock, Some(inner_ty)) => {
5848 let snake_async = format_ident!("{}_kp", snake);
5849 tokens.extend(quote! {
5850 #[inline(always)]
5851 pub fn #snake_async() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5852 rust_key_paths::Kp::new(
5853 rust_key_paths::constrain_get(|root: &#name| match root {
5854 #name::#v_ident(inner) => Some(inner),
5855 _ => None,
5856 }),
5857 rust_key_paths::constrain_set(|root: &mut #name| match root {
5858 #name::#v_ident(inner) => Some(inner),
5859 _ => None,
5860 }),
5861 )
5862 }
5863 pub fn #snake() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, #field_ty, #inner_ty> {
5864 rust_key_paths::async_lock::AsyncLockKp::new(
5865 rust_key_paths::Kp::new(
5866 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5867 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => Some(inner), _ => None }),
5868 ),
5869 rust_key_paths::async_lock::TokioRwLockAccess::new(),
5870 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5871 )
5872 }
5873 });
5874 }
5875 (WrapperKind::OptionTokioArcMutex, Some(inner_ty)) => {
5876 let snake_async = format_ident!("{}_kp", snake);
5877 tokens.extend(quote! {
5878 #[inline(always)]
5879 pub fn #snake_async() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5880 rust_key_paths::Kp::new(
5881 rust_key_paths::constrain_get(|root: &#name| match root {
5882 #name::#v_ident(inner) => Some(inner),
5883 _ => None,
5884 }),
5885 rust_key_paths::constrain_set(|root: &mut #name| match root {
5886 #name::#v_ident(inner) => Some(inner),
5887 _ => None,
5888 }),
5889 )
5890 }
5891 pub fn #snake() -> rust_key_paths::async_lock::AsyncLockKpMutexFor<#name, std::sync::Arc<tokio::sync::Mutex<#inner_ty>>, #inner_ty> {
5892 rust_key_paths::async_lock::AsyncLockKp::new(
5893 rust_key_paths::Kp::new(
5894 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None }),
5895 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None }),
5896 ),
5897 rust_key_paths::async_lock::TokioMutexAccess::new(),
5898 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5899 )
5900 }
5901 });
5902 }
5903 (WrapperKind::OptionTokioArcRwLock, Some(inner_ty)) => {
5904 let snake_async = format_ident!("{}_kp", snake);
5905 tokens.extend(quote! {
5906 #[inline(always)]
5907 pub fn #snake_async() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
5908 rust_key_paths::Kp::new(
5909 rust_key_paths::constrain_get(|root: &#name| match root {
5910 #name::#v_ident(inner) => Some(inner),
5911 _ => None,
5912 }),
5913 rust_key_paths::constrain_set(|root: &mut #name| match root {
5914 #name::#v_ident(inner) => Some(inner),
5915 _ => None,
5916 }),
5917 )
5918 }
5919 pub fn #snake() -> rust_key_paths::async_lock::AsyncLockKpRwLockFor<#name, std::sync::Arc<tokio::sync::RwLock<#inner_ty>>, #inner_ty> {
5920 rust_key_paths::async_lock::AsyncLockKp::new(
5921 rust_key_paths::Kp::new(
5922 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None }),
5923 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None }),
5924 ),
5925 rust_key_paths::async_lock::TokioRwLockAccess::new(),
5926 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5927 )
5928 }
5929 });
5930 }
5931 (WrapperKind::OptionStdArcMutex, Some(inner_ty)) => {
5932 let lock_ty =
5933 quote! { std::sync::Arc<std::sync::Mutex<#inner_ty>> };
5934 let lock_kp_return_ty =
5935 kp_lock_ty_arc_mutex(name, &lock_ty, &inner_ty);
5936 tokens.extend(quote! {
5937 #[inline(always)]
5938 pub fn #snake<'b>() -> #lock_kp_return_ty {
5939 rust_key_paths::sync_kp::SyncKp::new(
5940 rust_key_paths::Kp::new(
5941 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None }),
5942 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None }),
5943 ),
5944 rust_key_paths::sync_kp::ArcMutexAccess::new(),
5945 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5946 )
5947 }
5948 });
5949 }
5950 (WrapperKind::OptionArcMutex, Some(inner_ty)) => {
5951 let lock_ty =
5952 quote! { std::sync::Arc<parking_lot::Mutex<#inner_ty>> };
5953 let lock_kp_return_ty =
5954 kp_lock_ty_parking_lot_mutex(name, &lock_ty, &inner_ty);
5955 tokens.extend(quote! {
5956 #[inline(always)]
5957 pub fn #snake<'b>() -> #lock_kp_return_ty {
5958 rust_key_paths::sync_kp::SyncKp::new(
5959 rust_key_paths::Kp::new(
5960 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None }),
5961 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None }),
5962 ),
5963 rust_key_paths::sync_kp::ParkingLotMutexAccess::new(),
5964 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5965 )
5966 }
5967 });
5968 }
5969 (WrapperKind::OptionStdArcRwLock, Some(inner_ty)) => {
5970 let lock_ty =
5971 quote! { std::sync::Arc<std::sync::RwLock<#inner_ty>> };
5972 let lock_kp_return_ty =
5973 kp_lock_ty_arc_rw_lock(name, &lock_ty, &inner_ty);
5974 tokens.extend(quote! {
5975 #[inline(always)]
5976 pub fn #snake<'b>() -> #lock_kp_return_ty {
5977 rust_key_paths::sync_kp::SyncKp::new(
5978 rust_key_paths::Kp::new(
5979 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None }),
5980 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None }),
5981 ),
5982 rust_key_paths::sync_kp::ArcRwLockAccess::new(),
5983 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
5984 )
5985 }
5986 });
5987 }
5988 (WrapperKind::OptionArcRwLock, Some(inner_ty)) => {
5989 let lock_ty =
5990 quote! { std::sync::Arc<parking_lot::RwLock<#inner_ty>> };
5991 let lock_kp_return_ty =
5992 kp_lock_ty_parking_lot_rw_lock(name, &lock_ty, &inner_ty);
5993 tokens.extend(quote! {
5994 #[inline(always)]
5995 pub fn #snake<'b>() -> #lock_kp_return_ty {
5996 rust_key_paths::sync_kp::SyncKp::new(
5997 rust_key_paths::Kp::new(
5998 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None }),
5999 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None }),
6000 ),
6001 rust_key_paths::sync_kp::ParkingLotRwLockAccess::new(),
6002 rust_key_paths::Kp::new(|v: &#inner_ty| Some(v), |v: &mut #inner_ty| Some(v)),
6003 )
6004 }
6005 });
6006 }
6007 (WrapperKind::StdMutex, Some(_inner_ty))
6008 | (WrapperKind::Mutex, Some(_inner_ty))
6009 | (WrapperKind::StdRwLock, Some(_inner_ty))
6010 | (WrapperKind::RwLock, Some(_inner_ty)) => {
6011 tokens.extend(quote! {
6012 #[inline(always)]
6013 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
6014 rust_key_paths::Kp::new(
6015 rust_key_paths::constrain_get(|root: &#name| match root {
6016 #name::#v_ident(inner) => Some(inner),
6017 _ => None,
6018 }),
6019 rust_key_paths::constrain_set(|root: &mut #name| match root {
6020 #name::#v_ident(inner) => Some(inner),
6021 _ => None,
6022 }),
6023 )
6024 }
6025 });
6026 }
6027 (WrapperKind::Tagged, Some(inner_ty)) => {
6028 tokens.extend(quote! {
6029 #[inline(always)]
6030 pub fn #snake() -> rust_key_paths::Kp<
6031 #name,
6032 #inner_ty,
6033 &'static #name,
6034 &'static #inner_ty,
6035 &'static mut #name,
6036 &'static mut #inner_ty,
6037 impl Fn(&#name) -> Option<&#inner_ty>,
6038 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6039 > {
6040 rust_key_paths::Kp::new(
6041 rust_key_paths::constrain_get(|root: &#name| match root {
6042 #name::#v_ident(inner) => Some(std::ops::Deref::deref(inner)),
6043 _ => None,
6044 }),
6045 rust_key_paths::constrain_set(|root: &mut #name| match root {
6046 #name::#v_ident(inner) => Some(std::ops::DerefMut::deref_mut(inner)),
6047 _ => None,
6048 }),
6049 )
6050 }
6051 });
6052 }
6053 (WrapperKind::Atomic, None | Some(_)) => {
6054 tokens.extend(quote! {
6055 #[inline(always)]
6056 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
6057 rust_key_paths::Kp::new(
6058 rust_key_paths::constrain_get(|root: &#name| match root {
6059 #name::#v_ident(inner) => Some(inner),
6060 _ => None,
6061 }),
6062 rust_key_paths::constrain_set(|root: &mut #name| match root {
6063 #name::#v_ident(inner) => Some(inner),
6064 _ => None,
6065 }),
6066 )
6067 }
6068 });
6069 }
6070 (WrapperKind::OptionAtomic, Some(inner_ty)) => {
6071 tokens.extend(quote! {
6072 #[inline(always)]
6073 pub fn #snake() -> rust_key_paths::Kp<
6074 #name,
6075 #inner_ty,
6076 &'static #name,
6077 &'static #inner_ty,
6078 &'static mut #name,
6079 &'static mut #inner_ty,
6080 impl Fn(&#name) -> Option<&#inner_ty>,
6081 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6082 > {
6083 rust_key_paths::Kp::new(
6084 rust_key_paths::constrain_get(|root: &#name| match root { #name::#v_ident(inner) => inner.as_ref(), _ => None }),
6085 rust_key_paths::constrain_set(|root: &mut #name| match root { #name::#v_ident(inner) => inner.as_mut(), _ => None }),
6086 )
6087 }
6088 });
6089 }
6090 (WrapperKind::Reference, Some(_inner_ty)) => {
6091 tokens.extend(quote! {
6092 #[inline(always)]
6093 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
6094 rust_key_paths::Kp::new(
6095 rust_key_paths::constrain_get(|root: &#name| match root {
6096 #name::#v_ident(inner) => Some(inner),
6097 _ => None,
6098 }),
6099 rust_key_paths::constrain_set(|_root: &mut #name| None),
6100 )
6101 }
6102 });
6103 }
6104 (WrapperKind::Weak, Some(_inner_ty)) => {
6105 tokens.extend(quote! {
6106 #[inline(always)]
6107 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
6108 rust_key_paths::Kp::new(
6109 rust_key_paths::constrain_get(|root: &#name| match root {
6110 #name::#v_ident(inner) => Some(inner),
6111 _ => None,
6112 }),
6113 rust_key_paths::constrain_set(|_root: &mut #name| None),
6114 )
6115 }
6116 });
6117 }
6118 (WrapperKind::Cow, Some(inner_ty)) => {
6119 tokens.extend(quote! {
6120 #[inline(always)]
6121 pub fn #snake() -> rust_key_paths::Kp<
6122 #name,
6123 #inner_ty,
6124 &'static #name,
6125 &'static #inner_ty,
6126 &'static mut #name,
6127 &'static mut #inner_ty,
6128 impl Fn(&#name) -> Option<&#inner_ty>,
6129 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6130 > {
6131 rust_key_paths::Kp::new(
6132 rust_key_paths::constrain_get(|root: &#name| match root {
6133 #name::#v_ident(inner) => Some(inner.as_ref()),
6134 _ => None,
6135 }),
6136 rust_key_paths::constrain_set(|root: &mut #name| match root {
6137 #name::#v_ident(inner) => Some(inner.to_mut()),
6138 _ => None,
6139 }),
6140 )
6141 }
6142 });
6143 }
6144 (WrapperKind::OptionBox, Some(inner_ty)) => {
6145 // Option<Box<T>>: keypath to T via as_deref() / as_deref_mut()
6146 tokens.extend(quote! {
6147 #[inline(always)]
6148 pub fn #snake() -> rust_key_paths::Kp<
6149 #name,
6150 #inner_ty,
6151 &'static #name,
6152 &'static #inner_ty,
6153 &'static mut #name,
6154 &'static mut #inner_ty,
6155 impl Fn(&#name) -> Option<&#inner_ty>,
6156 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6157 > {
6158 rust_key_paths::Kp::new(
6159 rust_key_paths::constrain_get(|root: &#name| match root {
6160 #name::#v_ident(inner) => inner.as_deref(),
6161 _ => None,
6162 }),
6163 rust_key_paths::constrain_set(|root: &mut #name| match root {
6164 #name::#v_ident(inner) => inner.as_deref_mut(),
6165 _ => None,
6166 }),
6167 )
6168 }
6169 });
6170 }
6171 (WrapperKind::BoxOption, Some(inner_ty)) => {
6172 // Box<Option<T>>: keypath to T; inner is &Box<Option<T>>, deref then Option::as_ref/as_mut
6173 tokens.extend(quote! {
6174 #[inline(always)]
6175 pub fn #snake() -> rust_key_paths::Kp<
6176 #name,
6177 #inner_ty,
6178 &'static #name,
6179 &'static #inner_ty,
6180 &'static mut #name,
6181 &'static mut #inner_ty,
6182 impl Fn(&#name) -> Option<&#inner_ty>,
6183 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6184 > {
6185 rust_key_paths::Kp::new(
6186 rust_key_paths::constrain_get(|root: &#name| match root {
6187 #name::#v_ident(inner) => (&*inner).as_ref(),
6188 _ => None,
6189 }),
6190 rust_key_paths::constrain_set(|root: &mut #name| match root {
6191 #name::#v_ident(inner) => (&mut *inner).as_mut(),
6192 _ => None,
6193 }),
6194 )
6195 }
6196 });
6197 }
6198 (WrapperKind::RcOption, Some(inner_ty)) => {
6199 // Rc<Option<T>>: keypath to T; get = (&*inner).as_ref(), set = Rc::get_mut then as_mut
6200 tokens.extend(quote! {
6201 #[inline(always)]
6202 pub fn #snake() -> rust_key_paths::Kp<
6203 #name,
6204 #inner_ty,
6205 &'static #name,
6206 &'static #inner_ty,
6207 &'static mut #name,
6208 &'static mut #inner_ty,
6209 impl Fn(&#name) -> Option<&#inner_ty>,
6210 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6211 > {
6212 rust_key_paths::Kp::new(
6213 rust_key_paths::constrain_get(|root: &#name| match root {
6214 #name::#v_ident(inner) => (&*inner).as_ref(),
6215 _ => None,
6216 }),
6217 rust_key_paths::constrain_set(|root: &mut #name| match root {
6218 #name::#v_ident(inner) => std::rc::Rc::get_mut(inner).and_then(std::option::Option::as_mut),
6219 _ => None,
6220 }),
6221 )
6222 }
6223 });
6224 }
6225 (WrapperKind::ArcOption, Some(inner_ty)) => {
6226 // Arc<Option<T>>: keypath to T; get = (&*inner).as_ref(), set = Arc::get_mut then as_mut
6227 tokens.extend(quote! {
6228 #[inline(always)]
6229 pub fn #snake() -> rust_key_paths::Kp<
6230 #name,
6231 #inner_ty,
6232 &'static #name,
6233 &'static #inner_ty,
6234 &'static mut #name,
6235 &'static mut #inner_ty,
6236 impl Fn(&#name) -> Option<&#inner_ty>,
6237 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6238 > {
6239 rust_key_paths::Kp::new(
6240 rust_key_paths::constrain_get(|root: &#name| match root {
6241 #name::#v_ident(inner) => (&*inner).as_ref(),
6242 _ => None,
6243 }),
6244 rust_key_paths::constrain_set(|root: &mut #name| match root {
6245 #name::#v_ident(inner) => std::sync::Arc::get_mut(inner).and_then(std::option::Option::as_mut),
6246 _ => None,
6247 }),
6248 )
6249 }
6250 });
6251 }
6252 (WrapperKind::OptionRc, Some(inner_ty)) => {
6253 tokens.extend(quote! {
6254 #[inline(always)]
6255 pub fn #snake() -> rust_key_paths::Kp<
6256 #name,
6257 #inner_ty,
6258 &'static #name,
6259 &'static #inner_ty,
6260 &'static mut #name,
6261 &'static mut #inner_ty,
6262 impl Fn(&#name) -> Option<&#inner_ty>,
6263 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6264 > {
6265 rust_key_paths::Kp::new(
6266 rust_key_paths::constrain_get(|root: &#name| match root {
6267 #name::#v_ident(inner) => inner.as_deref(),
6268 _ => None,
6269 }),
6270 rust_key_paths::constrain_set(|root: &mut #name| match root {
6271 #name::#v_ident(inner) => inner.as_mut().and_then(std::rc::Rc::get_mut),
6272 _ => None,
6273 }),
6274 )
6275 }
6276 });
6277 }
6278 (WrapperKind::OptionArc, Some(inner_ty)) => {
6279 tokens.extend(quote! {
6280 #[inline(always)]
6281 pub fn #snake() -> rust_key_paths::Kp<
6282 #name,
6283 #inner_ty,
6284 &'static #name,
6285 &'static #inner_ty,
6286 &'static mut #name,
6287 &'static mut #inner_ty,
6288 impl Fn(&#name) -> Option<&#inner_ty>,
6289 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6290 > {
6291 rust_key_paths::Kp::new(
6292 rust_key_paths::constrain_get(|root: &#name| match root {
6293 #name::#v_ident(inner) => inner.as_deref(),
6294 _ => None,
6295 }),
6296 rust_key_paths::constrain_set(|root: &mut #name| match root {
6297 #name::#v_ident(inner) => inner.as_mut().and_then(std::sync::Arc::get_mut),
6298 _ => None,
6299 }),
6300 )
6301 }
6302 });
6303 }
6304 (WrapperKind::OptionCow, Some(inner_ty)) => {
6305 tokens.extend(quote! {
6306 #[inline(always)]
6307 pub fn #snake() -> rust_key_paths::Kp<
6308 #name,
6309 #inner_ty,
6310 &'static #name,
6311 &'static #inner_ty,
6312 &'static mut #name,
6313 &'static mut #inner_ty,
6314 impl Fn(&#name) -> Option<&#inner_ty>,
6315 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6316 > {
6317 rust_key_paths::Kp::new(
6318 rust_key_paths::constrain_get(|root: &#name| match root {
6319 #name::#v_ident(inner) => inner.as_ref().map(|c| c.as_ref()),
6320 _ => None,
6321 }),
6322 rust_key_paths::constrain_set(|root: &mut #name| match root {
6323 #name::#v_ident(inner) => inner.as_mut().map(|c| c.to_mut()),
6324 _ => None,
6325 }),
6326 )
6327 }
6328 });
6329 }
6330 (WrapperKind::OptionTagged, Some(inner_ty)) => {
6331 tokens.extend(quote! {
6332 #[inline(always)]
6333 pub fn #snake() -> rust_key_paths::Kp<
6334 #name,
6335 #inner_ty,
6336 &'static #name,
6337 &'static #inner_ty,
6338 &'static mut #name,
6339 &'static mut #inner_ty,
6340 impl Fn(&#name) -> Option<&#inner_ty>,
6341 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6342 > {
6343 rust_key_paths::Kp::new(
6344 rust_key_paths::constrain_get(|root: &#name| match root {
6345 #name::#v_ident(inner) => inner.as_ref().map(|t| std::ops::Deref::deref(t)),
6346 _ => None,
6347 }),
6348 rust_key_paths::constrain_set(|root: &mut #name| match root {
6349 #name::#v_ident(inner) => inner.as_mut().map(|t| std::ops::DerefMut::deref_mut(t)),
6350 _ => None,
6351 }),
6352 )
6353 }
6354 });
6355 }
6356 (WrapperKind::OptionReference, Some(inner_ty)) => {
6357 tokens.extend(quote! {
6358 #[inline(always)]
6359 pub fn #snake() -> rust_key_paths::Kp<
6360 #name,
6361 #inner_ty,
6362 &'static #name,
6363 &'static #inner_ty,
6364 &'static mut #name,
6365 &'static mut #inner_ty,
6366 impl Fn(&#name) -> Option<&#inner_ty>,
6367 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6368 > {
6369 rust_key_paths::Kp::new(
6370 rust_key_paths::constrain_get(|root: &#name| match root {
6371 #name::#v_ident(inner) => inner.as_ref(),
6372 _ => None,
6373 }),
6374 rust_key_paths::constrain_set(|_root: &mut #name| None),
6375 )
6376 }
6377 });
6378 }
6379 (WrapperKind::String, None) => {
6380 tokens.extend(quote! {
6381 #[inline(always)]
6382 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
6383 rust_key_paths::Kp::new(
6384 rust_key_paths::constrain_get(|root: &#name| match root {
6385 #name::#v_ident(inner) => Some(inner),
6386 _ => None,
6387 }),
6388 rust_key_paths::constrain_set(|root: &mut #name| match root {
6389 #name::#v_ident(inner) => Some(inner),
6390 _ => None,
6391 }),
6392 )
6393 }
6394 });
6395 }
6396 (WrapperKind::OptionString, None) => {
6397 tokens.extend(quote! {
6398 #[inline(always)]
6399 pub fn #snake() -> rust_key_paths::Kp<#name, std::string::String, &'static #name, &'static std::string::String, &'static mut #name, &'static mut std::string::String, impl Fn(&#name) -> Option<&std::string::String>, impl Fn(&mut #name) -> Option<&mut std::string::String>,> {
6400 rust_key_paths::Kp::new(
6401 rust_key_paths::constrain_get(|root: &#name| match root {
6402 #name::#v_ident(inner) => inner.as_ref(),
6403 _ => None,
6404 }),
6405 rust_key_paths::constrain_set(|root: &mut #name| match root {
6406 #name::#v_ident(inner) => inner.as_mut(),
6407 _ => None,
6408 }),
6409 )
6410 }
6411 });
6412 }
6413 (WrapperKind::OnceCell, Some(inner_ty)) => {
6414 tokens.extend(quote! {
6415 #[inline(always)]
6416 pub fn #snake() -> rust_key_paths::Kp<
6417 #name,
6418 #inner_ty,
6419 &'static #name,
6420 &'static #inner_ty,
6421 &'static mut #name,
6422 &'static mut #inner_ty,
6423 impl Fn(&#name) -> Option<&#inner_ty>,
6424 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6425 > {
6426 rust_key_paths::Kp::new(
6427 rust_key_paths::constrain_get(|root: &#name| match root {
6428 #name::#v_ident(inner) => inner.get(),
6429 _ => None,
6430 }),
6431 rust_key_paths::constrain_set(|_root: &mut #name| None),
6432 )
6433 }
6434 });
6435 }
6436 (WrapperKind::Lazy, Some(inner_ty)) => {
6437 tokens.extend(quote! {
6438 #[inline(always)]
6439 pub fn #snake() -> rust_key_paths::Kp<
6440 #name,
6441 #inner_ty,
6442 &'static #name,
6443 &'static #inner_ty,
6444 &'static mut #name,
6445 &'static mut #inner_ty,
6446 impl Fn(&#name) -> Option<&#inner_ty>,
6447 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6448 > {
6449 rust_key_paths::Kp::new(
6450 rust_key_paths::constrain_get(|root: &#name| match root {
6451 #name::#v_ident(inner) => Some(inner.get()),
6452 _ => None,
6453 }),
6454 rust_key_paths::constrain_set(|_root: &mut #name| None),
6455 )
6456 }
6457 });
6458 }
6459 (WrapperKind::OptionOnceCell, Some(inner_ty)) => {
6460 tokens.extend(quote! {
6461 #[inline(always)]
6462 pub fn #snake() -> rust_key_paths::Kp<
6463 #name,
6464 #inner_ty,
6465 &'static #name,
6466 &'static #inner_ty,
6467 &'static mut #name,
6468 &'static mut #inner_ty,
6469 impl Fn(&#name) -> Option<&#inner_ty>,
6470 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6471 > {
6472 rust_key_paths::Kp::new(
6473 rust_key_paths::constrain_get(|root: &#name| match root {
6474 #name::#v_ident(inner) => inner.as_ref().and_then(|c| c.get()),
6475 _ => None,
6476 }),
6477 rust_key_paths::constrain_set(|_root: &mut #name| None),
6478 )
6479 }
6480 });
6481 }
6482 (WrapperKind::OptionLazy, Some(inner_ty)) => {
6483 tokens.extend(quote! {
6484 #[inline(always)]
6485 pub fn #snake() -> rust_key_paths::Kp<
6486 #name,
6487 #inner_ty,
6488 &'static #name,
6489 &'static #inner_ty,
6490 &'static mut #name,
6491 &'static mut #inner_ty,
6492 impl Fn(&#name) -> Option<&#inner_ty>,
6493 impl Fn(&mut #name) -> Option<&mut #inner_ty>,
6494 > {
6495 rust_key_paths::Kp::new(
6496 rust_key_paths::constrain_get(|root: &#name| match root {
6497 #name::#v_ident(inner) => inner.as_ref().map(|c| c.get()),
6498 _ => None,
6499 }),
6500 rust_key_paths::constrain_set(|_root: &mut #name| None),
6501 )
6502 }
6503 });
6504 }
6505 (WrapperKind::Cell, Some(_inner_ty))
6506 | (WrapperKind::RefCell, Some(_inner_ty))
6507 | (WrapperKind::PhantomData, Some(_inner_ty))
6508 | (WrapperKind::Range, Some(_inner_ty))
6509 | (WrapperKind::OptionCell, Some(_inner_ty))
6510 | (WrapperKind::OptionPhantomData, Some(_inner_ty))
6511 | (WrapperKind::OptionRange, Some(_inner_ty)) => {
6512 tokens.extend(quote! {
6513 #[inline(always)]
6514 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
6515 rust_key_paths::Kp::new(
6516 rust_key_paths::constrain_get(|root: &#name| match root {
6517 #name::#v_ident(inner) => Some(inner),
6518 _ => None,
6519 }),
6520 rust_key_paths::constrain_set(|root: &mut #name| match root {
6521 #name::#v_ident(inner) => Some(inner),
6522 _ => None,
6523 }),
6524 )
6525 }
6526 });
6527 }
6528 (WrapperKind::OptionRefCell, Some(inner_ty)) => {
6529 tokens.extend(quote! {
6530 #[inline(always)]
6531 pub fn #snake() -> rust_key_paths::KpOptionRefCellType<'_, #name, #inner_ty> {
6532 rust_key_paths::Kp::new(
6533 rust_key_paths::constrain_get(|root: &#name| match root {
6534 #name::#v_ident(inner) => inner.as_ref().map(|r| r.borrow()),
6535 _ => None,
6536 }),
6537 rust_key_paths::constrain_set(|root: &mut #name| match root {
6538 #name::#v_ident(inner) => inner.as_ref().map(|r| r.borrow_mut()),
6539 _ => None,
6540 }),
6541 )
6542 }
6543 });
6544 }
6545 (WrapperKind::None, None) => {
6546 // Basic type
6547 tokens.extend(quote! {
6548 #[inline(always)]
6549 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
6550 rust_key_paths::Kp::new(
6551 rust_key_paths::constrain_get(|root: &#name| match root {
6552 #name::#v_ident(inner) => Some(inner),
6553 _ => None,
6554 }),
6555 rust_key_paths::constrain_set(|root: &mut #name| match root {
6556 #name::#v_ident(inner) => Some(inner),
6557 _ => None,
6558 }),
6559 )
6560 }
6561 });
6562 }
6563 _ => {
6564 // Other wrapper types - return keypath to field
6565 tokens.extend(quote! {
6566 #[inline(always)]
6567 pub fn #snake() -> rust_key_paths::Kp<#name, #field_ty, &'static #name, &'static #field_ty, &'static mut #name, &'static mut #field_ty, impl Fn(&#name) -> Option<&#field_ty>, impl Fn(&mut #name) -> Option<&mut #field_ty>,> {
6568 rust_key_paths::Kp::new(
6569 rust_key_paths::constrain_get(|root: &#name| match root {
6570 #name::#v_ident(inner) => Some(inner),
6571 _ => None,
6572 }),
6573 rust_key_paths::constrain_set(|root: &mut #name| match root {
6574 #name::#v_ident(inner) => Some(inner),
6575 _ => None,
6576 }),
6577 )
6578 }
6579 });
6580 }
6581 }
6582 } else {
6583 // Multi-field tuple variant - return keypath to variant itself
6584 tokens.extend(quote! {
6585 #[inline(always)]
6586 pub fn #snake() -> rust_key_paths::Kp<#name, #name, &'static #name, &'static #name, &'static mut #name, &'static mut #name, impl Fn(&#name) -> Option<&#name>, impl Fn(&mut #name) -> Option<&mut #name>,> {
6587 rust_key_paths::Kp::new(
6588 rust_key_paths::constrain_get(|root: &#name| match root {
6589 #name::#v_ident(..) => Some(root),
6590 _ => None,
6591 }),
6592 rust_key_paths::constrain_set(|root: &mut #name| match root {
6593 #name::#v_ident(..) => Some(root),
6594 _ => None,
6595 }),
6596 )
6597 }
6598 });
6599 }
6600 }
6601 Fields::Named(_) => {
6602 // Named field variant - return keypath to variant itself
6603 tokens.extend(quote! {
6604 pub fn #snake() -> rust_key_paths::Kp<#name, #name, &'static #name, &'static #name, &'static mut #name, &'static mut #name, impl Fn(&#name) -> Option<&#name>, impl Fn(&mut #name) -> Option<&mut #name>,> {
6605 rust_key_paths::Kp::new(
6606 rust_key_paths::constrain_get(|root: &#name| match root {
6607 #name::#v_ident { .. } => Some(root),
6608 _ => None,
6609 }),
6610 rust_key_paths::constrain_set(|root: &mut #name| match root {
6611 #name::#v_ident { .. } => Some(root),
6612 _ => None,
6613 }),
6614 )
6615 }
6616 });
6617 }
6618 }
6619 }
6620
6621 tokens
6622 }
6623 Data::Union(_) => {
6624 return syn::Error::new(input_span, "Kp derive does not support unions")
6625 .to_compile_error()
6626 .into();
6627 }
6628 };
6629
6630 let expanded = quote! {
6631 impl #name {
6632 #methods
6633 }
6634 };
6635
6636 TokenStream::from(expanded)
6637}
6638
6639/// Derive macro that generates `partial_kps() -> Vec<PKp<Self>>` returning all field/variant keypaths.
6640/// **Requires `#[derive(Kp)]`** so the keypath accessor methods exist.
6641///
6642/// For structs: returns keypaths for each field. For enums: returns keypaths for each variant
6643/// (using the same methods Kp generates, e.g. `some_variant()`).
6644///
6645/// # Example
6646/// ```
6647/// use key_paths_derive::{Kp, Pkp};
6648/// use rust_key_paths::PKp;
6649///
6650/// #[derive(Kp, Pkp)]
6651/// struct Person {
6652/// name: String,
6653/// age: i32,
6654/// }
6655///
6656/// let kps = Person::partial_kps();
6657/// assert_eq!(kps.len(), 2);
6658/// ```
6659#[proc_macro_derive(Pkp)]
6660pub fn derive_partial_keypaths(input: TokenStream) -> TokenStream {
6661 let input = parse_macro_input!(input as DeriveInput);
6662 let name = &input.ident;
6663
6664 let kp_calls = match &input.data {
6665 Data::Struct(data_struct) => match &data_struct.fields {
6666 Fields::Named(fields_named) => {
6667 let calls: Vec<_> = fields_named
6668 .named
6669 .iter()
6670 .filter_map(|f| f.ident.as_ref())
6671 .map(|field_ident| {
6672 quote! { rust_key_paths::PKp::new(Self::#field_ident()) }
6673 })
6674 .collect();
6675 quote! { #(#calls),* }
6676 }
6677 Fields::Unnamed(unnamed) => {
6678 let calls: Vec<_> = (0..unnamed.unnamed.len())
6679 .map(|idx| {
6680 let kp_fn = format_ident!("f{}", idx);
6681 quote! { rust_key_paths::PKp::new(Self::#kp_fn()) }
6682 })
6683 .collect();
6684 quote! { #(#calls),* }
6685 }
6686 Fields::Unit => quote! {},
6687 },
6688 Data::Enum(data_enum) => {
6689 let calls: Vec<_> = data_enum
6690 .variants
6691 .iter()
6692 .map(|variant| {
6693 let v_ident = &variant.ident;
6694 let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
6695 quote! { rust_key_paths::PKp::new(Self::#snake()) }
6696 })
6697 .collect();
6698 quote! { #(#calls),* }
6699 }
6700 Data::Union(_) => {
6701 return syn::Error::new(input.ident.span(), "Pkp derive does not support unions")
6702 .to_compile_error()
6703 .into();
6704 }
6705 };
6706
6707 let expanded = quote! {
6708 impl #name {
6709 /// Returns a vec of all field keypaths as partial keypaths (type-erased).
6710 #[inline(always)]
6711 pub fn partial_kps() -> Vec<rust_key_paths::PKp<#name>> {
6712 vec![#kp_calls]
6713 }
6714 }
6715 };
6716
6717 TokenStream::from(expanded)
6718}
6719
6720/// Derive macro that generates `any_kps() -> Vec<AKp>` returning all field/variant keypaths as any keypaths.
6721/// **Requires `#[derive(Kp)]`** so the keypath accessor methods exist.
6722/// AKp type-erases both Root and Value), enabling heterogeneous collections of keypaths.
6723///
6724/// For structs: returns keypaths for each field. For enums: returns keypaths for each variant
6725/// (using the same methods Kp generates, e.g. `some_variant()`).
6726///
6727/// # Example
6728/// ```
6729/// use key_paths_derive::{Kp, Akp};
6730/// use rust_key_paths::AKp;
6731///
6732/// #[derive(Kp, Akp)]
6733/// struct Person {
6734/// name: String,
6735/// age: i32,
6736/// }
6737///
6738/// let kps = Person::any_kps();
6739/// assert_eq!(kps.len(), 2);
6740/// let person = Person { name: "Akash".into(), age: 30 };
6741/// let name: Option<&String> = kps[0].get(&person as &dyn std::any::Any).and_then(|v| v.downcast_ref());
6742/// assert_eq!(name, Some(&"Akash".to_string()));
6743/// ```
6744#[proc_macro_derive(Akp)]
6745pub fn derive_any_keypaths(input: TokenStream) -> TokenStream {
6746 let input = parse_macro_input!(input as DeriveInput);
6747 let name = &input.ident;
6748
6749 let kp_calls = match &input.data {
6750 Data::Struct(data_struct) => match &data_struct.fields {
6751 Fields::Named(fields_named) => {
6752 let calls: Vec<_> = fields_named
6753 .named
6754 .iter()
6755 .filter_map(|f| f.ident.as_ref())
6756 .map(|field_ident| {
6757 quote! { rust_key_paths::AKp::new(Self::#field_ident()) }
6758 })
6759 .collect();
6760 quote! { #(#calls),* }
6761 }
6762 Fields::Unnamed(unnamed) => {
6763 let calls: Vec<_> = (0..unnamed.unnamed.len())
6764 .map(|idx| {
6765 let kp_fn = format_ident!("f{}", idx);
6766 quote! { rust_key_paths::AKp::new(Self::#kp_fn()) }
6767 })
6768 .collect();
6769 quote! { #(#calls),* }
6770 }
6771 Fields::Unit => quote! {},
6772 },
6773 Data::Enum(data_enum) => {
6774 let calls: Vec<_> = data_enum
6775 .variants
6776 .iter()
6777 .map(|variant| {
6778 let v_ident = &variant.ident;
6779 let snake = format_ident!("{}", to_snake_case(&v_ident.to_string()));
6780 quote! { rust_key_paths::AKp::new(Self::#snake()) }
6781 })
6782 .collect();
6783 quote! { #(#calls),* }
6784 }
6785 Data::Union(_) => {
6786 return syn::Error::new(input.ident.span(), "Akp derive does not support unions")
6787 .to_compile_error()
6788 .into();
6789 }
6790 };
6791
6792 let expanded = quote! {
6793 impl #name {
6794 /// Returns a vec of all field keypaths as any keypaths (fully type-erased).
6795 #[inline(always)]
6796 pub fn any_kps() -> Vec<rust_key_paths::AKp> {
6797 vec![#kp_calls]
6798 }
6799 }
6800 };
6801
6802 TokenStream::from(expanded)
6803}