dyn_clone/
macros.rs

1/// Implement the standard library `Clone` for a trait object that has
2/// `DynClone` as a supertrait.
3///
4/// ```
5/// use dyn_clone::DynClone;
6///
7/// trait MyTrait: DynClone {
8///     /* ... */
9/// }
10///
11/// dyn_clone::clone_trait_object!(MyTrait);
12///
13/// // Now data structures containing Box<dyn MyTrait> can derive Clone.
14/// #[derive(Clone)]
15/// struct Container {
16///     trait_object: Box<dyn MyTrait>,
17/// }
18/// ```
19///
20/// The macro supports traits that have type parameters and/or `where` clauses.
21///
22/// ```
23/// use dyn_clone::DynClone;
24/// use std::io::Read;
25///
26/// trait Difficult<R>: DynClone where R: Read {
27///     /* ... */
28/// }
29///
30/// dyn_clone::clone_trait_object!(<R> Difficult<R> where R: Read);
31/// ```
32#[macro_export]
33macro_rules! clone_trait_object {
34    ($($path:tt)+) => {
35        $crate::__internal_clone_trait_object!(begin $($path)+);
36    };
37}
38
39#[doc(hidden)]
40#[macro_export]
41macro_rules! __internal_clone_trait_object {
42    // Invocation started with `<`, parse generics.
43    (begin < $($rest:tt)*) => {
44        $crate::__internal_clone_trait_object!(generics () () $($rest)*);
45    };
46
47    // Invocation did not start with `<`.
48    (begin $first:tt $($rest:tt)*) => {
49        $crate::__internal_clone_trait_object!(path () ($first) $($rest)*);
50    };
51
52    // End of generics.
53    (generics ($($generics:tt)*) () > $($rest:tt)*) => {
54        $crate::__internal_clone_trait_object!(path ($($generics)*) () $($rest)*);
55    };
56
57    // Generics open bracket.
58    (generics ($($generics:tt)*) ($($brackets:tt)*) < $($rest:tt)*) => {
59        $crate::__internal_clone_trait_object!(generics ($($generics)* <) ($($brackets)* <) $($rest)*);
60    };
61
62    // Generics close bracket.
63    (generics ($($generics:tt)*) (< $($brackets:tt)*) > $($rest:tt)*) => {
64        $crate::__internal_clone_trait_object!(generics ($($generics)* >) ($($brackets)*) $($rest)*);
65    };
66
67    // Token inside of generics.
68    (generics ($($generics:tt)*) ($($brackets:tt)*) $first:tt $($rest:tt)*) => {
69        $crate::__internal_clone_trait_object!(generics ($($generics)* $first) ($($brackets)*) $($rest)*);
70    };
71
72    // End with `where` clause.
73    (path ($($generics:tt)*) ($($path:tt)*) where $($rest:tt)*) => {
74        $crate::__internal_clone_trait_object!(impl ($($generics)*) ($($path)*) ($($rest)*));
75    };
76
77    // End without `where` clause.
78    (path ($($generics:tt)*) ($($path:tt)*)) => {
79        $crate::__internal_clone_trait_object!(impl ($($generics)*) ($($path)*) ());
80    };
81
82    // Token inside of path.
83    (path ($($generics:tt)*) ($($path:tt)*) $first:tt $($rest:tt)*) => {
84        $crate::__internal_clone_trait_object!(path ($($generics)*) ($($path)* $first) $($rest)*);
85    };
86
87    // The impl.
88    (impl ($($generics:tt)*) ($($path:tt)*) ($($bound:tt)*)) => {
89        impl<'clone, $($generics)*> $crate::private::Clone for $crate::private::Box<dyn $($path)* + 'clone> where $($bound)* {
90            fn clone(&self) -> Self {
91                $crate::clone_box(&**self)
92            }
93        }
94        impl<'clone, $($generics)*> $crate::private::Clone for $crate::private::Box<dyn $($path)* + $crate::private::Send + 'clone> where $($bound)* {
95            fn clone(&self) -> Self {
96                $crate::clone_box(&**self)
97            }
98        }
99        impl<'clone, $($generics)*> $crate::private::Clone for $crate::private::Box<dyn $($path)* + $crate::private::Sync + 'clone> where $($bound)* {
100            fn clone(&self) -> Self {
101                $crate::clone_box(&**self)
102            }
103        }
104        impl<'clone, $($generics)*> $crate::private::Clone for $crate::private::Box<dyn $($path)* + $crate::private::Send + $crate::private::Sync + 'clone> where $($bound)* {
105            fn clone(&self) -> Self {
106                $crate::clone_box(&**self)
107            }
108        }
109    };
110}