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