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