dyn_clone/
macros.rs

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