concoct/view/
one_of.rs

1use crate::{Tree, View};
2use std::any::Any;
3
4macro_rules! one_of {
5    ($name:tt, $($t:tt),*) => {
6        /// Container view for children of multiple types.
7        pub enum $name<$($t),*> {
8            $($t($t)),*
9        }
10
11        impl<$($t: View),*> View for $name<$($t),*> {
12            fn into_tree(self) -> impl Tree {
13                match self {
14                    $(
15                        $name::$t(body) => $name::$t(body.into_tree()),
16                    )*
17                }
18            }
19        }
20
21        impl<$($t: Tree),*> Tree for $name<$($t),*> {
22            unsafe fn build(&mut self) {
23                match self {
24                    $(
25                        $name::$t(tree) => tree.build(),
26                    )*
27                }
28            }
29
30            unsafe fn rebuild(&mut self, last: &mut dyn Any, is_changed: bool) {
31                let last =  last.downcast_mut::<Self>().unwrap();
32                match (self, last) {
33                    $(
34                        ($name::$t(tree), $name::$t(last_tree)) => {
35                            tree.rebuild(last_tree, is_changed)
36                        }
37                    ),*
38                    (me, last) => {
39                        last.remove();
40                        me.build();
41                    }
42                }
43
44            }
45
46            unsafe fn remove(&mut self) {
47                match self {
48                    $(
49                        $name::$t(tree) => tree.remove(),
50                    )*
51                }
52            }
53        }
54    };
55}
56
57one_of!(OneOf2, A, B);
58one_of!(OneOf3, A, B, C);
59one_of!(OneOf4, A, B, C, D);
60one_of!(OneOf5, A, B, C, D, E);
61one_of!(OneOf6, A, B, C, D, E, F);
62one_of!(OneOf7, A, B, C, D, E, F, G);
63one_of!(OneOf8, A, B, C, D, E, F, G, H);