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