1use std::rc::Rc;
2use std::sync::{Arc, Mutex, RwLock};
3use std::cell::RefCell;
4
5pub trait WithContainer<Root, Value> {
9 fn with_arc<F, R>(self, arc: &Arc<Root>, f: F) -> R
12 where
13 F: FnOnce(&Value) -> R;
14
15 fn with_box<F, R>(self, boxed: &Box<Root>, f: F) -> R
18 where
19 F: FnOnce(&Value) -> R;
20
21 fn with_box_mut<F, R>(self, boxed: &mut Box<Root>, f: F) -> R
24 where
25 F: FnOnce(&mut Value) -> R;
26
27 fn with_rc<F, R>(self, rc: &Rc<Root>, f: F) -> R
30 where
31 F: FnOnce(&Value) -> R;
32
33 fn with_result<F, R, E>(self, result: &Result<Root, E>, f: F) -> Option<R>
36 where
37 F: FnOnce(&Value) -> R;
38
39 fn with_result_mut<F, R, E>(self, result: &mut Result<Root, E>, f: F) -> Option<R>
42 where
43 F: FnOnce(&mut Value) -> R;
44
45 fn with_option<F, R>(self, option: &Option<Root>, f: F) -> Option<R>
48 where
49 F: FnOnce(&Value) -> R;
50
51 fn with_option_mut<F, R>(self, option: &mut Option<Root>, f: F) -> Option<R>
54 where
55 F: FnOnce(&mut Value) -> R;
56
57 fn with_refcell<F, R>(self, refcell: &RefCell<Root>, f: F) -> Option<R>
60 where
61 F: FnOnce(&Value) -> R;
62
63 fn with_refcell_mut<F, R>(self, refcell: &RefCell<Root>, f: F) -> Option<R>
66 where
67 F: FnOnce(&mut Value) -> R;
68
69 fn with_mutex<F, R>(self, mutex: &Mutex<Root>, f: F) -> Option<R>
72 where
73 F: FnOnce(&Value) -> R;
74
75 fn with_mutex_mut<F, R>(self, mutex: &mut Mutex<Root>, f: F) -> Option<R>
78 where
79 F: FnOnce(&mut Value) -> R;
80
81 fn with_rwlock<F, R>(self, rwlock: &RwLock<Root>, f: F) -> Option<R>
84 where
85 F: FnOnce(&Value) -> R;
86
87 fn with_rwlock_mut<F, R>(self, rwlock: &mut RwLock<Root>, f: F) -> Option<R>
90 where
91 F: FnOnce(&mut Value) -> R;
92
93 fn with_arc_rwlock<F, R>(self, arc_rwlock: &Arc<RwLock<Root>>, f: F) -> Option<R>
96 where
97 F: FnOnce(&Value) -> R;
98
99 fn with_arc_rwlock_mut<F, R>(self, arc_rwlock: &Arc<RwLock<Root>>, f: F) -> Option<R>
102 where
103 F: FnOnce(&mut Value) -> R;
104}
105
106#[derive(Clone)]
107pub enum KeyPaths<Root, Value> {
110 Readable(Rc<dyn for<'a> Fn(&'a Root) -> &'a Value>),
111 ReadableEnum {
112 extract: Rc<dyn for<'a> Fn(&'a Root) -> Option<&'a Value>>,
113 embed: Rc<dyn Fn(Value) -> Root>,
114 },
115 FailableReadable(Rc<dyn for<'a> Fn(&'a Root) -> Option<&'a Value>>),
116
117 Writable(Rc<dyn for<'a> Fn(&'a mut Root) -> &'a mut Value>),
118 FailableWritable(Rc<dyn for<'a> Fn(&'a mut Root) -> Option<&'a mut Value>>),
119 WritableEnum {
120 extract: Rc<dyn for<'a> Fn(&'a Root) -> Option<&'a Value>>,
121 extract_mut: Rc<dyn for<'a> Fn(&'a mut Root) -> Option<&'a mut Value>>,
122 embed: Rc<dyn Fn(Value) -> Root>,
123 },
124
125
126
127 Owned(Rc<dyn Fn(Root) -> Value>),
129 FailableOwned(Rc<dyn Fn(Root) -> Option<Value>>),
130}
131
132impl<Root, Value> KeyPaths<Root, Value> {
133 #[inline]
134 pub fn readable(get: impl for<'a> Fn(&'a Root) -> &'a Value + 'static) -> Self {
135 Self::Readable(Rc::new(get))
136 }
137
138 #[inline]
139 pub fn writable(get_mut: impl for<'a> Fn(&'a mut Root) -> &'a mut Value + 'static) -> Self {
140 Self::Writable(Rc::new(get_mut))
141 }
142
143 #[inline]
144 pub fn failable_readable(
145 get: impl for<'a> Fn(&'a Root) -> Option<&'a Value> + 'static,
146 ) -> Self {
147 Self::FailableReadable(Rc::new(get))
148 }
149
150 #[inline]
151 pub fn failable_writable(
152 get_mut: impl for<'a> Fn(&'a mut Root) -> Option<&'a mut Value> + 'static,
153 ) -> Self {
154 Self::FailableWritable(Rc::new(get_mut))
155 }
156
157 #[inline]
158 pub fn readable_enum(
159 embed: impl Fn(Value) -> Root + 'static,
160 extract: impl for<'a> Fn(&'a Root) -> Option<&'a Value> + 'static,
161 ) -> Self {
162 Self::ReadableEnum {
163 extract: Rc::new(extract),
164 embed: Rc::new(embed),
165 }
166 }
167
168 #[inline]
169 pub fn writable_enum(
170 embed: impl Fn(Value) -> Root + 'static,
171 extract: impl for<'a> Fn(&'a Root) -> Option<&'a Value> + 'static,
172 extract_mut: impl for<'a> Fn(&'a mut Root) -> Option<&'a mut Value> + 'static,
173 ) -> Self {
174 Self::WritableEnum {
175 extract: Rc::new(extract),
176 embed: Rc::new(embed),
177 extract_mut: Rc::new(extract_mut),
178 }
179 }
180
181
182 #[inline]
184 pub fn owned(get: impl Fn(Root) -> Value + 'static) -> Self {
185 Self::Owned(Rc::new(get))
186 }
187
188 #[inline]
189 pub fn failable_owned(get: impl Fn(Root) -> Option<Value> + 'static) -> Self {
190 Self::FailableOwned(Rc::new(get))
191 }
192
193 #[inline]
194 pub fn owned_writable(get: impl Fn(Root) -> Value + 'static) -> Self {
195 Self::Owned(Rc::new(get))
196 }
197
198 #[inline]
199 pub fn failable_owned_writable(get: impl Fn(Root) -> Option<Value> + 'static) -> Self {
200 Self::FailableOwned(Rc::new(get))
201 }
202}
203
204impl<Root, Value> KeyPaths<Root, Value> {
205 #[inline]
207 pub fn get<'a>(&'a self, root: &'a Root) -> Option<&'a Value> {
208 match self {
209 KeyPaths::Readable(f) => Some(f(root)),
210 KeyPaths::Writable(_) => None, KeyPaths::FailableReadable(f) => f(root),
212 KeyPaths::FailableWritable(_) => None, KeyPaths::ReadableEnum { extract, .. } => extract(root),
214 KeyPaths::WritableEnum { extract, .. } => extract(root),
215 KeyPaths::Owned(_) => None, KeyPaths::FailableOwned(_) => None, }
219 }
220
221 #[inline]
224 pub fn get_ref<'a, 'b>(&'a self, root: &'b &Root) -> Option<&'b Value>
225 where
226 'a: 'b,
227 {
228 self.get(*root)
229 }
230
231 #[inline]
233 pub fn get_mut<'a>(&'a self, root: &'a mut Root) -> Option<&'a mut Value> {
234 match self {
235 KeyPaths::Readable(_) => None, KeyPaths::Writable(f) => Some(f(root)),
237 KeyPaths::FailableReadable(_) => None, KeyPaths::FailableWritable(f) => f(root),
239 KeyPaths::ReadableEnum { .. } => None, KeyPaths::WritableEnum { extract_mut, .. } => extract_mut(root),
241 KeyPaths::Owned(_) => None, KeyPaths::FailableOwned(_) => None, }
245 }
246
247 #[inline]
250 pub fn get_mut_ref<'a, 'b>(&'a self, root: &'b mut &mut Root) -> Option<&'b mut Value>
251 where
252 'a: 'b,
253 {
254 self.get_mut(*root)
255 }
256
257 #[inline]
264 pub fn for_arc(self) -> KeyPaths<Arc<Root>, Value>
265 where
266 Root: 'static,
267 Value: 'static,
268 {
269 match self {
270 KeyPaths::Readable(f) => KeyPaths::Readable(Rc::new(move |root: &Arc<Root>| {
271 f(&**root)
272 })),
273 KeyPaths::Writable(_) => {
274 panic!("Cannot create writable keypath for Arc (Arc is immutable)")
276 }
277 KeyPaths::FailableReadable(f) => {
278 KeyPaths::FailableReadable(Rc::new(move |root: &Arc<Root>| f(&**root)))
279 }
280 KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
281 extract: Rc::new(move |root: &Arc<Root>| extract(&**root)),
282 embed: Rc::new(move |value| Arc::new(embed(value))),
283 },
284 other => panic!("Unsupported keypath variant for Arc adapter: {:?}", kind_name(&other)),
285 }
286 }
287
288 #[inline]
291 pub fn for_box(self) -> KeyPaths<Box<Root>, Value>
292 where
293 Root: 'static,
294 Value: 'static,
295 {
296 match self {
297 KeyPaths::Readable(f) => KeyPaths::Readable(Rc::new(move |root: &Box<Root>| {
298 f(&**root)
299 })),
300 KeyPaths::Writable(f) => KeyPaths::Writable(Rc::new(move |root: &mut Box<Root>| {
301 f(&mut **root)
302 })),
303 KeyPaths::FailableReadable(f) => {
304 KeyPaths::FailableReadable(Rc::new(move |root: &Box<Root>| f(&**root)))
305 }
306 KeyPaths::FailableWritable(f) => {
307 KeyPaths::FailableWritable(Rc::new(move |root: &mut Box<Root>| f(&mut **root)))
308 }
309 KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
310 extract: Rc::new(move |root: &Box<Root>| extract(&**root)),
311 embed: Rc::new(move |value| Box::new(embed(value))),
312 },
313 KeyPaths::WritableEnum { extract, extract_mut, embed } => KeyPaths::WritableEnum {
314 extract: Rc::new(move |root: &Box<Root>| extract(&**root)),
315 extract_mut: Rc::new(move |root: &mut Box<Root>| extract_mut(&mut **root)),
316 embed: Rc::new(move |value| Box::new(embed(value))),
317 },
318 other => panic!("Unsupported keypath variant for Box adapter: {:?}", kind_name(&other)),
319 }
320 }
321
322 #[inline]
325 pub fn for_rc(self) -> KeyPaths<Rc<Root>, Value>
326 where
327 Root: 'static,
328 Value: 'static,
329 {
330 match self {
331 KeyPaths::Readable(f) => KeyPaths::Readable(Rc::new(move |root: &Rc<Root>| {
332 f(&**root)
333 })),
334 KeyPaths::Writable(_) => {
335 panic!("Cannot create writable keypath for Rc (Rc is immutable)")
337 }
338 KeyPaths::FailableReadable(f) => {
339 KeyPaths::FailableReadable(Rc::new(move |root: &Rc<Root>| f(&**root)))
340 }
341 KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
342 extract: Rc::new(move |root: &Rc<Root>| extract(&**root)),
343 embed: Rc::new(move |value| Rc::new(embed(value))),
344 },
345 other => panic!("Unsupported keypath variant for Rc adapter: {:?}", kind_name(&other)),
346 }
347 }
348
349 #[inline]
353 pub fn for_result<E>(self) -> KeyPaths<Result<Root, E>, Value>
354 where
355 Root: 'static,
356 Value: 'static,
357 E: 'static,
358 {
359 match self {
360 KeyPaths::Readable(f) => KeyPaths::FailableReadable(Rc::new(move |root: &Result<Root, E>| {
361 root.as_ref().ok().map(|r| f(r))
362 })),
363 KeyPaths::Writable(f) => KeyPaths::FailableWritable(Rc::new(move |root: &mut Result<Root, E>| {
364 root.as_mut().ok().map(|r| f(r))
365 })),
366 KeyPaths::FailableReadable(f) => {
367 KeyPaths::FailableReadable(Rc::new(move |root: &Result<Root, E>| {
368 root.as_ref().ok().and_then(|r| f(r))
369 }))
370 }
371 KeyPaths::FailableWritable(f) => {
372 KeyPaths::FailableWritable(Rc::new(move |root: &mut Result<Root, E>| {
373 root.as_mut().ok().and_then(|r| f(r))
374 }))
375 }
376 KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
377 extract: Rc::new(move |root: &Result<Root, E>| {
378 root.as_ref().ok().and_then(|r| extract(r))
379 }),
380 embed: Rc::new(move |value| Ok(embed(value))),
381 },
382 KeyPaths::WritableEnum { extract, extract_mut, embed } => KeyPaths::WritableEnum {
383 extract: Rc::new(move |root: &Result<Root, E>| {
384 root.as_ref().ok().and_then(|r| extract(r))
385 }),
386 extract_mut: Rc::new(move |root: &mut Result<Root, E>| {
387 root.as_mut().ok().and_then(|r| extract_mut(r))
388 }),
389 embed: Rc::new(move |value| Ok(embed(value))),
390 },
391 other => panic!("Unsupported keypath variant for Result adapter: {:?}", kind_name(&other)),
392 }
393 }
394
395 #[inline]
399 pub fn for_option(self) -> KeyPaths<Option<Root>, Value>
400 where
401 Root: 'static,
402 Value: 'static,
403 {
404 match self {
405 KeyPaths::Readable(f) => KeyPaths::FailableReadable(Rc::new(move |root: &Option<Root>| {
406 root.as_ref().map(|r| f(r))
407 })),
408 KeyPaths::Writable(f) => KeyPaths::FailableWritable(Rc::new(move |root: &mut Option<Root>| {
409 root.as_mut().map(|r| f(r))
410 })),
411 KeyPaths::FailableReadable(f) => {
412 KeyPaths::FailableReadable(Rc::new(move |root: &Option<Root>| {
413 root.as_ref().and_then(|r| f(r))
414 }))
415 }
416 KeyPaths::FailableWritable(f) => {
417 KeyPaths::FailableWritable(Rc::new(move |root: &mut Option<Root>| {
418 root.as_mut().and_then(|r| f(r))
419 }))
420 }
421 KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
422 extract: Rc::new(move |root: &Option<Root>| {
423 root.as_ref().and_then(|r| extract(r))
424 }),
425 embed: Rc::new(move |value| Some(embed(value))),
426 },
427 KeyPaths::WritableEnum { extract, extract_mut, embed } => KeyPaths::WritableEnum {
428 extract: Rc::new(move |root: &Option<Root>| {
429 root.as_ref().and_then(|r| extract(r))
430 }),
431 extract_mut: Rc::new(move |root: &mut Option<Root>| {
432 root.as_mut().and_then(|r| extract_mut(r))
433 }),
434 embed: Rc::new(move |value| Some(embed(value))),
435 },
436 other => panic!("Unsupported keypath variant for Option adapter: {:?}", kind_name(&other)),
437 }
438 }
439
440 #[inline]
444 pub fn for_arc_rwlock(self) -> KeyPaths<Arc<RwLock<Root>>, Value>
445 where
446 Root: 'static,
447 Value: Clone + 'static,
448 {
449 match self {
450 KeyPaths::Readable(f) => KeyPaths::FailableOwned(Rc::new(move |root: Arc<RwLock<Root>>| {
451 let guard = root.read().ok()?;
452 Some(f(&*guard).clone())
453 })),
454 KeyPaths::Writable(_) => {
455 panic!("Cannot create writable keypath for Arc<RwLock> (use with_arc_rwlock_mut instead)")
457 }
458 KeyPaths::FailableReadable(f) => {
459 KeyPaths::FailableOwned(Rc::new(move |root: Arc<RwLock<Root>>| {
460 let guard = root.read().ok()?;
461 f(&*guard).map(|v| v.clone())
462 }))
463 }
464 KeyPaths::ReadableEnum { extract, embed: _ } => KeyPaths::FailableOwned(Rc::new(move |root: Arc<RwLock<Root>>| {
465 let guard = root.read().ok()?;
466 extract(&*guard).map(|v| v.clone())
467 })),
468 other => panic!("Unsupported keypath variant for Arc<RwLock> adapter: {:?}", kind_name(&other)),
469 }
470 }
471
472 #[inline]
476 pub fn for_arc_mutex(self) -> KeyPaths<Arc<Mutex<Root>>, Value>
477 where
478 Root: 'static,
479 Value: Clone + 'static,
480 {
481 match self {
482 KeyPaths::Readable(f) => KeyPaths::FailableOwned(Rc::new(move |root: Arc<Mutex<Root>>| {
483 let guard = root.lock().ok()?;
484 Some(f(&*guard).clone())
485 })),
486 KeyPaths::Writable(_) => {
487 panic!("Cannot create writable keypath for Arc<Mutex> (use with_arc_mutex_mut instead)")
489 }
490 KeyPaths::FailableReadable(f) => {
491 KeyPaths::FailableOwned(Rc::new(move |root: Arc<Mutex<Root>>| {
492 let guard = root.lock().ok()?;
493 f(&*guard).map(|v| v.clone())
494 }))
495 }
496 KeyPaths::ReadableEnum { extract, embed: _ } => KeyPaths::FailableOwned(Rc::new(move |root: Arc<Mutex<Root>>| {
497 let guard = root.lock().ok()?;
498 extract(&*guard).map(|v| v.clone())
499 })),
500 other => panic!("Unsupported keypath variant for Arc<Mutex> adapter: {:?}", kind_name(&other)),
501 }
502 }
503
504 #[cfg(feature = "parking_lot")]
509 #[inline]
510 pub fn for_arc_parking_mutex(self) -> KeyPaths<Arc<parking_lot::Mutex<Root>>, Value>
511 where
512 Root: 'static,
513 Value: Clone + 'static,
514 {
515 match self {
516 KeyPaths::Readable(f) => KeyPaths::FailableOwned(Rc::new(move |root: Arc<parking_lot::Mutex<Root>>| {
517 let guard = root.lock();
518 Some(f(&*guard).clone())
519 })),
520 KeyPaths::Writable(_) => {
521 panic!("Cannot create writable keypath for Arc<parking_lot::Mutex> (use with_arc_parking_mutex_mut instead)")
523 }
524 KeyPaths::FailableReadable(f) => {
525 KeyPaths::FailableOwned(Rc::new(move |root: Arc<parking_lot::Mutex<Root>>| {
526 let guard = root.lock();
527 f(&*guard).map(|v| v.clone())
528 }))
529 }
530 KeyPaths::ReadableEnum { extract, embed: _ } => KeyPaths::FailableOwned(Rc::new(move |root: Arc<parking_lot::Mutex<Root>>| {
531 let guard = root.lock();
532 extract(&*guard).map(|v| v.clone())
533 })),
534 other => panic!("Unsupported keypath variant for Arc<parking_lot::Mutex> adapter: {:?}", kind_name(&other)),
535 }
536 }
537
538 #[cfg(feature = "parking_lot")]
543 #[inline]
544 pub fn for_arc_parking_rwlock(self) -> KeyPaths<Arc<parking_lot::RwLock<Root>>, Value>
545 where
546 Root: 'static,
547 Value: Clone + 'static,
548 {
549 match self {
550 KeyPaths::Readable(f) => KeyPaths::FailableOwned(Rc::new(move |root: Arc<parking_lot::RwLock<Root>>| {
551 let guard = root.read();
552 Some(f(&*guard).clone())
553 })),
554 KeyPaths::Writable(_) => {
555 panic!("Cannot create writable keypath for Arc<parking_lot::RwLock> (use with_arc_parking_rwlock_mut instead)")
557 }
558 KeyPaths::FailableReadable(f) => {
559 KeyPaths::FailableOwned(Rc::new(move |root: Arc<parking_lot::RwLock<Root>>| {
560 let guard = root.read();
561 f(&*guard).map(|v| v.clone())
562 }))
563 }
564 KeyPaths::ReadableEnum { extract, embed: _ } => KeyPaths::FailableOwned(Rc::new(move |root: Arc<parking_lot::RwLock<Root>>| {
565 let guard = root.read();
566 extract(&*guard).map(|v| v.clone())
567 })),
568 other => panic!("Unsupported keypath variant for Arc<parking_lot::RwLock> adapter: {:?}", kind_name(&other)),
569 }
570 }
571
572 pub fn embed(&self, value: Value) -> Option<Root>
576 where
577 Value: Clone,
578 {
579 match self {
580 KeyPaths::ReadableEnum { embed, .. } => Some(embed(value)),
581 _ => None,
582 }
583 }
584
585 pub fn embed_mut(&self, value: Value) -> Option<Root>
586 where
587 Value: Clone,
588 {
589 match self {
590 KeyPaths::WritableEnum { embed, .. } => Some(embed(value)),
591 _ => None,
592 }
593 }
594
595
596 #[inline]
600 pub fn get_owned(self, root: Root) -> Value {
601 match self {
602 KeyPaths::Owned(f) => f(root),
603 _ => panic!("get_owned only works with owned keypaths"),
604 }
605 }
606
607 #[inline]
609 pub fn get_failable_owned(self, root: Root) -> Option<Value> {
610 match self {
611 KeyPaths::FailableOwned(f) => f(root),
612 _ => panic!("get_failable_owned only works with failable owned keypaths"),
613 }
614 }
615
616 pub fn iter<'a, T>(&'a self, root: &'a Root) -> Option<<&'a Value as IntoIterator>::IntoIter>
618 where
619 &'a Value: IntoIterator<Item = &'a T>,
620 T: 'a,
621 {
622 self.get(root).map(|v| v.into_iter())
623 }
624
625 pub fn iter_mut<'a, T>(
627 &'a self,
628 root: &'a mut Root,
629 ) -> Option<<&'a mut Value as IntoIterator>::IntoIter>
630 where
631 &'a mut Value: IntoIterator<Item = &'a mut T>,
632 T: 'a,
633 {
634 self.get_mut(root).map(|v| v.into_iter())
635 }
636
637 #[inline]
639 pub fn into_iter<T>(self, root: Root) -> Option<<Value as IntoIterator>::IntoIter>
640 where
641 Value: IntoIterator<Item = T> + Clone,
642 {
643 match self {
644 KeyPaths::Readable(f) => Some(f(&root).clone().into_iter()), KeyPaths::Writable(_) => None,
646 KeyPaths::FailableReadable(f) => f(&root).map(|v| v.clone().into_iter()),
647 KeyPaths::FailableWritable(_) => None,
648 KeyPaths::ReadableEnum { extract, .. } => extract(&root).map(|v| v.clone().into_iter()),
649 KeyPaths::WritableEnum { extract, .. } => extract(&root).map(|v| v.clone().into_iter()),
650 KeyPaths::Owned(f) => Some(f(root).into_iter()),
652 KeyPaths::FailableOwned(f) => f(root).map(|v| v.into_iter()),
653 }
654 }
655}
656
657impl<Root, Value> WithContainer<Root, Value> for KeyPaths<Root, Value> {
659 #[inline]
662 fn with_arc<F, R>(self, arc: &Arc<Root>, f: F) -> R
663 where
664 F: FnOnce(&Value) -> R,
665 {
666 match self {
667 KeyPaths::Readable(get) => f(get(&**arc)),
668 KeyPaths::FailableReadable(get) => {
669 if let Some(value) = get(&**arc) {
670 f(value)
671 } else {
672 panic!("FailableReadable keypath returned None for Arc")
673 }
674 }
675 _ => panic!("with_arc only works with readable keypaths"),
676 }
677 }
678
679 #[inline]
682 fn with_box<F, R>(self, boxed: &Box<Root>, f: F) -> R
683 where
684 F: FnOnce(&Value) -> R,
685 {
686 match self {
687 KeyPaths::Readable(get) => f(get(&**boxed)),
688 KeyPaths::FailableReadable(get) => {
689 if let Some(value) = get(&**boxed) {
690 f(value)
691 } else {
692 panic!("FailableReadable keypath returned None for Box")
693 }
694 }
695 _ => panic!("with_box only works with readable keypaths"),
696 }
697 }
698
699 #[inline]
702 fn with_box_mut<F, R>(self, boxed: &mut Box<Root>, f: F) -> R
703 where
704 F: FnOnce(&mut Value) -> R,
705 {
706 match self {
707 KeyPaths::Writable(get) => f(get(&mut **boxed)),
708 KeyPaths::FailableWritable(get) => {
709 if let Some(value) = get(&mut **boxed) {
710 f(value)
711 } else {
712 panic!("FailableWritable keypath returned None for Box")
713 }
714 }
715 _ => panic!("with_box_mut only works with writable keypaths"),
716 }
717 }
718
719 #[inline]
722 fn with_rc<F, R>(self, rc: &Rc<Root>, f: F) -> R
723 where
724 F: FnOnce(&Value) -> R,
725 {
726 match self {
727 KeyPaths::Readable(get) => f(get(&**rc)),
728 KeyPaths::FailableReadable(get) => {
729 if let Some(value) = get(&**rc) {
730 f(value)
731 } else {
732 panic!("FailableReadable keypath returned None for Rc")
733 }
734 }
735 _ => panic!("with_rc only works with readable keypaths"),
736 }
737 }
738
739 #[inline]
742 fn with_result<F, R, E>(self, result: &Result<Root, E>, f: F) -> Option<R>
743 where
744 F: FnOnce(&Value) -> R,
745 {
746 match self {
747 KeyPaths::Readable(get) => {
748 result.as_ref().ok().map(|root| f(get(root)))
749 }
750 KeyPaths::FailableReadable(get) => {
751 result.as_ref().ok().and_then(|root| get(root).map(|v| f(v)))
752 }
753 _ => panic!("with_result only works with readable keypaths"),
754 }
755 }
756
757 #[inline]
760 fn with_result_mut<F, R, E>(self, result: &mut Result<Root, E>, f: F) -> Option<R>
761 where
762 F: FnOnce(&mut Value) -> R,
763 {
764 match self {
765 KeyPaths::Writable(get) => {
766 result.as_mut().ok().map(|root| f(get(root)))
767 }
768 KeyPaths::FailableWritable(get) => {
769 result.as_mut().ok().and_then(|root| get(root).map(|v| f(v)))
770 }
771 _ => panic!("with_result_mut only works with writable keypaths"),
772 }
773 }
774
775 #[inline]
778 fn with_option<F, R>(self, option: &Option<Root>, f: F) -> Option<R>
779 where
780 F: FnOnce(&Value) -> R,
781 {
782 match self {
783 KeyPaths::Readable(get) => {
784 option.as_ref().map(|root| f(get(root)))
785 }
786 KeyPaths::FailableReadable(get) => {
787 option.as_ref().and_then(|root| get(root).map(|v| f(v)))
788 }
789 _ => panic!("with_option only works with readable keypaths"),
790 }
791 }
792
793 #[inline]
796 fn with_option_mut<F, R>(self, option: &mut Option<Root>, f: F) -> Option<R>
797 where
798 F: FnOnce(&mut Value) -> R,
799 {
800 match self {
801 KeyPaths::Writable(get) => {
802 option.as_mut().map(|root| f(get(root)))
803 }
804 KeyPaths::FailableWritable(get) => {
805 option.as_mut().and_then(|root| get(root).map(|v| f(v)))
806 }
807 _ => panic!("with_option_mut only works with writable keypaths"),
808 }
809 }
810
811 #[inline]
814 fn with_refcell<F, R>(self, refcell: &RefCell<Root>, f: F) -> Option<R>
815 where
816 F: FnOnce(&Value) -> R,
817 {
818 match self {
819 KeyPaths::Readable(get) => {
820 refcell.try_borrow().ok().map(|borrow| f(get(&*borrow)))
821 }
822 KeyPaths::FailableReadable(get) => {
823 refcell.try_borrow().ok().and_then(|borrow| get(&*borrow).map(|v| f(v)))
824 }
825 _ => panic!("with_refcell only works with readable keypaths"),
826 }
827 }
828
829 #[inline]
832 fn with_refcell_mut<F, R>(self, refcell: &RefCell<Root>, f: F) -> Option<R>
833 where
834 F: FnOnce(&mut Value) -> R,
835 {
836 match self {
837 KeyPaths::Writable(get) => {
838 refcell.try_borrow_mut().ok().map(|mut borrow| f(get(&mut *borrow)))
839 }
840 KeyPaths::FailableWritable(get) => {
841 refcell.try_borrow_mut().ok().and_then(|mut borrow| get(&mut *borrow).map(|v| f(v)))
842 }
843 _ => panic!("with_refcell_mut only works with writable keypaths"),
844 }
845 }
846
847 #[inline]
850 fn with_mutex<F, R>(self, mutex: &Mutex<Root>, f: F) -> Option<R>
851 where
852 F: FnOnce(&Value) -> R,
853 {
854 match self {
855 KeyPaths::Readable(get) => {
856 mutex.try_lock().ok().map(|guard| f(get(&*guard)))
857 }
858 KeyPaths::FailableReadable(get) => {
859 mutex.try_lock().ok().and_then(|guard| get(&*guard).map(|v| f(v)))
860 }
861 _ => panic!("with_mutex only works with readable keypaths"),
862 }
863 }
864
865 #[inline]
868 fn with_mutex_mut<F, R>(self, mutex: &mut Mutex<Root>, f: F) -> Option<R>
869 where
870 F: FnOnce(&mut Value) -> R,
871 {
872 match self {
873 KeyPaths::Writable(get) => {
874 mutex.try_lock().ok().map(|mut guard| f(get(&mut *guard)))
875 }
876 KeyPaths::FailableWritable(get) => {
877 mutex.try_lock().ok().and_then(|mut guard| get(&mut *guard).map(|v| f(v)))
878 }
879 _ => panic!("with_mutex_mut only works with writable keypaths"),
880 }
881 }
882
883 #[inline]
886 fn with_rwlock<F, R>(self, rwlock: &RwLock<Root>, f: F) -> Option<R>
887 where
888 F: FnOnce(&Value) -> R,
889 {
890 match self {
891 KeyPaths::Readable(get) => {
892 rwlock.try_read().ok().map(|guard| f(get(&*guard)))
893 }
894 KeyPaths::FailableReadable(get) => {
895 rwlock.try_read().ok().and_then(|guard| get(&*guard).map(|v| f(v)))
896 }
897 _ => panic!("with_rwlock only works with readable keypaths"),
898 }
899 }
900
901 #[inline]
904 fn with_rwlock_mut<F, R>(self, rwlock: &mut RwLock<Root>, f: F) -> Option<R>
905 where
906 F: FnOnce(&mut Value) -> R,
907 {
908 match self {
909 KeyPaths::Writable(get) => {
910 rwlock.try_write().ok().map(|mut guard| f(get(&mut *guard)))
911 }
912 KeyPaths::FailableWritable(get) => {
913 rwlock.try_write().ok().and_then(|mut guard| get(&mut *guard).map(|v| f(v)))
914 }
915 _ => panic!("with_rwlock_mut only works with writable keypaths"),
916 }
917 }
918
919 fn with_arc_rwlock<F, R>(self, arc_rwlock: &Arc<RwLock<Root>>, f: F) -> Option<R>
922 where
923 F: FnOnce(&Value) -> R,
924 {
925 match self {
926 KeyPaths::Readable(get) => {
927 arc_rwlock.try_read().ok().map(|guard| f(get(&*guard)))
928 }
929 KeyPaths::FailableReadable(get) => {
930 arc_rwlock.try_read().ok().and_then(|guard| get(&*guard).map(|v| f(v)))
931 }
932 _ => panic!("with_arc_rwlock only works with readable keypaths"),
933 }
934 }
935
936 fn with_arc_rwlock_mut<F, R>(self, arc_rwlock: &Arc<RwLock<Root>>, f: F) -> Option<R>
939 where
940 F: FnOnce(&mut Value) -> R,
941 {
942 match self {
943 KeyPaths::Writable(get) => {
944 arc_rwlock.try_write().ok().map(|mut guard| f(get(&mut *guard)))
945 }
946 KeyPaths::FailableWritable(get) => {
947 arc_rwlock.try_write().ok().and_then(|mut guard| get(&mut *guard).map(|v| f(v)))
948 }
949 _ => panic!("with_arc_rwlock_mut only works with writable keypaths"),
950 }
951 }
952}
953
954impl<Root, Mid> KeyPaths<Root, Mid>
955where
956 Root: 'static,
957 Mid: 'static,
958{
959 #[inline]
961 pub fn then<Value>(self, mid: KeyPaths<Mid, Value>) -> KeyPaths<Root, Value>
962 where
963 Value: 'static,
964 {
965 self.compose(mid)
966 }
967
968 pub fn compose<Value>(self, mid: KeyPaths<Mid, Value>) -> KeyPaths<Root, Value>
969 where
970 Value: 'static,
971 {
972 use KeyPaths::*;
973
974 match (self, mid) {
975 (Readable(f1), Readable(f2)) => Readable(Rc::new(move |r| f2(f1(r)))),
976
977 (Writable(f1), Writable(f2)) => Writable(Rc::new(move |r| f2(f1(r)))),
978
979 (FailableReadable(f1), Readable(f2)) => {
980 FailableReadable(Rc::new(move |r| f1(r).map(|m| f2(m))))
981 }
982
983 (Readable(f1), FailableReadable(f2)) => FailableReadable(Rc::new(move |r| f2(f1(r)))),
984
985 (FailableReadable(f1), FailableReadable(f2)) => {
986 FailableReadable(Rc::new(move |r| f1(r).and_then(|m| f2(m))))
987 }
988
989 (FailableWritable(f1), Writable(f2)) => {
990 FailableWritable(Rc::new(move |r| f1(r).map(|m| f2(m))))
991 }
992
993 (Writable(f1), FailableWritable(f2)) => FailableWritable(Rc::new(move |r| f2(f1(r)))),
994
995 (FailableWritable(f1), FailableWritable(f2)) => {
996 FailableWritable(Rc::new(move |r| f1(r).and_then(|m| f2(m))))
997 }
998 (FailableReadable(f1), ReadableEnum { extract, .. }) => {
999 FailableReadable(Rc::new(move |r| f1(r).and_then(|m| extract(m))))
1000 }
1001 (ReadableEnum { extract, .. }, Readable(f2)) => {
1005 FailableReadable(Rc::new(move |r| extract(r).map(|m| f2(m))))
1006 }
1007
1008 (ReadableEnum { extract, .. }, FailableReadable(f2)) => {
1009 FailableReadable(Rc::new(move |r| extract(r).and_then(|m| f2(m))))
1010 }
1011
1012 (WritableEnum { extract, .. }, Readable(f2)) => {
1013 FailableReadable(Rc::new(move |r| extract(r).map(|m| f2(m))))
1014 }
1015
1016 (WritableEnum { extract, .. }, FailableReadable(f2)) => {
1017 FailableReadable(Rc::new(move |r| extract(r).and_then(|m| f2(m))))
1018 }
1019
1020 (WritableEnum { extract_mut, .. }, Writable(f2)) => {
1021 FailableWritable(Rc::new(move |r| extract_mut(r).map(|m| f2(m))))
1022 }
1023
1024 (
1025 FailableWritable(f_root_mid),
1026 WritableEnum {
1027 extract_mut: exm_mid_val,
1028 ..
1029 },
1030 ) => {
1031 FailableWritable(Rc::new(move |r: &mut Root| {
1032 let intermediate_mid_ref = f_root_mid(r);
1035
1036 intermediate_mid_ref.and_then(|intermediate_mid| exm_mid_val(intermediate_mid))
1039 }))
1040 }
1041
1042 (WritableEnum { extract_mut, .. }, FailableWritable(f2)) => {
1043 FailableWritable(Rc::new(move |r| extract_mut(r).and_then(|m| f2(m))))
1044 }
1045
1046 (Writable(f1), WritableEnum { extract_mut, .. }) => {
1048 FailableWritable(Rc::new(move |r: &mut Root| {
1049 let mid: &mut Mid = f1(r);
1050 extract_mut(mid)
1051 }))
1052 }
1053
1054 (
1055 ReadableEnum {
1056 extract: ex1,
1057 embed: em1,
1058 },
1059 ReadableEnum {
1060 extract: ex2,
1061 embed: em2,
1062 },
1063 ) => ReadableEnum {
1064 extract: Rc::new(move |r| ex1(r).and_then(|m| ex2(m))),
1065 embed: Rc::new(move |v| em1(em2(v))),
1066 },
1067
1068 (
1069 WritableEnum {
1070 extract: ex1,
1071 extract_mut: _,
1072 embed: em1,
1073 },
1074 ReadableEnum {
1075 extract: ex2,
1076 embed: em2,
1077 },
1078 ) => ReadableEnum {
1079 extract: Rc::new(move |r| ex1(r).and_then(|m| ex2(m))),
1080 embed: Rc::new(move |v| em1(em2(v))),
1081 },
1082
1083 (
1084 WritableEnum {
1085 extract: ex1,
1086 extract_mut: exm1,
1087 embed: em1,
1088 },
1089 WritableEnum {
1090 extract: ex2,
1091 extract_mut: exm2,
1092 embed: em2,
1093 },
1094 ) => WritableEnum {
1095 extract: Rc::new(move |r| ex1(r).and_then(|m| ex2(m))),
1096 extract_mut: Rc::new(move |r| exm1(r).and_then(|m| exm2(m))),
1097 embed: Rc::new(move |v| em1(em2(v))),
1098 },
1099
1100
1101 (Owned(f1), Owned(f2)) => {
1103 Owned(Rc::new(move |r| f2(f1(r))))
1104 }
1105 (FailableOwned(f1), Owned(f2)) => {
1106 FailableOwned(Rc::new(move |r| f1(r).map(|m| f2(m))))
1107 }
1108 (Owned(f1), FailableOwned(f2)) => {
1109 FailableOwned(Rc::new(move |r| f2(f1(r))))
1110 }
1111 (FailableOwned(f1), FailableOwned(f2)) => {
1112 FailableOwned(Rc::new(move |r| f1(r).and_then(|m| f2(m))))
1113 }
1114
1115 (a, b) => panic!(
1120 "Unsupported composition: {:?} then {:?}",
1121 kind_name(&a),
1122 kind_name(&b)
1123 ),
1124 }
1125 }
1126
1127 #[inline]
1129 pub fn kind_name(&self) -> &'static str {
1130 kind_name(self)
1131 }
1132}
1133
1134fn kind_name<Root, Value>(k: &KeyPaths<Root, Value>) -> &'static str {
1135 use KeyPaths::*;
1136 match k {
1137 Readable(_) => "Readable",
1138 Writable(_) => "Writable",
1139 FailableReadable(_) => "FailableReadable",
1140 FailableWritable(_) => "FailableWritable",
1141 ReadableEnum { .. } => "ReadableEnum",
1142 WritableEnum { .. } => "WritableEnum",
1143 Owned(_) => "Owned",
1145 FailableOwned(_) => "FailableOwned",
1146 }
1147}
1148
1149pub fn compose<Root, Mid, Value>(
1158 kp1: KeyPaths<Root, Mid>,
1159 kp2: KeyPaths<Mid, Value>,
1160) -> KeyPaths<Root, Value>
1161where
1162 Root: 'static,
1163 Mid: 'static,
1164 Value: 'static,
1165{
1166 kp1.compose(kp2)
1167}
1168
1169#[macro_export]
1172macro_rules! readable_enum_macro {
1173 ($enum:path, $variant:ident) => {{
1175 $crate::KeyPaths::readable_enum(
1176 |_| <$enum>::$variant,
1177 |e: &$enum| match e {
1178 <$enum>::$variant => Some(&()),
1179 _ => None,
1180 },
1181 )
1182 }};
1183 ($enum:path, $variant:ident($inner:ty)) => {{
1185 $crate::KeyPaths::readable_enum(
1186 |v: $inner| <$enum>::$variant(v),
1187 |e: &$enum| match e {
1188 <$enum>::$variant(v) => Some(v),
1189 _ => None,
1190 },
1191 )
1192 }};
1193}
1194
1195#[macro_export]
1196macro_rules! writable_enum_macro {
1197 ($enum:path, $variant:ident) => {{
1199 $crate::KeyPaths::writable_enum(
1200 |_| <$enum>::$variant,
1201 |e: &$enum| match e {
1202 <$enum>::$variant => Some(&()),
1203 _ => None,
1204 },
1205 |e: &mut $enum| match e {
1206 <$enum>::$variant => Some(&mut ()),
1207 _ => None,
1208 },
1209 )
1210 }};
1211 ($enum:path, $variant:ident($inner:ty)) => {{
1213 $crate::KeyPaths::writable_enum(
1214 |v: $inner| <$enum>::$variant(v),
1215 |e: &$enum| match e {
1216 <$enum>::$variant(v) => Some(v),
1217 _ => None,
1218 },
1219 |e: &mut $enum| match e {
1220 <$enum>::$variant(v) => Some(v),
1221 _ => None,
1222 },
1223 )
1224 }};
1225}