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
94#[derive(Clone)]
95pub enum KeyPaths<Root, Value> {
98 Readable(Rc<dyn for<'a> Fn(&'a Root) -> &'a Value>),
99 ReadableEnum {
100 extract: Rc<dyn for<'a> Fn(&'a Root) -> Option<&'a Value>>,
101 embed: Rc<dyn Fn(Value) -> Root>,
102 },
103 FailableReadable(Rc<dyn for<'a> Fn(&'a Root) -> Option<&'a Value>>),
104
105 Writable(Rc<dyn for<'a> Fn(&'a mut Root) -> &'a mut Value>),
106 FailableWritable(Rc<dyn for<'a> Fn(&'a mut Root) -> Option<&'a mut Value>>),
107 WritableEnum {
108 extract: Rc<dyn for<'a> Fn(&'a Root) -> Option<&'a Value>>,
109 extract_mut: Rc<dyn for<'a> Fn(&'a mut Root) -> Option<&'a mut Value>>,
110 embed: Rc<dyn Fn(Value) -> Root>,
111 },
112
113
114
115 Owned(Rc<dyn Fn(Root) -> Value>),
117 FailableOwned(Rc<dyn Fn(Root) -> Option<Value>>),
118}
119
120impl<Root, Value> KeyPaths<Root, Value> {
121 #[inline]
122 pub fn readable(get: impl for<'a> Fn(&'a Root) -> &'a Value + 'static) -> Self {
123 Self::Readable(Rc::new(get))
124 }
125
126 #[inline]
127 pub fn writable(get_mut: impl for<'a> Fn(&'a mut Root) -> &'a mut Value + 'static) -> Self {
128 Self::Writable(Rc::new(get_mut))
129 }
130
131 #[inline]
132 pub fn failable_readable(
133 get: impl for<'a> Fn(&'a Root) -> Option<&'a Value> + 'static,
134 ) -> Self {
135 Self::FailableReadable(Rc::new(get))
136 }
137
138 #[inline]
139 pub fn failable_writable(
140 get_mut: impl for<'a> Fn(&'a mut Root) -> Option<&'a mut Value> + 'static,
141 ) -> Self {
142 Self::FailableWritable(Rc::new(get_mut))
143 }
144
145 #[inline]
146 pub fn readable_enum(
147 embed: impl Fn(Value) -> Root + 'static,
148 extract: impl for<'a> Fn(&'a Root) -> Option<&'a Value> + 'static,
149 ) -> Self {
150 Self::ReadableEnum {
151 extract: Rc::new(extract),
152 embed: Rc::new(embed),
153 }
154 }
155
156 #[inline]
157 pub fn writable_enum(
158 embed: impl Fn(Value) -> Root + 'static,
159 extract: impl for<'a> Fn(&'a Root) -> Option<&'a Value> + 'static,
160 extract_mut: impl for<'a> Fn(&'a mut Root) -> Option<&'a mut Value> + 'static,
161 ) -> Self {
162 Self::WritableEnum {
163 extract: Rc::new(extract),
164 embed: Rc::new(embed),
165 extract_mut: Rc::new(extract_mut),
166 }
167 }
168
169
170 #[inline]
172 pub fn owned(get: impl Fn(Root) -> Value + 'static) -> Self {
173 Self::Owned(Rc::new(get))
174 }
175
176 #[inline]
177 pub fn failable_owned(get: impl Fn(Root) -> Option<Value> + 'static) -> Self {
178 Self::FailableOwned(Rc::new(get))
179 }
180
181 #[inline]
182 pub fn owned_writable(get: impl Fn(Root) -> Value + 'static) -> Self {
183 Self::Owned(Rc::new(get))
184 }
185
186 #[inline]
187 pub fn failable_owned_writable(get: impl Fn(Root) -> Option<Value> + 'static) -> Self {
188 Self::FailableOwned(Rc::new(get))
189 }
190}
191
192impl<Root, Value> KeyPaths<Root, Value> {
193 #[inline]
195 pub fn get<'a>(&'a self, root: &'a Root) -> Option<&'a Value> {
196 match self {
197 KeyPaths::Readable(f) => Some(f(root)),
198 KeyPaths::Writable(_) => None, KeyPaths::FailableReadable(f) => f(root),
200 KeyPaths::FailableWritable(_) => None, KeyPaths::ReadableEnum { extract, .. } => extract(root),
202 KeyPaths::WritableEnum { extract, .. } => extract(root),
203 KeyPaths::Owned(_) => None, KeyPaths::FailableOwned(_) => None, }
207 }
208
209 #[inline]
212 pub fn get_ref<'a, 'b>(&'a self, root: &'b &Root) -> Option<&'b Value>
213 where
214 'a: 'b,
215 {
216 self.get(*root)
217 }
218
219 #[inline]
221 pub fn get_mut<'a>(&'a self, root: &'a mut Root) -> Option<&'a mut Value> {
222 match self {
223 KeyPaths::Readable(_) => None, KeyPaths::Writable(f) => Some(f(root)),
225 KeyPaths::FailableReadable(_) => None, KeyPaths::FailableWritable(f) => f(root),
227 KeyPaths::ReadableEnum { .. } => None, KeyPaths::WritableEnum { extract_mut, .. } => extract_mut(root),
229 KeyPaths::Owned(_) => None, KeyPaths::FailableOwned(_) => None, }
233 }
234
235 #[inline]
238 pub fn get_mut_ref<'a, 'b>(&'a self, root: &'b mut &mut Root) -> Option<&'b mut Value>
239 where
240 'a: 'b,
241 {
242 self.get_mut(*root)
243 }
244
245 #[inline]
252 pub fn for_arc(self) -> KeyPaths<Arc<Root>, Value>
253 where
254 Root: 'static,
255 Value: 'static,
256 {
257 match self {
258 KeyPaths::Readable(f) => KeyPaths::Readable(Rc::new(move |root: &Arc<Root>| {
259 f(&**root)
260 })),
261 KeyPaths::Writable(_) => {
262 panic!("Cannot create writable keypath for Arc (Arc is immutable)")
264 }
265 KeyPaths::FailableReadable(f) => {
266 KeyPaths::FailableReadable(Rc::new(move |root: &Arc<Root>| f(&**root)))
267 }
268 KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
269 extract: Rc::new(move |root: &Arc<Root>| extract(&**root)),
270 embed: Rc::new(move |value| Arc::new(embed(value))),
271 },
272 other => panic!("Unsupported keypath variant for Arc adapter: {:?}", kind_name(&other)),
273 }
274 }
275
276 #[inline]
279 pub fn for_box(self) -> KeyPaths<Box<Root>, Value>
280 where
281 Root: 'static,
282 Value: 'static,
283 {
284 match self {
285 KeyPaths::Readable(f) => KeyPaths::Readable(Rc::new(move |root: &Box<Root>| {
286 f(&**root)
287 })),
288 KeyPaths::Writable(f) => KeyPaths::Writable(Rc::new(move |root: &mut Box<Root>| {
289 f(&mut **root)
290 })),
291 KeyPaths::FailableReadable(f) => {
292 KeyPaths::FailableReadable(Rc::new(move |root: &Box<Root>| f(&**root)))
293 }
294 KeyPaths::FailableWritable(f) => {
295 KeyPaths::FailableWritable(Rc::new(move |root: &mut Box<Root>| f(&mut **root)))
296 }
297 KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
298 extract: Rc::new(move |root: &Box<Root>| extract(&**root)),
299 embed: Rc::new(move |value| Box::new(embed(value))),
300 },
301 KeyPaths::WritableEnum { extract, extract_mut, embed } => KeyPaths::WritableEnum {
302 extract: Rc::new(move |root: &Box<Root>| extract(&**root)),
303 extract_mut: Rc::new(move |root: &mut Box<Root>| extract_mut(&mut **root)),
304 embed: Rc::new(move |value| Box::new(embed(value))),
305 },
306 other => panic!("Unsupported keypath variant for Box adapter: {:?}", kind_name(&other)),
307 }
308 }
309
310 #[inline]
313 pub fn for_rc(self) -> KeyPaths<Rc<Root>, Value>
314 where
315 Root: 'static,
316 Value: 'static,
317 {
318 match self {
319 KeyPaths::Readable(f) => KeyPaths::Readable(Rc::new(move |root: &Rc<Root>| {
320 f(&**root)
321 })),
322 KeyPaths::Writable(_) => {
323 panic!("Cannot create writable keypath for Rc (Rc is immutable)")
325 }
326 KeyPaths::FailableReadable(f) => {
327 KeyPaths::FailableReadable(Rc::new(move |root: &Rc<Root>| f(&**root)))
328 }
329 KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
330 extract: Rc::new(move |root: &Rc<Root>| extract(&**root)),
331 embed: Rc::new(move |value| Rc::new(embed(value))),
332 },
333 other => panic!("Unsupported keypath variant for Rc adapter: {:?}", kind_name(&other)),
334 }
335 }
336
337 #[inline]
341 pub fn for_result<E>(self) -> KeyPaths<Result<Root, E>, Value>
342 where
343 Root: 'static,
344 Value: 'static,
345 E: 'static,
346 {
347 match self {
348 KeyPaths::Readable(f) => KeyPaths::FailableReadable(Rc::new(move |root: &Result<Root, E>| {
349 root.as_ref().ok().map(|r| f(r))
350 })),
351 KeyPaths::Writable(f) => KeyPaths::FailableWritable(Rc::new(move |root: &mut Result<Root, E>| {
352 root.as_mut().ok().map(|r| f(r))
353 })),
354 KeyPaths::FailableReadable(f) => {
355 KeyPaths::FailableReadable(Rc::new(move |root: &Result<Root, E>| {
356 root.as_ref().ok().and_then(|r| f(r))
357 }))
358 }
359 KeyPaths::FailableWritable(f) => {
360 KeyPaths::FailableWritable(Rc::new(move |root: &mut Result<Root, E>| {
361 root.as_mut().ok().and_then(|r| f(r))
362 }))
363 }
364 KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
365 extract: Rc::new(move |root: &Result<Root, E>| {
366 root.as_ref().ok().and_then(|r| extract(r))
367 }),
368 embed: Rc::new(move |value| Ok(embed(value))),
369 },
370 KeyPaths::WritableEnum { extract, extract_mut, embed } => KeyPaths::WritableEnum {
371 extract: Rc::new(move |root: &Result<Root, E>| {
372 root.as_ref().ok().and_then(|r| extract(r))
373 }),
374 extract_mut: Rc::new(move |root: &mut Result<Root, E>| {
375 root.as_mut().ok().and_then(|r| extract_mut(r))
376 }),
377 embed: Rc::new(move |value| Ok(embed(value))),
378 },
379 other => panic!("Unsupported keypath variant for Result adapter: {:?}", kind_name(&other)),
380 }
381 }
382
383 #[inline]
387 pub fn for_option(self) -> KeyPaths<Option<Root>, Value>
388 where
389 Root: 'static,
390 Value: 'static,
391 {
392 match self {
393 KeyPaths::Readable(f) => KeyPaths::FailableReadable(Rc::new(move |root: &Option<Root>| {
394 root.as_ref().map(|r| f(r))
395 })),
396 KeyPaths::Writable(f) => KeyPaths::FailableWritable(Rc::new(move |root: &mut Option<Root>| {
397 root.as_mut().map(|r| f(r))
398 })),
399 KeyPaths::FailableReadable(f) => {
400 KeyPaths::FailableReadable(Rc::new(move |root: &Option<Root>| {
401 root.as_ref().and_then(|r| f(r))
402 }))
403 }
404 KeyPaths::FailableWritable(f) => {
405 KeyPaths::FailableWritable(Rc::new(move |root: &mut Option<Root>| {
406 root.as_mut().and_then(|r| f(r))
407 }))
408 }
409 KeyPaths::ReadableEnum { extract, embed } => KeyPaths::ReadableEnum {
410 extract: Rc::new(move |root: &Option<Root>| {
411 root.as_ref().and_then(|r| extract(r))
412 }),
413 embed: Rc::new(move |value| Some(embed(value))),
414 },
415 KeyPaths::WritableEnum { extract, extract_mut, embed } => KeyPaths::WritableEnum {
416 extract: Rc::new(move |root: &Option<Root>| {
417 root.as_ref().and_then(|r| extract(r))
418 }),
419 extract_mut: Rc::new(move |root: &mut Option<Root>| {
420 root.as_mut().and_then(|r| extract_mut(r))
421 }),
422 embed: Rc::new(move |value| Some(embed(value))),
423 },
424 other => panic!("Unsupported keypath variant for Option adapter: {:?}", kind_name(&other)),
425 }
426 }
427
428 pub fn embed(&self, value: Value) -> Option<Root>
432 where
433 Value: Clone,
434 {
435 match self {
436 KeyPaths::ReadableEnum { embed, .. } => Some(embed(value)),
437 _ => None,
438 }
439 }
440
441 pub fn embed_mut(&self, value: Value) -> Option<Root>
442 where
443 Value: Clone,
444 {
445 match self {
446 KeyPaths::WritableEnum { embed, .. } => Some(embed(value)),
447 _ => None,
448 }
449 }
450
451
452 #[inline]
456 pub fn get_owned(self, root: Root) -> Value {
457 match self {
458 KeyPaths::Owned(f) => f(root),
459 _ => panic!("get_owned only works with owned keypaths"),
460 }
461 }
462
463 #[inline]
465 pub fn get_failable_owned(self, root: Root) -> Option<Value> {
466 match self {
467 KeyPaths::FailableOwned(f) => f(root),
468 _ => panic!("get_failable_owned only works with failable owned keypaths"),
469 }
470 }
471
472 pub fn iter<'a, T>(&'a self, root: &'a Root) -> Option<<&'a Value as IntoIterator>::IntoIter>
474 where
475 &'a Value: IntoIterator<Item = &'a T>,
476 T: 'a,
477 {
478 self.get(root).map(|v| v.into_iter())
479 }
480
481 pub fn iter_mut<'a, T>(
483 &'a self,
484 root: &'a mut Root,
485 ) -> Option<<&'a mut Value as IntoIterator>::IntoIter>
486 where
487 &'a mut Value: IntoIterator<Item = &'a mut T>,
488 T: 'a,
489 {
490 self.get_mut(root).map(|v| v.into_iter())
491 }
492
493 #[inline]
495 pub fn into_iter<T>(self, root: Root) -> Option<<Value as IntoIterator>::IntoIter>
496 where
497 Value: IntoIterator<Item = T> + Clone,
498 {
499 match self {
500 KeyPaths::Readable(f) => Some(f(&root).clone().into_iter()), KeyPaths::Writable(_) => None,
502 KeyPaths::FailableReadable(f) => f(&root).map(|v| v.clone().into_iter()),
503 KeyPaths::FailableWritable(_) => None,
504 KeyPaths::ReadableEnum { extract, .. } => extract(&root).map(|v| v.clone().into_iter()),
505 KeyPaths::WritableEnum { extract, .. } => extract(&root).map(|v| v.clone().into_iter()),
506 KeyPaths::Owned(f) => Some(f(root).into_iter()),
508 KeyPaths::FailableOwned(f) => f(root).map(|v| v.into_iter()),
509 }
510 }
511}
512
513impl<Root, Value> WithContainer<Root, Value> for KeyPaths<Root, Value> {
515 #[inline]
518 fn with_arc<F, R>(self, arc: &Arc<Root>, f: F) -> R
519 where
520 F: FnOnce(&Value) -> R,
521 {
522 match self {
523 KeyPaths::Readable(get) => f(get(&**arc)),
524 KeyPaths::FailableReadable(get) => {
525 if let Some(value) = get(&**arc) {
526 f(value)
527 } else {
528 panic!("FailableReadable keypath returned None for Arc")
529 }
530 }
531 _ => panic!("with_arc only works with readable keypaths"),
532 }
533 }
534
535 #[inline]
538 fn with_box<F, R>(self, boxed: &Box<Root>, f: F) -> R
539 where
540 F: FnOnce(&Value) -> R,
541 {
542 match self {
543 KeyPaths::Readable(get) => f(get(&**boxed)),
544 KeyPaths::FailableReadable(get) => {
545 if let Some(value) = get(&**boxed) {
546 f(value)
547 } else {
548 panic!("FailableReadable keypath returned None for Box")
549 }
550 }
551 _ => panic!("with_box only works with readable keypaths"),
552 }
553 }
554
555 #[inline]
558 fn with_box_mut<F, R>(self, boxed: &mut Box<Root>, f: F) -> R
559 where
560 F: FnOnce(&mut Value) -> R,
561 {
562 match self {
563 KeyPaths::Writable(get) => f(get(&mut **boxed)),
564 KeyPaths::FailableWritable(get) => {
565 if let Some(value) = get(&mut **boxed) {
566 f(value)
567 } else {
568 panic!("FailableWritable keypath returned None for Box")
569 }
570 }
571 _ => panic!("with_box_mut only works with writable keypaths"),
572 }
573 }
574
575 #[inline]
578 fn with_rc<F, R>(self, rc: &Rc<Root>, f: F) -> R
579 where
580 F: FnOnce(&Value) -> R,
581 {
582 match self {
583 KeyPaths::Readable(get) => f(get(&**rc)),
584 KeyPaths::FailableReadable(get) => {
585 if let Some(value) = get(&**rc) {
586 f(value)
587 } else {
588 panic!("FailableReadable keypath returned None for Rc")
589 }
590 }
591 _ => panic!("with_rc only works with readable keypaths"),
592 }
593 }
594
595 #[inline]
598 fn with_result<F, R, E>(self, result: &Result<Root, E>, f: F) -> Option<R>
599 where
600 F: FnOnce(&Value) -> R,
601 {
602 match self {
603 KeyPaths::Readable(get) => {
604 result.as_ref().ok().map(|root| f(get(root)))
605 }
606 KeyPaths::FailableReadable(get) => {
607 result.as_ref().ok().and_then(|root| get(root).map(|v| f(v)))
608 }
609 _ => panic!("with_result only works with readable keypaths"),
610 }
611 }
612
613 #[inline]
616 fn with_result_mut<F, R, E>(self, result: &mut Result<Root, E>, f: F) -> Option<R>
617 where
618 F: FnOnce(&mut Value) -> R,
619 {
620 match self {
621 KeyPaths::Writable(get) => {
622 result.as_mut().ok().map(|root| f(get(root)))
623 }
624 KeyPaths::FailableWritable(get) => {
625 result.as_mut().ok().and_then(|root| get(root).map(|v| f(v)))
626 }
627 _ => panic!("with_result_mut only works with writable keypaths"),
628 }
629 }
630
631 #[inline]
634 fn with_option<F, R>(self, option: &Option<Root>, f: F) -> Option<R>
635 where
636 F: FnOnce(&Value) -> R,
637 {
638 match self {
639 KeyPaths::Readable(get) => {
640 option.as_ref().map(|root| f(get(root)))
641 }
642 KeyPaths::FailableReadable(get) => {
643 option.as_ref().and_then(|root| get(root).map(|v| f(v)))
644 }
645 _ => panic!("with_option only works with readable keypaths"),
646 }
647 }
648
649 #[inline]
652 fn with_option_mut<F, R>(self, option: &mut Option<Root>, f: F) -> Option<R>
653 where
654 F: FnOnce(&mut Value) -> R,
655 {
656 match self {
657 KeyPaths::Writable(get) => {
658 option.as_mut().map(|root| f(get(root)))
659 }
660 KeyPaths::FailableWritable(get) => {
661 option.as_mut().and_then(|root| get(root).map(|v| f(v)))
662 }
663 _ => panic!("with_option_mut only works with writable keypaths"),
664 }
665 }
666
667 #[inline]
670 fn with_refcell<F, R>(self, refcell: &RefCell<Root>, f: F) -> Option<R>
671 where
672 F: FnOnce(&Value) -> R,
673 {
674 match self {
675 KeyPaths::Readable(get) => {
676 refcell.try_borrow().ok().map(|borrow| f(get(&*borrow)))
677 }
678 KeyPaths::FailableReadable(get) => {
679 refcell.try_borrow().ok().and_then(|borrow| get(&*borrow).map(|v| f(v)))
680 }
681 _ => panic!("with_refcell only works with readable keypaths"),
682 }
683 }
684
685 #[inline]
688 fn with_refcell_mut<F, R>(self, refcell: &RefCell<Root>, f: F) -> Option<R>
689 where
690 F: FnOnce(&mut Value) -> R,
691 {
692 match self {
693 KeyPaths::Writable(get) => {
694 refcell.try_borrow_mut().ok().map(|mut borrow| f(get(&mut *borrow)))
695 }
696 KeyPaths::FailableWritable(get) => {
697 refcell.try_borrow_mut().ok().and_then(|mut borrow| get(&mut *borrow).map(|v| f(v)))
698 }
699 _ => panic!("with_refcell_mut only works with writable keypaths"),
700 }
701 }
702
703 #[inline]
706 fn with_mutex<F, R>(self, mutex: &Mutex<Root>, f: F) -> Option<R>
707 where
708 F: FnOnce(&Value) -> R,
709 {
710 match self {
711 KeyPaths::Readable(get) => {
712 mutex.try_lock().ok().map(|guard| f(get(&*guard)))
713 }
714 KeyPaths::FailableReadable(get) => {
715 mutex.try_lock().ok().and_then(|guard| get(&*guard).map(|v| f(v)))
716 }
717 _ => panic!("with_mutex only works with readable keypaths"),
718 }
719 }
720
721 #[inline]
724 fn with_mutex_mut<F, R>(self, mutex: &mut Mutex<Root>, f: F) -> Option<R>
725 where
726 F: FnOnce(&mut Value) -> R,
727 {
728 match self {
729 KeyPaths::Writable(get) => {
730 mutex.try_lock().ok().map(|mut guard| f(get(&mut *guard)))
731 }
732 KeyPaths::FailableWritable(get) => {
733 mutex.try_lock().ok().and_then(|mut guard| get(&mut *guard).map(|v| f(v)))
734 }
735 _ => panic!("with_mutex_mut only works with writable keypaths"),
736 }
737 }
738
739 #[inline]
742 fn with_rwlock<F, R>(self, rwlock: &RwLock<Root>, f: F) -> Option<R>
743 where
744 F: FnOnce(&Value) -> R,
745 {
746 match self {
747 KeyPaths::Readable(get) => {
748 rwlock.try_read().ok().map(|guard| f(get(&*guard)))
749 }
750 KeyPaths::FailableReadable(get) => {
751 rwlock.try_read().ok().and_then(|guard| get(&*guard).map(|v| f(v)))
752 }
753 _ => panic!("with_rwlock only works with readable keypaths"),
754 }
755 }
756
757 #[inline]
760 fn with_rwlock_mut<F, R>(self, rwlock: &mut RwLock<Root>, f: F) -> Option<R>
761 where
762 F: FnOnce(&mut Value) -> R,
763 {
764 match self {
765 KeyPaths::Writable(get) => {
766 rwlock.try_write().ok().map(|mut guard| f(get(&mut *guard)))
767 }
768 KeyPaths::FailableWritable(get) => {
769 rwlock.try_write().ok().and_then(|mut guard| get(&mut *guard).map(|v| f(v)))
770 }
771 _ => panic!("with_rwlock_mut only works with writable keypaths"),
772 }
773 }
774}
775
776impl<Root, Mid> KeyPaths<Root, Mid>
777where
778 Root: 'static,
779 Mid: 'static,
780{
781 #[inline]
783 pub fn then<Value>(self, mid: KeyPaths<Mid, Value>) -> KeyPaths<Root, Value>
784 where
785 Value: 'static,
786 {
787 self.compose(mid)
788 }
789
790 pub fn compose<Value>(self, mid: KeyPaths<Mid, Value>) -> KeyPaths<Root, Value>
791 where
792 Value: 'static,
793 {
794 use KeyPaths::*;
795
796 match (self, mid) {
797 (Readable(f1), Readable(f2)) => Readable(Rc::new(move |r| f2(f1(r)))),
798
799 (Writable(f1), Writable(f2)) => Writable(Rc::new(move |r| f2(f1(r)))),
800
801 (FailableReadable(f1), Readable(f2)) => {
802 FailableReadable(Rc::new(move |r| f1(r).map(|m| f2(m))))
803 }
804
805 (Readable(f1), FailableReadable(f2)) => FailableReadable(Rc::new(move |r| f2(f1(r)))),
806
807 (FailableReadable(f1), FailableReadable(f2)) => {
808 FailableReadable(Rc::new(move |r| f1(r).and_then(|m| f2(m))))
809 }
810
811 (FailableWritable(f1), Writable(f2)) => {
812 FailableWritable(Rc::new(move |r| f1(r).map(|m| f2(m))))
813 }
814
815 (Writable(f1), FailableWritable(f2)) => FailableWritable(Rc::new(move |r| f2(f1(r)))),
816
817 (FailableWritable(f1), FailableWritable(f2)) => {
818 FailableWritable(Rc::new(move |r| f1(r).and_then(|m| f2(m))))
819 }
820 (FailableReadable(f1), ReadableEnum { extract, .. }) => {
821 FailableReadable(Rc::new(move |r| f1(r).and_then(|m| extract(m))))
822 }
823 (ReadableEnum { extract, .. }, Readable(f2)) => {
827 FailableReadable(Rc::new(move |r| extract(r).map(|m| f2(m))))
828 }
829
830 (ReadableEnum { extract, .. }, FailableReadable(f2)) => {
831 FailableReadable(Rc::new(move |r| extract(r).and_then(|m| f2(m))))
832 }
833
834 (WritableEnum { extract, .. }, Readable(f2)) => {
835 FailableReadable(Rc::new(move |r| extract(r).map(|m| f2(m))))
836 }
837
838 (WritableEnum { extract, .. }, FailableReadable(f2)) => {
839 FailableReadable(Rc::new(move |r| extract(r).and_then(|m| f2(m))))
840 }
841
842 (WritableEnum { extract_mut, .. }, Writable(f2)) => {
843 FailableWritable(Rc::new(move |r| extract_mut(r).map(|m| f2(m))))
844 }
845
846 (
847 FailableWritable(f_root_mid),
848 WritableEnum {
849 extract_mut: exm_mid_val,
850 ..
851 },
852 ) => {
853 FailableWritable(Rc::new(move |r: &mut Root| {
854 let intermediate_mid_ref = f_root_mid(r);
857
858 intermediate_mid_ref.and_then(|intermediate_mid| exm_mid_val(intermediate_mid))
861 }))
862 }
863
864 (WritableEnum { extract_mut, .. }, FailableWritable(f2)) => {
865 FailableWritable(Rc::new(move |r| extract_mut(r).and_then(|m| f2(m))))
866 }
867
868 (Writable(f1), WritableEnum { extract_mut, .. }) => {
870 FailableWritable(Rc::new(move |r: &mut Root| {
871 let mid: &mut Mid = f1(r);
872 extract_mut(mid)
873 }))
874 }
875
876 (
877 ReadableEnum {
878 extract: ex1,
879 embed: em1,
880 },
881 ReadableEnum {
882 extract: ex2,
883 embed: em2,
884 },
885 ) => ReadableEnum {
886 extract: Rc::new(move |r| ex1(r).and_then(|m| ex2(m))),
887 embed: Rc::new(move |v| em1(em2(v))),
888 },
889
890 (
891 WritableEnum {
892 extract: ex1,
893 extract_mut: _,
894 embed: em1,
895 },
896 ReadableEnum {
897 extract: ex2,
898 embed: em2,
899 },
900 ) => ReadableEnum {
901 extract: Rc::new(move |r| ex1(r).and_then(|m| ex2(m))),
902 embed: Rc::new(move |v| em1(em2(v))),
903 },
904
905 (
906 WritableEnum {
907 extract: ex1,
908 extract_mut: exm1,
909 embed: em1,
910 },
911 WritableEnum {
912 extract: ex2,
913 extract_mut: exm2,
914 embed: em2,
915 },
916 ) => WritableEnum {
917 extract: Rc::new(move |r| ex1(r).and_then(|m| ex2(m))),
918 extract_mut: Rc::new(move |r| exm1(r).and_then(|m| exm2(m))),
919 embed: Rc::new(move |v| em1(em2(v))),
920 },
921
922
923 (Owned(f1), Owned(f2)) => {
925 Owned(Rc::new(move |r| f2(f1(r))))
926 }
927 (FailableOwned(f1), Owned(f2)) => {
928 FailableOwned(Rc::new(move |r| f1(r).map(|m| f2(m))))
929 }
930 (Owned(f1), FailableOwned(f2)) => {
931 FailableOwned(Rc::new(move |r| f2(f1(r))))
932 }
933 (FailableOwned(f1), FailableOwned(f2)) => {
934 FailableOwned(Rc::new(move |r| f1(r).and_then(|m| f2(m))))
935 }
936
937 (a, b) => panic!(
942 "Unsupported composition: {:?} then {:?}",
943 kind_name(&a),
944 kind_name(&b)
945 ),
946 }
947 }
948
949 #[inline]
951 pub fn kind_name(&self) -> &'static str {
952 kind_name(self)
953 }
954}
955
956fn kind_name<Root, Value>(k: &KeyPaths<Root, Value>) -> &'static str {
957 use KeyPaths::*;
958 match k {
959 Readable(_) => "Readable",
960 Writable(_) => "Writable",
961 FailableReadable(_) => "FailableReadable",
962 FailableWritable(_) => "FailableWritable",
963 ReadableEnum { .. } => "ReadableEnum",
964 WritableEnum { .. } => "WritableEnum",
965 Owned(_) => "Owned",
967 FailableOwned(_) => "FailableOwned",
968 }
969}
970
971pub fn compose<Root, Mid, Value>(
980 kp1: KeyPaths<Root, Mid>,
981 kp2: KeyPaths<Mid, Value>,
982) -> KeyPaths<Root, Value>
983where
984 Root: 'static,
985 Mid: 'static,
986 Value: 'static,
987{
988 kp1.compose(kp2)
989}
990
991#[macro_export]
994macro_rules! readable_enum_macro {
995 ($enum:path, $variant:ident) => {{
997 $crate::KeyPaths::readable_enum(
998 |_| <$enum>::$variant,
999 |e: &$enum| match e {
1000 <$enum>::$variant => Some(&()),
1001 _ => None,
1002 },
1003 )
1004 }};
1005 ($enum:path, $variant:ident($inner:ty)) => {{
1007 $crate::KeyPaths::readable_enum(
1008 |v: $inner| <$enum>::$variant(v),
1009 |e: &$enum| match e {
1010 <$enum>::$variant(v) => Some(v),
1011 _ => None,
1012 },
1013 )
1014 }};
1015}
1016
1017#[macro_export]
1018macro_rules! writable_enum_macro {
1019 ($enum:path, $variant:ident) => {{
1021 $crate::KeyPaths::writable_enum(
1022 |_| <$enum>::$variant,
1023 |e: &$enum| match e {
1024 <$enum>::$variant => Some(&()),
1025 _ => None,
1026 },
1027 |e: &mut $enum| match e {
1028 <$enum>::$variant => Some(&mut ()),
1029 _ => None,
1030 },
1031 )
1032 }};
1033 ($enum:path, $variant:ident($inner:ty)) => {{
1035 $crate::KeyPaths::writable_enum(
1036 |v: $inner| <$enum>::$variant(v),
1037 |e: &$enum| match e {
1038 <$enum>::$variant(v) => Some(v),
1039 _ => None,
1040 },
1041 |e: &mut $enum| match e {
1042 <$enum>::$variant(v) => Some(v),
1043 _ => None,
1044 },
1045 )
1046 }};
1047}